2018-06-05 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / fortran / trans-intrinsic.c
blobd306e3a5a6209c1621d91f99ffc366acecd9c3d0
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, true) == 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 bool has_vector = gfc_has_vector_subscript (lhs_expr);
1912 if (gfc_is_coindexed (lhs_expr) || !has_vector)
1914 /* If has_vector, pass descriptor for whole array and the
1915 vector bounds separately. */
1916 gfc_array_ref *ar, ar2;
1917 bool has_tmp_lhs_array = false;
1918 if (has_vector)
1920 has_tmp_lhs_array = true;
1921 ar = gfc_find_array_ref (lhs_expr);
1922 ar2 = *ar;
1923 memset (ar, '\0', sizeof (*ar));
1924 ar->as = ar2.as;
1925 ar->type = AR_FULL;
1927 lhs_se.want_pointer = 1;
1928 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1929 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but
1930 that has the wrong type if component references are done. */
1931 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1932 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1933 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1934 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1935 : lhs_expr->rank,
1936 lhs_type));
1937 if (has_tmp_lhs_array)
1939 vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
1940 *ar = ar2;
1943 else
1945 /* Special casing for arr1 ([...]) = arr2[...], i.e. caf_get to
1946 indexed array expression. This is rewritten to:
1948 tmp_array = arr2[...]
1949 arr1 ([...]) = tmp_array
1951 because using the standard gfc_conv_expr (lhs_expr) did the
1952 assignment with lhs and rhs exchanged. */
1954 gfc_ss *lss_for_tmparray, *lss_real;
1955 gfc_loopinfo loop;
1956 gfc_se se;
1957 stmtblock_t body;
1958 tree tmparr_desc, src;
1959 tree index = gfc_index_zero_node;
1960 tree stride = gfc_index_zero_node;
1961 int n;
1963 /* Walk both sides of the assignment, once to get the shape of the
1964 temporary array to create right. */
1965 lss_for_tmparray = gfc_walk_expr (lhs_expr);
1966 /* And a second time to be able to create an assignment of the
1967 temporary to the lhs_expr. gfc_trans_create_temp_array replaces
1968 the tree in the descriptor with the one for the temporary
1969 array. */
1970 lss_real = gfc_walk_expr (lhs_expr);
1971 gfc_init_loopinfo (&loop);
1972 gfc_add_ss_to_loop (&loop, lss_for_tmparray);
1973 gfc_add_ss_to_loop (&loop, lss_real);
1974 gfc_conv_ss_startstride (&loop);
1975 gfc_conv_loop_setup (&loop, &lhs_expr->where);
1976 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1977 gfc_trans_create_temp_array (&lhs_se.pre, &lhs_se.post,
1978 lss_for_tmparray, lhs_type, NULL_TREE,
1979 false, true, false,
1980 &lhs_expr->where);
1981 tmparr_desc = lss_for_tmparray->info->data.array.descriptor;
1982 gfc_start_scalarized_body (&loop, &body);
1983 gfc_init_se (&se, NULL);
1984 gfc_copy_loopinfo_to_se (&se, &loop);
1985 se.ss = lss_real;
1986 gfc_conv_expr (&se, lhs_expr);
1987 gfc_add_block_to_block (&body, &se.pre);
1989 /* Walk over all indexes of the loop. */
1990 for (n = loop.dimen - 1; n > 0; --n)
1992 tmp = loop.loopvar[n];
1993 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1994 gfc_array_index_type, tmp, loop.from[n]);
1995 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1996 gfc_array_index_type, tmp, index);
1998 stride = fold_build2_loc (input_location, MINUS_EXPR,
1999 gfc_array_index_type,
2000 loop.to[n - 1], loop.from[n - 1]);
2001 stride = fold_build2_loc (input_location, PLUS_EXPR,
2002 gfc_array_index_type,
2003 stride, gfc_index_one_node);
2005 index = fold_build2_loc (input_location, MULT_EXPR,
2006 gfc_array_index_type, tmp, stride);
2009 index = fold_build2_loc (input_location, MINUS_EXPR,
2010 gfc_array_index_type,
2011 index, loop.from[0]);
2013 index = fold_build2_loc (input_location, PLUS_EXPR,
2014 gfc_array_index_type,
2015 loop.loopvar[0], index);
2017 src = build_fold_indirect_ref (gfc_conv_array_data (tmparr_desc));
2018 src = gfc_build_array_ref (src, index, NULL);
2019 /* Now create the assignment of lhs_expr = tmp_array. */
2020 gfc_add_modify (&body, se.expr, src);
2021 gfc_add_block_to_block (&body, &se.post);
2022 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, tmparr_desc);
2023 gfc_trans_scalarizing_loops (&loop, &body);
2024 gfc_add_block_to_block (&loop.pre, &loop.post);
2025 gfc_add_expr_to_block (&lhs_se.post, gfc_finish_block (&loop.pre));
2026 gfc_free_ss (lss_for_tmparray);
2027 gfc_free_ss (lss_real);
2031 lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
2033 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
2034 temporary and a loop. */
2035 if (!gfc_is_coindexed (lhs_expr)
2036 && (!lhs_caf_attr.codimension
2037 || !(lhs_expr->rank > 0
2038 && (lhs_caf_attr.allocatable || lhs_caf_attr.pointer))))
2040 bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
2041 gcc_assert (gfc_is_coindexed (rhs_expr));
2042 gfc_init_se (&rhs_se, NULL);
2043 if (lhs_expr->rank == 0 && lhs_caf_attr.allocatable)
2045 gfc_se scal_se;
2046 gfc_init_se (&scal_se, NULL);
2047 scal_se.want_pointer = 1;
2048 gfc_conv_expr (&scal_se, lhs_expr);
2049 /* Ensure scalar on lhs is allocated. */
2050 gfc_add_block_to_block (&block, &scal_se.pre);
2052 gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
2053 TYPE_SIZE_UNIT (
2054 gfc_typenode_for_spec (&lhs_expr->ts)),
2055 NULL_TREE);
2056 tmp = fold_build2 (EQ_EXPR, logical_type_node, scal_se.expr,
2057 null_pointer_node);
2058 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2059 tmp, gfc_finish_block (&scal_se.pre),
2060 build_empty_stmt (input_location));
2061 gfc_add_expr_to_block (&block, tmp);
2063 else
2064 lhs_may_realloc = lhs_may_realloc
2065 && gfc_full_array_ref_p (lhs_expr->ref, NULL);
2066 gfc_add_block_to_block (&block, &lhs_se.pre);
2067 gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
2068 may_require_tmp, lhs_may_realloc,
2069 &rhs_caf_attr);
2070 gfc_add_block_to_block (&block, &rhs_se.pre);
2071 gfc_add_block_to_block (&block, &rhs_se.post);
2072 gfc_add_block_to_block (&block, &lhs_se.post);
2073 return gfc_finish_block (&block);
2076 gfc_add_block_to_block (&block, &lhs_se.pre);
2078 /* Obtain token, offset and image index for the LHS. */
2079 caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
2080 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2081 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2082 image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
2083 tmp = lhs_se.expr;
2084 if (lhs_caf_attr.alloc_comp)
2085 gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL_TREE,
2086 NULL);
2087 else
2088 gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
2089 lhs_expr);
2090 lhs_se.expr = tmp;
2092 /* RHS. */
2093 gfc_init_se (&rhs_se, NULL);
2094 if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
2095 && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
2096 rhs_expr = rhs_expr->value.function.actual->expr;
2097 if (rhs_expr->rank == 0)
2099 symbol_attribute attr;
2100 gfc_clear_attr (&attr);
2101 gfc_conv_expr (&rhs_se, rhs_expr);
2102 rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
2103 rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
2105 else if ((rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2106 && rhs_caf_attr.codimension)
2108 tree tmp2;
2109 rhs_se.want_pointer = 1;
2110 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2111 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2112 has the wrong type if component references are done. */
2113 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2114 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2115 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2116 gfc_get_dtype_rank_type (
2117 gfc_has_vector_subscript (rhs_expr)
2118 ? gfc_find_array_ref (rhs_expr)->dimen
2119 : rhs_expr->rank,
2120 tmp2));
2122 else
2124 /* If has_vector, pass descriptor for whole array and the
2125 vector bounds separately. */
2126 gfc_array_ref *ar, ar2;
2127 bool has_vector = false;
2128 tree tmp2;
2130 if (gfc_is_coindexed (rhs_expr) && gfc_has_vector_subscript (rhs_expr))
2132 has_vector = true;
2133 ar = gfc_find_array_ref (rhs_expr);
2134 ar2 = *ar;
2135 memset (ar, '\0', sizeof (*ar));
2136 ar->as = ar2.as;
2137 ar->type = AR_FULL;
2139 rhs_se.want_pointer = 1;
2140 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2141 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2142 has the wrong type if component references are done. */
2143 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2144 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2145 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2146 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2147 : rhs_expr->rank,
2148 tmp2));
2149 if (has_vector)
2151 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
2152 *ar = ar2;
2156 gfc_add_block_to_block (&block, &rhs_se.pre);
2158 rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
2160 tmp_stat = gfc_find_stat_co (lhs_expr);
2162 if (tmp_stat)
2164 gfc_se stat_se;
2165 gfc_init_se (&stat_se, NULL);
2166 gfc_conv_expr_reference (&stat_se, tmp_stat);
2167 dst_stat = stat_se.expr;
2168 gfc_add_block_to_block (&block, &stat_se.pre);
2169 gfc_add_block_to_block (&block, &stat_se.post);
2172 tmp_team = gfc_find_team_co (lhs_expr);
2174 if (tmp_team)
2176 gfc_se team_se;
2177 gfc_init_se (&team_se, NULL);
2178 gfc_conv_expr_reference (&team_se, tmp_team);
2179 dst_team = team_se.expr;
2180 gfc_add_block_to_block (&block, &team_se.pre);
2181 gfc_add_block_to_block (&block, &team_se.post);
2184 if (!gfc_is_coindexed (rhs_expr))
2186 if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
2188 tree reference, dst_realloc;
2189 reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2190 dst_realloc = lhs_caf_attr.allocatable ? boolean_true_node
2191 : boolean_false_node;
2192 tmp = build_call_expr_loc (input_location,
2193 gfor_fndecl_caf_send_by_ref,
2194 10, token, image_index, rhs_se.expr,
2195 reference, lhs_kind, rhs_kind,
2196 may_require_tmp, dst_realloc, src_stat,
2197 build_int_cst (integer_type_node,
2198 lhs_expr->ts.type));
2200 else
2201 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 11,
2202 token, offset, image_index, lhs_se.expr, vec,
2203 rhs_se.expr, lhs_kind, rhs_kind,
2204 may_require_tmp, src_stat, dst_team);
2206 else
2208 tree rhs_token, rhs_offset, rhs_image_index;
2210 /* It guarantees memory consistency within the same segment. */
2211 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2212 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2213 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2214 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2215 ASM_VOLATILE_P (tmp) = 1;
2216 gfc_add_expr_to_block (&block, tmp);
2218 caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
2219 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2220 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2221 rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
2222 tmp = rhs_se.expr;
2223 if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2225 tmp_stat = gfc_find_stat_co (lhs_expr);
2227 if (tmp_stat)
2229 gfc_se stat_se;
2230 gfc_init_se (&stat_se, NULL);
2231 gfc_conv_expr_reference (&stat_se, tmp_stat);
2232 src_stat = stat_se.expr;
2233 gfc_add_block_to_block (&block, &stat_se.pre);
2234 gfc_add_block_to_block (&block, &stat_se.post);
2237 gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL, caf_decl,
2238 NULL_TREE, NULL);
2239 tree lhs_reference, rhs_reference;
2240 lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2241 rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
2242 tmp = build_call_expr_loc (input_location,
2243 gfor_fndecl_caf_sendget_by_ref, 13,
2244 token, image_index, lhs_reference,
2245 rhs_token, rhs_image_index, rhs_reference,
2246 lhs_kind, rhs_kind, may_require_tmp,
2247 dst_stat, src_stat,
2248 build_int_cst (integer_type_node,
2249 lhs_expr->ts.type),
2250 build_int_cst (integer_type_node,
2251 rhs_expr->ts.type));
2253 else
2255 gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
2256 tmp, rhs_expr);
2257 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
2258 14, token, offset, image_index,
2259 lhs_se.expr, vec, rhs_token, rhs_offset,
2260 rhs_image_index, tmp, rhs_vec, lhs_kind,
2261 rhs_kind, may_require_tmp, src_stat);
2264 gfc_add_expr_to_block (&block, tmp);
2265 gfc_add_block_to_block (&block, &lhs_se.post);
2266 gfc_add_block_to_block (&block, &rhs_se.post);
2268 /* It guarantees memory consistency within the same segment. */
2269 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2270 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2271 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2272 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2273 ASM_VOLATILE_P (tmp) = 1;
2274 gfc_add_expr_to_block (&block, tmp);
2276 return gfc_finish_block (&block);
2280 static void
2281 trans_this_image (gfc_se * se, gfc_expr *expr)
2283 stmtblock_t loop;
2284 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
2285 lbound, ubound, extent, ml;
2286 gfc_se argse;
2287 int rank, corank;
2288 gfc_expr *distance = expr->value.function.actual->next->next->expr;
2290 if (expr->value.function.actual->expr
2291 && !gfc_is_coarray (expr->value.function.actual->expr))
2292 distance = expr->value.function.actual->expr;
2294 /* The case -fcoarray=single is handled elsewhere. */
2295 gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
2297 /* Argument-free version: THIS_IMAGE(). */
2298 if (distance || expr->value.function.actual->expr == NULL)
2300 if (distance)
2302 gfc_init_se (&argse, NULL);
2303 gfc_conv_expr_val (&argse, distance);
2304 gfc_add_block_to_block (&se->pre, &argse.pre);
2305 gfc_add_block_to_block (&se->post, &argse.post);
2306 tmp = fold_convert (integer_type_node, argse.expr);
2308 else
2309 tmp = integer_zero_node;
2310 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2311 tmp);
2312 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2313 tmp);
2314 return;
2317 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2319 type = gfc_get_int_type (gfc_default_integer_kind);
2320 corank = gfc_get_corank (expr->value.function.actual->expr);
2321 rank = expr->value.function.actual->expr->rank;
2323 /* Obtain the descriptor of the COARRAY. */
2324 gfc_init_se (&argse, NULL);
2325 argse.want_coarray = 1;
2326 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2327 gfc_add_block_to_block (&se->pre, &argse.pre);
2328 gfc_add_block_to_block (&se->post, &argse.post);
2329 desc = argse.expr;
2331 if (se->ss)
2333 /* Create an implicit second parameter from the loop variable. */
2334 gcc_assert (!expr->value.function.actual->next->expr);
2335 gcc_assert (corank > 0);
2336 gcc_assert (se->loop->dimen == 1);
2337 gcc_assert (se->ss->info->expr == expr);
2339 dim_arg = se->loop->loopvar[0];
2340 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
2341 gfc_array_index_type, dim_arg,
2342 build_int_cst (TREE_TYPE (dim_arg), 1));
2343 gfc_advance_se_ss_chain (se);
2345 else
2347 /* Use the passed DIM= argument. */
2348 gcc_assert (expr->value.function.actual->next->expr);
2349 gfc_init_se (&argse, NULL);
2350 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
2351 gfc_array_index_type);
2352 gfc_add_block_to_block (&se->pre, &argse.pre);
2353 dim_arg = argse.expr;
2355 if (INTEGER_CST_P (dim_arg))
2357 if (wi::ltu_p (wi::to_wide (dim_arg), 1)
2358 || wi::gtu_p (wi::to_wide (dim_arg),
2359 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2360 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2361 "dimension index", expr->value.function.isym->name,
2362 &expr->where);
2364 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2366 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
2367 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2368 dim_arg,
2369 build_int_cst (TREE_TYPE (dim_arg), 1));
2370 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2371 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2372 dim_arg, tmp);
2373 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2374 logical_type_node, cond, tmp);
2375 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2376 gfc_msg_fault);
2380 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2381 one always has a dim_arg argument.
2383 m = this_image() - 1
2384 if (corank == 1)
2386 sub(1) = m + lcobound(corank)
2387 return;
2389 i = rank
2390 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2391 for (;;)
2393 extent = gfc_extent(i)
2394 ml = m
2395 m = m/extent
2396 if (i >= min_var)
2397 goto exit_label
2400 exit_label:
2401 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2402 : m + lcobound(corank)
2405 /* this_image () - 1. */
2406 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2407 integer_zero_node);
2408 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
2409 fold_convert (type, tmp), build_int_cst (type, 1));
2410 if (corank == 1)
2412 /* sub(1) = m + lcobound(corank). */
2413 lbound = gfc_conv_descriptor_lbound_get (desc,
2414 build_int_cst (TREE_TYPE (gfc_array_index_type),
2415 corank+rank-1));
2416 lbound = fold_convert (type, lbound);
2417 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2419 se->expr = tmp;
2420 return;
2423 m = gfc_create_var (type, NULL);
2424 ml = gfc_create_var (type, NULL);
2425 loop_var = gfc_create_var (integer_type_node, NULL);
2426 min_var = gfc_create_var (integer_type_node, NULL);
2428 /* m = this_image () - 1. */
2429 gfc_add_modify (&se->pre, m, tmp);
2431 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2432 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2433 fold_convert (integer_type_node, dim_arg),
2434 build_int_cst (integer_type_node, rank - 1));
2435 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
2436 build_int_cst (integer_type_node, rank + corank - 2),
2437 tmp);
2438 gfc_add_modify (&se->pre, min_var, tmp);
2440 /* i = rank. */
2441 tmp = build_int_cst (integer_type_node, rank);
2442 gfc_add_modify (&se->pre, loop_var, tmp);
2444 exit_label = gfc_build_label_decl (NULL_TREE);
2445 TREE_USED (exit_label) = 1;
2447 /* Loop body. */
2448 gfc_init_block (&loop);
2450 /* ml = m. */
2451 gfc_add_modify (&loop, ml, m);
2453 /* extent = ... */
2454 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
2455 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
2456 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2457 extent = fold_convert (type, extent);
2459 /* m = m/extent. */
2460 gfc_add_modify (&loop, m,
2461 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
2462 m, extent));
2464 /* Exit condition: if (i >= min_var) goto exit_label. */
2465 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, loop_var,
2466 min_var);
2467 tmp = build1_v (GOTO_EXPR, exit_label);
2468 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
2469 build_empty_stmt (input_location));
2470 gfc_add_expr_to_block (&loop, tmp);
2472 /* Increment loop variable: i++. */
2473 gfc_add_modify (&loop, loop_var,
2474 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2475 loop_var,
2476 build_int_cst (integer_type_node, 1)));
2478 /* Making the loop... actually loop! */
2479 tmp = gfc_finish_block (&loop);
2480 tmp = build1_v (LOOP_EXPR, tmp);
2481 gfc_add_expr_to_block (&se->pre, tmp);
2483 /* The exit label. */
2484 tmp = build1_v (LABEL_EXPR, exit_label);
2485 gfc_add_expr_to_block (&se->pre, tmp);
2487 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2488 : m + lcobound(corank) */
2490 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, dim_arg,
2491 build_int_cst (TREE_TYPE (dim_arg), corank));
2493 lbound = gfc_conv_descriptor_lbound_get (desc,
2494 fold_build2_loc (input_location, PLUS_EXPR,
2495 gfc_array_index_type, dim_arg,
2496 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
2497 lbound = fold_convert (type, lbound);
2499 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
2500 fold_build2_loc (input_location, MULT_EXPR, type,
2501 m, extent));
2502 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2504 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
2505 fold_build2_loc (input_location, PLUS_EXPR, type,
2506 m, lbound));
2510 /* Convert a call to image_status. */
2512 static void
2513 conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
2515 unsigned int num_args;
2516 tree *args, tmp;
2518 num_args = gfc_intrinsic_argument_list_length (expr);
2519 args = XALLOCAVEC (tree, num_args);
2520 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2521 /* In args[0] the number of the image the status is desired for has to be
2522 given. */
2524 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2526 tree arg;
2527 arg = gfc_evaluate_now (args[0], &se->pre);
2528 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2529 fold_convert (integer_type_node, arg),
2530 integer_one_node);
2531 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2532 tmp, integer_zero_node,
2533 build_int_cst (integer_type_node,
2534 GFC_STAT_STOPPED_IMAGE));
2536 else if (flag_coarray == GFC_FCOARRAY_LIB)
2537 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
2538 args[0], build_int_cst (integer_type_node, -1));
2539 else
2540 gcc_unreachable ();
2542 se->expr = tmp;
2545 static void
2546 conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
2548 unsigned int num_args;
2550 tree *args, tmp;
2552 num_args = gfc_intrinsic_argument_list_length (expr);
2553 args = XALLOCAVEC (tree, num_args);
2554 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2556 if (flag_coarray ==
2557 GFC_FCOARRAY_SINGLE && expr->value.function.actual->expr)
2559 tree arg;
2561 arg = gfc_evaluate_now (args[0], &se->pre);
2562 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2563 fold_convert (integer_type_node, arg),
2564 integer_one_node);
2565 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2566 tmp, integer_zero_node,
2567 build_int_cst (integer_type_node,
2568 GFC_STAT_STOPPED_IMAGE));
2570 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
2572 // the value -1 represents that no team has been created yet
2573 tmp = build_int_cst (integer_type_node, -1);
2575 else if (flag_coarray == GFC_FCOARRAY_LIB && expr->value.function.actual->expr)
2576 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2577 args[0], build_int_cst (integer_type_node, -1));
2578 else if (flag_coarray == GFC_FCOARRAY_LIB)
2579 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2580 integer_zero_node, build_int_cst (integer_type_node, -1));
2581 else
2582 gcc_unreachable ();
2584 se->expr = tmp;
2588 static void
2589 trans_image_index (gfc_se * se, gfc_expr *expr)
2591 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
2592 tmp, invalid_bound;
2593 gfc_se argse, subse;
2594 int rank, corank, codim;
2596 type = gfc_get_int_type (gfc_default_integer_kind);
2597 corank = gfc_get_corank (expr->value.function.actual->expr);
2598 rank = expr->value.function.actual->expr->rank;
2600 /* Obtain the descriptor of the COARRAY. */
2601 gfc_init_se (&argse, NULL);
2602 argse.want_coarray = 1;
2603 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2604 gfc_add_block_to_block (&se->pre, &argse.pre);
2605 gfc_add_block_to_block (&se->post, &argse.post);
2606 desc = argse.expr;
2608 /* Obtain a handle to the SUB argument. */
2609 gfc_init_se (&subse, NULL);
2610 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
2611 gfc_add_block_to_block (&se->pre, &subse.pre);
2612 gfc_add_block_to_block (&se->post, &subse.post);
2613 subdesc = build_fold_indirect_ref_loc (input_location,
2614 gfc_conv_descriptor_data_get (subse.expr));
2616 /* Fortran 2008 does not require that the values remain in the cobounds,
2617 thus we need explicitly check this - and return 0 if they are exceeded. */
2619 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2620 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
2621 invalid_bound = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2622 fold_convert (gfc_array_index_type, tmp),
2623 lbound);
2625 for (codim = corank + rank - 2; codim >= rank; codim--)
2627 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2628 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2629 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2630 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2631 fold_convert (gfc_array_index_type, tmp),
2632 lbound);
2633 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2634 logical_type_node, invalid_bound, cond);
2635 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2636 fold_convert (gfc_array_index_type, tmp),
2637 ubound);
2638 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2639 logical_type_node, invalid_bound, cond);
2642 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
2644 /* See Fortran 2008, C.10 for the following algorithm. */
2646 /* coindex = sub(corank) - lcobound(n). */
2647 coindex = fold_convert (gfc_array_index_type,
2648 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
2649 NULL));
2650 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2651 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2652 fold_convert (gfc_array_index_type, coindex),
2653 lbound);
2655 for (codim = corank + rank - 2; codim >= rank; codim--)
2657 tree extent, ubound;
2659 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2660 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2661 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2662 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2664 /* coindex *= extent. */
2665 coindex = fold_build2_loc (input_location, MULT_EXPR,
2666 gfc_array_index_type, coindex, extent);
2668 /* coindex += sub(codim). */
2669 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2670 coindex = fold_build2_loc (input_location, PLUS_EXPR,
2671 gfc_array_index_type, coindex,
2672 fold_convert (gfc_array_index_type, tmp));
2674 /* coindex -= lbound(codim). */
2675 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2676 coindex = fold_build2_loc (input_location, MINUS_EXPR,
2677 gfc_array_index_type, coindex, lbound);
2680 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
2681 fold_convert(type, coindex),
2682 build_int_cst (type, 1));
2684 /* Return 0 if "coindex" exceeds num_images(). */
2686 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2687 num_images = build_int_cst (type, 1);
2688 else
2690 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2691 integer_zero_node,
2692 build_int_cst (integer_type_node, -1));
2693 num_images = fold_convert (type, tmp);
2696 tmp = gfc_create_var (type, NULL);
2697 gfc_add_modify (&se->pre, tmp, coindex);
2699 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, tmp,
2700 num_images);
2701 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
2702 cond,
2703 fold_convert (logical_type_node, invalid_bound));
2704 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
2705 build_int_cst (type, 0), tmp);
2708 static void
2709 trans_num_images (gfc_se * se, gfc_expr *expr)
2711 tree tmp, distance, failed;
2712 gfc_se argse;
2714 if (expr->value.function.actual->expr)
2716 gfc_init_se (&argse, NULL);
2717 gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
2718 gfc_add_block_to_block (&se->pre, &argse.pre);
2719 gfc_add_block_to_block (&se->post, &argse.post);
2720 distance = fold_convert (integer_type_node, argse.expr);
2722 else
2723 distance = integer_zero_node;
2725 if (expr->value.function.actual->next->expr)
2727 gfc_init_se (&argse, NULL);
2728 gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
2729 gfc_add_block_to_block (&se->pre, &argse.pre);
2730 gfc_add_block_to_block (&se->post, &argse.post);
2731 failed = fold_convert (integer_type_node, argse.expr);
2733 else
2734 failed = build_int_cst (integer_type_node, -1);
2735 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2736 distance, failed);
2737 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2741 static void
2742 gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
2744 gfc_se argse;
2746 gfc_init_se (&argse, NULL);
2747 argse.data_not_needed = 1;
2748 argse.descriptor_only = 1;
2750 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2751 gfc_add_block_to_block (&se->pre, &argse.pre);
2752 gfc_add_block_to_block (&se->post, &argse.post);
2754 se->expr = gfc_conv_descriptor_rank (argse.expr);
2755 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2756 se->expr);
2760 /* Evaluate a single upper or lower bound. */
2761 /* TODO: bound intrinsic generates way too much unnecessary code. */
2763 static void
2764 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
2766 gfc_actual_arglist *arg;
2767 gfc_actual_arglist *arg2;
2768 tree desc;
2769 tree type;
2770 tree bound;
2771 tree tmp;
2772 tree cond, cond1, cond3, cond4, size;
2773 tree ubound;
2774 tree lbound;
2775 gfc_se argse;
2776 gfc_array_spec * as;
2777 bool assumed_rank_lb_one;
2779 arg = expr->value.function.actual;
2780 arg2 = arg->next;
2782 if (se->ss)
2784 /* Create an implicit second parameter from the loop variable. */
2785 gcc_assert (!arg2->expr);
2786 gcc_assert (se->loop->dimen == 1);
2787 gcc_assert (se->ss->info->expr == expr);
2788 gfc_advance_se_ss_chain (se);
2789 bound = se->loop->loopvar[0];
2790 bound = fold_build2_loc (input_location, MINUS_EXPR,
2791 gfc_array_index_type, bound,
2792 se->loop->from[0]);
2794 else
2796 /* use the passed argument. */
2797 gcc_assert (arg2->expr);
2798 gfc_init_se (&argse, NULL);
2799 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2800 gfc_add_block_to_block (&se->pre, &argse.pre);
2801 bound = argse.expr;
2802 /* Convert from one based to zero based. */
2803 bound = fold_build2_loc (input_location, MINUS_EXPR,
2804 gfc_array_index_type, bound,
2805 gfc_index_one_node);
2808 /* TODO: don't re-evaluate the descriptor on each iteration. */
2809 /* Get a descriptor for the first parameter. */
2810 gfc_init_se (&argse, NULL);
2811 gfc_conv_expr_descriptor (&argse, arg->expr);
2812 gfc_add_block_to_block (&se->pre, &argse.pre);
2813 gfc_add_block_to_block (&se->post, &argse.post);
2815 desc = argse.expr;
2817 as = gfc_get_full_arrayspec_from_expr (arg->expr);
2819 if (INTEGER_CST_P (bound))
2821 if (((!as || as->type != AS_ASSUMED_RANK)
2822 && wi::geu_p (wi::to_wide (bound),
2823 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
2824 || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS))
2825 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2826 "dimension index", upper ? "UBOUND" : "LBOUND",
2827 &expr->where);
2830 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
2832 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2834 bound = gfc_evaluate_now (bound, &se->pre);
2835 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2836 bound, build_int_cst (TREE_TYPE (bound), 0));
2837 if (as && as->type == AS_ASSUMED_RANK)
2838 tmp = gfc_conv_descriptor_rank (desc);
2839 else
2840 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
2841 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2842 bound, fold_convert(TREE_TYPE (bound), tmp));
2843 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2844 logical_type_node, cond, tmp);
2845 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2846 gfc_msg_fault);
2850 /* Take care of the lbound shift for assumed-rank arrays, which are
2851 nonallocatable and nonpointers. Those has a lbound of 1. */
2852 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
2853 && ((arg->expr->ts.type != BT_CLASS
2854 && !arg->expr->symtree->n.sym->attr.allocatable
2855 && !arg->expr->symtree->n.sym->attr.pointer)
2856 || (arg->expr->ts.type == BT_CLASS
2857 && !CLASS_DATA (arg->expr)->attr.allocatable
2858 && !CLASS_DATA (arg->expr)->attr.class_pointer));
2860 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
2861 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
2863 /* 13.14.53: Result value for LBOUND
2865 Case (i): For an array section or for an array expression other than a
2866 whole array or array structure component, LBOUND(ARRAY, DIM)
2867 has the value 1. For a whole array or array structure
2868 component, LBOUND(ARRAY, DIM) has the value:
2869 (a) equal to the lower bound for subscript DIM of ARRAY if
2870 dimension DIM of ARRAY does not have extent zero
2871 or if ARRAY is an assumed-size array of rank DIM,
2872 or (b) 1 otherwise.
2874 13.14.113: Result value for UBOUND
2876 Case (i): For an array section or for an array expression other than a
2877 whole array or array structure component, UBOUND(ARRAY, DIM)
2878 has the value equal to the number of elements in the given
2879 dimension; otherwise, it has a value equal to the upper bound
2880 for subscript DIM of ARRAY if dimension DIM of ARRAY does
2881 not have size zero and has value zero if dimension DIM has
2882 size zero. */
2884 if (!upper && assumed_rank_lb_one)
2885 se->expr = gfc_index_one_node;
2886 else if (as)
2888 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
2890 cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2891 ubound, lbound);
2892 cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2893 stride, gfc_index_zero_node);
2894 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2895 logical_type_node, cond3, cond1);
2896 cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2897 stride, gfc_index_zero_node);
2899 if (upper)
2901 tree cond5;
2902 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2903 logical_type_node, cond3, cond4);
2904 cond5 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2905 gfc_index_one_node, lbound);
2906 cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2907 logical_type_node, cond4, cond5);
2909 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2910 logical_type_node, cond, cond5);
2912 if (assumed_rank_lb_one)
2914 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2915 gfc_array_index_type, ubound, lbound);
2916 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2917 gfc_array_index_type, tmp, gfc_index_one_node);
2919 else
2920 tmp = ubound;
2922 se->expr = fold_build3_loc (input_location, COND_EXPR,
2923 gfc_array_index_type, cond,
2924 tmp, gfc_index_zero_node);
2926 else
2928 if (as->type == AS_ASSUMED_SIZE)
2929 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2930 bound, build_int_cst (TREE_TYPE (bound),
2931 arg->expr->rank - 1));
2932 else
2933 cond = logical_false_node;
2935 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2936 logical_type_node, cond3, cond4);
2937 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2938 logical_type_node, cond, cond1);
2940 se->expr = fold_build3_loc (input_location, COND_EXPR,
2941 gfc_array_index_type, cond,
2942 lbound, gfc_index_one_node);
2945 else
2947 if (upper)
2949 size = fold_build2_loc (input_location, MINUS_EXPR,
2950 gfc_array_index_type, ubound, lbound);
2951 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
2952 gfc_array_index_type, size,
2953 gfc_index_one_node);
2954 se->expr = fold_build2_loc (input_location, MAX_EXPR,
2955 gfc_array_index_type, se->expr,
2956 gfc_index_zero_node);
2958 else
2959 se->expr = gfc_index_one_node;
2962 type = gfc_typenode_for_spec (&expr->ts);
2963 se->expr = convert (type, se->expr);
2967 static void
2968 conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
2970 gfc_actual_arglist *arg;
2971 gfc_actual_arglist *arg2;
2972 gfc_se argse;
2973 tree bound, resbound, resbound2, desc, cond, tmp;
2974 tree type;
2975 int corank;
2977 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
2978 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
2979 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
2981 arg = expr->value.function.actual;
2982 arg2 = arg->next;
2984 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
2985 corank = gfc_get_corank (arg->expr);
2987 gfc_init_se (&argse, NULL);
2988 argse.want_coarray = 1;
2990 gfc_conv_expr_descriptor (&argse, arg->expr);
2991 gfc_add_block_to_block (&se->pre, &argse.pre);
2992 gfc_add_block_to_block (&se->post, &argse.post);
2993 desc = argse.expr;
2995 if (se->ss)
2997 /* Create an implicit second parameter from the loop variable. */
2998 gcc_assert (!arg2->expr);
2999 gcc_assert (corank > 0);
3000 gcc_assert (se->loop->dimen == 1);
3001 gcc_assert (se->ss->info->expr == expr);
3003 bound = se->loop->loopvar[0];
3004 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3005 bound, gfc_rank_cst[arg->expr->rank]);
3006 gfc_advance_se_ss_chain (se);
3008 else
3010 /* use the passed argument. */
3011 gcc_assert (arg2->expr);
3012 gfc_init_se (&argse, NULL);
3013 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
3014 gfc_add_block_to_block (&se->pre, &argse.pre);
3015 bound = argse.expr;
3017 if (INTEGER_CST_P (bound))
3019 if (wi::ltu_p (wi::to_wide (bound), 1)
3020 || wi::gtu_p (wi::to_wide (bound),
3021 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
3022 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3023 "dimension index", expr->value.function.isym->name,
3024 &expr->where);
3026 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3028 bound = gfc_evaluate_now (bound, &se->pre);
3029 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3030 bound, build_int_cst (TREE_TYPE (bound), 1));
3031 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
3032 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3033 bound, tmp);
3034 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3035 logical_type_node, cond, tmp);
3036 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3037 gfc_msg_fault);
3041 /* Subtract 1 to get to zero based and add dimensions. */
3042 switch (arg->expr->rank)
3044 case 0:
3045 bound = fold_build2_loc (input_location, MINUS_EXPR,
3046 gfc_array_index_type, bound,
3047 gfc_index_one_node);
3048 case 1:
3049 break;
3050 default:
3051 bound = fold_build2_loc (input_location, PLUS_EXPR,
3052 gfc_array_index_type, bound,
3053 gfc_rank_cst[arg->expr->rank - 1]);
3057 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
3059 /* Handle UCOBOUND with special handling of the last codimension. */
3060 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
3062 /* Last codimension: For -fcoarray=single just return
3063 the lcobound - otherwise add
3064 ceiling (real (num_images ()) / real (size)) - 1
3065 = (num_images () + size - 1) / size - 1
3066 = (num_images - 1) / size(),
3067 where size is the product of the extent of all but the last
3068 codimension. */
3070 if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
3072 tree cosize;
3074 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
3075 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3076 2, integer_zero_node,
3077 build_int_cst (integer_type_node, -1));
3078 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3079 gfc_array_index_type,
3080 fold_convert (gfc_array_index_type, tmp),
3081 build_int_cst (gfc_array_index_type, 1));
3082 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
3083 gfc_array_index_type, tmp,
3084 fold_convert (gfc_array_index_type, cosize));
3085 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3086 gfc_array_index_type, resbound, tmp);
3088 else if (flag_coarray != GFC_FCOARRAY_SINGLE)
3090 /* ubound = lbound + num_images() - 1. */
3091 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3092 2, integer_zero_node,
3093 build_int_cst (integer_type_node, -1));
3094 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3095 gfc_array_index_type,
3096 fold_convert (gfc_array_index_type, tmp),
3097 build_int_cst (gfc_array_index_type, 1));
3098 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3099 gfc_array_index_type, resbound, tmp);
3102 if (corank > 1)
3104 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3105 bound,
3106 build_int_cst (TREE_TYPE (bound),
3107 arg->expr->rank + corank - 1));
3109 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
3110 se->expr = fold_build3_loc (input_location, COND_EXPR,
3111 gfc_array_index_type, cond,
3112 resbound, resbound2);
3114 else
3115 se->expr = resbound;
3117 else
3118 se->expr = resbound;
3120 type = gfc_typenode_for_spec (&expr->ts);
3121 se->expr = convert (type, se->expr);
3125 static void
3126 conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
3128 gfc_actual_arglist *array_arg;
3129 gfc_actual_arglist *dim_arg;
3130 gfc_se argse;
3131 tree desc, tmp;
3133 array_arg = expr->value.function.actual;
3134 dim_arg = array_arg->next;
3136 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
3138 gfc_init_se (&argse, NULL);
3139 gfc_conv_expr_descriptor (&argse, array_arg->expr);
3140 gfc_add_block_to_block (&se->pre, &argse.pre);
3141 gfc_add_block_to_block (&se->post, &argse.post);
3142 desc = argse.expr;
3144 gcc_assert (dim_arg->expr);
3145 gfc_init_se (&argse, NULL);
3146 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
3147 gfc_add_block_to_block (&se->pre, &argse.pre);
3148 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3149 argse.expr, gfc_index_one_node);
3150 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
3153 static void
3154 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
3156 tree arg, cabs;
3158 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3160 switch (expr->value.function.actual->expr->ts.type)
3162 case BT_INTEGER:
3163 case BT_REAL:
3164 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
3165 arg);
3166 break;
3168 case BT_COMPLEX:
3169 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
3170 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
3171 break;
3173 default:
3174 gcc_unreachable ();
3179 /* Create a complex value from one or two real components. */
3181 static void
3182 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
3184 tree real;
3185 tree imag;
3186 tree type;
3187 tree *args;
3188 unsigned int num_args;
3190 num_args = gfc_intrinsic_argument_list_length (expr);
3191 args = XALLOCAVEC (tree, num_args);
3193 type = gfc_typenode_for_spec (&expr->ts);
3194 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3195 real = convert (TREE_TYPE (type), args[0]);
3196 if (both)
3197 imag = convert (TREE_TYPE (type), args[1]);
3198 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
3200 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
3201 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
3202 imag = convert (TREE_TYPE (type), imag);
3204 else
3205 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
3207 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
3211 /* Remainder function MOD(A, P) = A - INT(A / P) * P
3212 MODULO(A, P) = A - FLOOR (A / P) * P
3214 The obvious algorithms above are numerically instable for large
3215 arguments, hence these intrinsics are instead implemented via calls
3216 to the fmod family of functions. It is the responsibility of the
3217 user to ensure that the second argument is non-zero. */
3219 static void
3220 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
3222 tree type;
3223 tree tmp;
3224 tree test;
3225 tree test2;
3226 tree fmod;
3227 tree zero;
3228 tree args[2];
3230 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3232 switch (expr->ts.type)
3234 case BT_INTEGER:
3235 /* Integer case is easy, we've got a builtin op. */
3236 type = TREE_TYPE (args[0]);
3238 if (modulo)
3239 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
3240 args[0], args[1]);
3241 else
3242 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3243 args[0], args[1]);
3244 break;
3246 case BT_REAL:
3247 fmod = NULL_TREE;
3248 /* Check if we have a builtin fmod. */
3249 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
3251 /* The builtin should always be available. */
3252 gcc_assert (fmod != NULL_TREE);
3254 tmp = build_addr (fmod);
3255 se->expr = build_call_array_loc (input_location,
3256 TREE_TYPE (TREE_TYPE (fmod)),
3257 tmp, 2, args);
3258 if (modulo == 0)
3259 return;
3261 type = TREE_TYPE (args[0]);
3263 args[0] = gfc_evaluate_now (args[0], &se->pre);
3264 args[1] = gfc_evaluate_now (args[1], &se->pre);
3266 /* Definition:
3267 modulo = arg - floor (arg/arg2) * arg2
3269 In order to calculate the result accurately, we use the fmod
3270 function as follows.
3272 res = fmod (arg, arg2);
3273 if (res)
3275 if ((arg < 0) xor (arg2 < 0))
3276 res += arg2;
3278 else
3279 res = copysign (0., arg2);
3281 => As two nested ternary exprs:
3283 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3284 : copysign (0., arg2);
3288 zero = gfc_build_const (type, integer_zero_node);
3289 tmp = gfc_evaluate_now (se->expr, &se->pre);
3290 if (!flag_signed_zeros)
3292 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3293 args[0], zero);
3294 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3295 args[1], zero);
3296 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3297 logical_type_node, test, test2);
3298 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3299 tmp, zero);
3300 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3301 logical_type_node, test, test2);
3302 test = gfc_evaluate_now (test, &se->pre);
3303 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3304 fold_build2_loc (input_location,
3305 PLUS_EXPR,
3306 type, tmp, args[1]),
3307 tmp);
3309 else
3311 tree expr1, copysign, cscall;
3312 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
3313 expr->ts.kind);
3314 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3315 args[0], zero);
3316 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3317 args[1], zero);
3318 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3319 logical_type_node, test, test2);
3320 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
3321 fold_build2_loc (input_location,
3322 PLUS_EXPR,
3323 type, tmp, args[1]),
3324 tmp);
3325 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3326 tmp, zero);
3327 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
3328 args[1]);
3329 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3330 expr1, cscall);
3332 return;
3334 default:
3335 gcc_unreachable ();
3339 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3340 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3341 where the right shifts are logical (i.e. 0's are shifted in).
3342 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3343 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3344 DSHIFTL(I,J,0) = I
3345 DSHIFTL(I,J,BITSIZE) = J
3346 DSHIFTR(I,J,0) = J
3347 DSHIFTR(I,J,BITSIZE) = I. */
3349 static void
3350 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
3352 tree type, utype, stype, arg1, arg2, shift, res, left, right;
3353 tree args[3], cond, tmp;
3354 int bitsize;
3356 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3358 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
3359 type = TREE_TYPE (args[0]);
3360 bitsize = TYPE_PRECISION (type);
3361 utype = unsigned_type_for (type);
3362 stype = TREE_TYPE (args[2]);
3364 arg1 = gfc_evaluate_now (args[0], &se->pre);
3365 arg2 = gfc_evaluate_now (args[1], &se->pre);
3366 shift = gfc_evaluate_now (args[2], &se->pre);
3368 /* The generic case. */
3369 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
3370 build_int_cst (stype, bitsize), shift);
3371 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3372 arg1, dshiftl ? shift : tmp);
3374 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
3375 fold_convert (utype, arg2), dshiftl ? tmp : shift);
3376 right = fold_convert (type, right);
3378 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
3380 /* Special cases. */
3381 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3382 build_int_cst (stype, 0));
3383 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3384 dshiftl ? arg1 : arg2, res);
3386 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3387 build_int_cst (stype, bitsize));
3388 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3389 dshiftl ? arg2 : arg1, res);
3391 se->expr = res;
3395 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3397 static void
3398 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
3400 tree val;
3401 tree tmp;
3402 tree type;
3403 tree zero;
3404 tree args[2];
3406 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3407 type = TREE_TYPE (args[0]);
3409 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
3410 val = gfc_evaluate_now (val, &se->pre);
3412 zero = gfc_build_const (type, integer_zero_node);
3413 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node, val, zero);
3414 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
3418 /* SIGN(A, B) is absolute value of A times sign of B.
3419 The real value versions use library functions to ensure the correct
3420 handling of negative zero. Integer case implemented as:
3421 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3424 static void
3425 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
3427 tree tmp;
3428 tree type;
3429 tree args[2];
3431 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3432 if (expr->ts.type == BT_REAL)
3434 tree abs;
3436 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
3437 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
3439 /* We explicitly have to ignore the minus sign. We do so by using
3440 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3441 if (!flag_sign_zero
3442 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
3444 tree cond, zero;
3445 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
3446 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3447 args[1], zero);
3448 se->expr = fold_build3_loc (input_location, COND_EXPR,
3449 TREE_TYPE (args[0]), cond,
3450 build_call_expr_loc (input_location, abs, 1,
3451 args[0]),
3452 build_call_expr_loc (input_location, tmp, 2,
3453 args[0], args[1]));
3455 else
3456 se->expr = build_call_expr_loc (input_location, tmp, 2,
3457 args[0], args[1]);
3458 return;
3461 /* Having excluded floating point types, we know we are now dealing
3462 with signed integer types. */
3463 type = TREE_TYPE (args[0]);
3465 /* Args[0] is used multiple times below. */
3466 args[0] = gfc_evaluate_now (args[0], &se->pre);
3468 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3469 the signs of A and B are the same, and of all ones if they differ. */
3470 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
3471 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
3472 build_int_cst (type, TYPE_PRECISION (type) - 1));
3473 tmp = gfc_evaluate_now (tmp, &se->pre);
3475 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3476 is all ones (i.e. -1). */
3477 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
3478 fold_build2_loc (input_location, PLUS_EXPR,
3479 type, args[0], tmp), tmp);
3483 /* Test for the presence of an optional argument. */
3485 static void
3486 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
3488 gfc_expr *arg;
3490 arg = expr->value.function.actual->expr;
3491 gcc_assert (arg->expr_type == EXPR_VARIABLE);
3492 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
3493 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3497 /* Calculate the double precision product of two single precision values. */
3499 static void
3500 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
3502 tree type;
3503 tree args[2];
3505 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3507 /* Convert the args to double precision before multiplying. */
3508 type = gfc_typenode_for_spec (&expr->ts);
3509 args[0] = convert (type, args[0]);
3510 args[1] = convert (type, args[1]);
3511 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
3512 args[1]);
3516 /* Return a length one character string containing an ascii character. */
3518 static void
3519 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
3521 tree arg[2];
3522 tree var;
3523 tree type;
3524 unsigned int num_args;
3526 num_args = gfc_intrinsic_argument_list_length (expr);
3527 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
3529 type = gfc_get_char_type (expr->ts.kind);
3530 var = gfc_create_var (type, "char");
3532 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
3533 gfc_add_modify (&se->pre, var, arg[0]);
3534 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
3535 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
3539 static void
3540 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
3542 tree var;
3543 tree len;
3544 tree tmp;
3545 tree cond;
3546 tree fndecl;
3547 tree *args;
3548 unsigned int num_args;
3550 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3551 args = XALLOCAVEC (tree, num_args);
3553 var = gfc_create_var (pchar_type_node, "pstr");
3554 len = gfc_create_var (gfc_charlen_type_node, "len");
3556 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3557 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3558 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3560 fndecl = build_addr (gfor_fndecl_ctime);
3561 tmp = build_call_array_loc (input_location,
3562 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
3563 fndecl, num_args, args);
3564 gfc_add_expr_to_block (&se->pre, tmp);
3566 /* Free the temporary afterwards, if necessary. */
3567 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3568 len, build_int_cst (TREE_TYPE (len), 0));
3569 tmp = gfc_call_free (var);
3570 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3571 gfc_add_expr_to_block (&se->post, tmp);
3573 se->expr = var;
3574 se->string_length = len;
3578 static void
3579 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
3581 tree var;
3582 tree len;
3583 tree tmp;
3584 tree cond;
3585 tree fndecl;
3586 tree *args;
3587 unsigned int num_args;
3589 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3590 args = XALLOCAVEC (tree, num_args);
3592 var = gfc_create_var (pchar_type_node, "pstr");
3593 len = gfc_create_var (gfc_charlen_type_node, "len");
3595 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3596 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3597 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3599 fndecl = build_addr (gfor_fndecl_fdate);
3600 tmp = build_call_array_loc (input_location,
3601 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
3602 fndecl, num_args, args);
3603 gfc_add_expr_to_block (&se->pre, tmp);
3605 /* Free the temporary afterwards, if necessary. */
3606 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3607 len, build_int_cst (TREE_TYPE (len), 0));
3608 tmp = gfc_call_free (var);
3609 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3610 gfc_add_expr_to_block (&se->post, tmp);
3612 se->expr = var;
3613 se->string_length = len;
3617 /* Generate a direct call to free() for the FREE subroutine. */
3619 static tree
3620 conv_intrinsic_free (gfc_code *code)
3622 stmtblock_t block;
3623 gfc_se argse;
3624 tree arg, call;
3626 gfc_init_se (&argse, NULL);
3627 gfc_conv_expr (&argse, code->ext.actual->expr);
3628 arg = fold_convert (ptr_type_node, argse.expr);
3630 gfc_init_block (&block);
3631 call = build_call_expr_loc (input_location,
3632 builtin_decl_explicit (BUILT_IN_FREE), 1, arg);
3633 gfc_add_expr_to_block (&block, call);
3634 return gfc_finish_block (&block);
3638 /* Call the RANDOM_INIT library subroutine with a hidden argument for
3639 handling seeding on coarray images. */
3641 static tree
3642 conv_intrinsic_random_init (gfc_code *code)
3644 stmtblock_t block;
3645 gfc_se se;
3646 tree arg1, arg2, arg3, tmp;
3647 tree logical4_type_node = gfc_get_logical_type (4);
3649 /* Make the function call. */
3650 gfc_init_block (&block);
3651 gfc_init_se (&se, NULL);
3653 /* Convert REPEATABLE to a LOGICAL(4) entity. */
3654 gfc_conv_expr (&se, code->ext.actual->expr);
3655 gfc_add_block_to_block (&block, &se.pre);
3656 arg1 = fold_convert (logical4_type_node, gfc_evaluate_now (se.expr, &block));
3657 gfc_add_block_to_block (&block, &se.post);
3659 /* Convert IMAGE_DISTINCT to a LOGICAL(4) entity. */
3660 gfc_conv_expr (&se, code->ext.actual->next->expr);
3661 gfc_add_block_to_block (&block, &se.pre);
3662 arg2 = fold_convert (logical4_type_node, gfc_evaluate_now (se.expr, &block));
3663 gfc_add_block_to_block (&block, &se.post);
3665 /* Create the hidden argument. For non-coarray codes and -fcoarray=single,
3666 simply set this to 0. For -fcoarray=lib, generate a call to
3667 THIS_IMAGE() without arguments. */
3668 arg3 = build_int_cst (gfc_get_int_type (4), 0);
3669 if (flag_coarray == GFC_FCOARRAY_LIB)
3671 arg3 = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image,
3672 1, arg3);
3673 se.expr = fold_convert (gfc_get_int_type (4), arg3);
3676 tmp = build_call_expr_loc (input_location, gfor_fndecl_random_init, 3,
3677 arg1, arg2, arg3);
3678 gfc_add_expr_to_block (&block, tmp);
3680 return gfc_finish_block (&block);
3684 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3685 conversions. */
3687 static tree
3688 conv_intrinsic_system_clock (gfc_code *code)
3690 stmtblock_t block;
3691 gfc_se count_se, count_rate_se, count_max_se;
3692 tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
3693 tree tmp;
3694 int least;
3696 gfc_expr *count = code->ext.actual->expr;
3697 gfc_expr *count_rate = code->ext.actual->next->expr;
3698 gfc_expr *count_max = code->ext.actual->next->next->expr;
3700 /* Evaluate our arguments. */
3701 if (count)
3703 gfc_init_se (&count_se, NULL);
3704 gfc_conv_expr (&count_se, count);
3707 if (count_rate)
3709 gfc_init_se (&count_rate_se, NULL);
3710 gfc_conv_expr (&count_rate_se, count_rate);
3713 if (count_max)
3715 gfc_init_se (&count_max_se, NULL);
3716 gfc_conv_expr (&count_max_se, count_max);
3719 /* Find the smallest kind found of the arguments. */
3720 least = 16;
3721 least = (count && count->ts.kind < least) ? count->ts.kind : least;
3722 least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
3723 : least;
3724 least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
3725 : least;
3727 /* Prepare temporary variables. */
3729 if (count)
3731 if (least >= 8)
3732 arg1 = gfc_create_var (gfc_get_int_type (8), "count");
3733 else if (least == 4)
3734 arg1 = gfc_create_var (gfc_get_int_type (4), "count");
3735 else if (count->ts.kind == 1)
3736 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
3737 count->ts.kind);
3738 else
3739 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
3740 count->ts.kind);
3743 if (count_rate)
3745 if (least >= 8)
3746 arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
3747 else if (least == 4)
3748 arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
3749 else
3750 arg2 = integer_zero_node;
3753 if (count_max)
3755 if (least >= 8)
3756 arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
3757 else if (least == 4)
3758 arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
3759 else
3760 arg3 = integer_zero_node;
3763 /* Make the function call. */
3764 gfc_init_block (&block);
3766 if (least <= 2)
3768 if (least == 1)
3770 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3771 : null_pointer_node;
3772 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3773 : null_pointer_node;
3774 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3775 : null_pointer_node;
3778 if (least == 2)
3780 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3781 : null_pointer_node;
3782 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3783 : null_pointer_node;
3784 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3785 : null_pointer_node;
3788 else
3790 if (least == 4)
3792 tmp = build_call_expr_loc (input_location,
3793 gfor_fndecl_system_clock4, 3,
3794 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3795 : null_pointer_node,
3796 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3797 : null_pointer_node,
3798 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3799 : null_pointer_node);
3800 gfc_add_expr_to_block (&block, tmp);
3802 /* Handle kind>=8, 10, or 16 arguments */
3803 if (least >= 8)
3805 tmp = build_call_expr_loc (input_location,
3806 gfor_fndecl_system_clock8, 3,
3807 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3808 : null_pointer_node,
3809 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3810 : null_pointer_node,
3811 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3812 : null_pointer_node);
3813 gfc_add_expr_to_block (&block, tmp);
3817 /* And store values back if needed. */
3818 if (arg1 && arg1 != count_se.expr)
3819 gfc_add_modify (&block, count_se.expr,
3820 fold_convert (TREE_TYPE (count_se.expr), arg1));
3821 if (arg2 && arg2 != count_rate_se.expr)
3822 gfc_add_modify (&block, count_rate_se.expr,
3823 fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
3824 if (arg3 && arg3 != count_max_se.expr)
3825 gfc_add_modify (&block, count_max_se.expr,
3826 fold_convert (TREE_TYPE (count_max_se.expr), arg3));
3828 return gfc_finish_block (&block);
3832 /* Return a character string containing the tty name. */
3834 static void
3835 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
3837 tree var;
3838 tree len;
3839 tree tmp;
3840 tree cond;
3841 tree fndecl;
3842 tree *args;
3843 unsigned int num_args;
3845 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3846 args = XALLOCAVEC (tree, num_args);
3848 var = gfc_create_var (pchar_type_node, "pstr");
3849 len = gfc_create_var (gfc_charlen_type_node, "len");
3851 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3852 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3853 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3855 fndecl = build_addr (gfor_fndecl_ttynam);
3856 tmp = build_call_array_loc (input_location,
3857 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
3858 fndecl, num_args, args);
3859 gfc_add_expr_to_block (&se->pre, tmp);
3861 /* Free the temporary afterwards, if necessary. */
3862 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3863 len, build_int_cst (TREE_TYPE (len), 0));
3864 tmp = gfc_call_free (var);
3865 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3866 gfc_add_expr_to_block (&se->post, tmp);
3868 se->expr = var;
3869 se->string_length = len;
3873 /* Get the minimum/maximum value of all the parameters.
3874 minmax (a1, a2, a3, ...)
3876 mvar = a1;
3877 if (a2 .op. mvar || isnan (mvar))
3878 mvar = a2;
3879 if (a3 .op. mvar || isnan (mvar))
3880 mvar = a3;
3882 return mvar
3886 /* TODO: Mismatching types can occur when specific names are used.
3887 These should be handled during resolution. */
3888 static void
3889 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
3891 tree tmp;
3892 tree mvar;
3893 tree val;
3894 tree thencase;
3895 tree *args;
3896 tree type;
3897 gfc_actual_arglist *argexpr;
3898 unsigned int i, nargs;
3900 nargs = gfc_intrinsic_argument_list_length (expr);
3901 args = XALLOCAVEC (tree, nargs);
3903 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
3904 type = gfc_typenode_for_spec (&expr->ts);
3906 argexpr = expr->value.function.actual;
3907 if (TREE_TYPE (args[0]) != type)
3908 args[0] = convert (type, args[0]);
3909 /* Only evaluate the argument once. */
3910 if (!VAR_P (args[0]) && !TREE_CONSTANT (args[0]))
3911 args[0] = gfc_evaluate_now (args[0], &se->pre);
3913 mvar = gfc_create_var (type, "M");
3914 gfc_add_modify (&se->pre, mvar, args[0]);
3915 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
3917 tree cond, isnan;
3919 val = args[i];
3921 /* Handle absent optional arguments by ignoring the comparison. */
3922 if (argexpr->expr->expr_type == EXPR_VARIABLE
3923 && argexpr->expr->symtree->n.sym->attr.optional
3924 && TREE_CODE (val) == INDIRECT_REF)
3925 cond = fold_build2_loc (input_location,
3926 NE_EXPR, logical_type_node,
3927 TREE_OPERAND (val, 0),
3928 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
3929 else
3931 cond = NULL_TREE;
3933 /* Only evaluate the argument once. */
3934 if (!VAR_P (val) && !TREE_CONSTANT (val))
3935 val = gfc_evaluate_now (val, &se->pre);
3938 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
3940 tmp = fold_build2_loc (input_location, op, logical_type_node,
3941 convert (type, val), mvar);
3943 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
3944 __builtin_isnan might be made dependent on that module being loaded,
3945 to help performance of programs that don't rely on IEEE semantics. */
3946 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
3948 isnan = build_call_expr_loc (input_location,
3949 builtin_decl_explicit (BUILT_IN_ISNAN),
3950 1, mvar);
3951 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3952 logical_type_node, tmp,
3953 fold_convert (logical_type_node, isnan));
3955 tmp = build3_v (COND_EXPR, tmp, thencase,
3956 build_empty_stmt (input_location));
3958 if (cond != NULL_TREE)
3959 tmp = build3_v (COND_EXPR, cond, tmp,
3960 build_empty_stmt (input_location));
3962 gfc_add_expr_to_block (&se->pre, tmp);
3963 argexpr = argexpr->next;
3965 se->expr = mvar;
3969 /* Generate library calls for MIN and MAX intrinsics for character
3970 variables. */
3971 static void
3972 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
3974 tree *args;
3975 tree var, len, fndecl, tmp, cond, function;
3976 unsigned int nargs;
3978 nargs = gfc_intrinsic_argument_list_length (expr);
3979 args = XALLOCAVEC (tree, nargs + 4);
3980 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
3982 /* Create the result variables. */
3983 len = gfc_create_var (gfc_charlen_type_node, "len");
3984 args[0] = gfc_build_addr_expr (NULL_TREE, len);
3985 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
3986 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
3987 args[2] = build_int_cst (integer_type_node, op);
3988 args[3] = build_int_cst (integer_type_node, nargs / 2);
3990 if (expr->ts.kind == 1)
3991 function = gfor_fndecl_string_minmax;
3992 else if (expr->ts.kind == 4)
3993 function = gfor_fndecl_string_minmax_char4;
3994 else
3995 gcc_unreachable ();
3997 /* Make the function call. */
3998 fndecl = build_addr (function);
3999 tmp = build_call_array_loc (input_location,
4000 TREE_TYPE (TREE_TYPE (function)), fndecl,
4001 nargs + 4, args);
4002 gfc_add_expr_to_block (&se->pre, tmp);
4004 /* Free the temporary afterwards, if necessary. */
4005 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4006 len, build_int_cst (TREE_TYPE (len), 0));
4007 tmp = gfc_call_free (var);
4008 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4009 gfc_add_expr_to_block (&se->post, tmp);
4011 se->expr = var;
4012 se->string_length = len;
4016 /* Create a symbol node for this intrinsic. The symbol from the frontend
4017 has the generic name. */
4019 static gfc_symbol *
4020 gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
4022 gfc_symbol *sym;
4024 /* TODO: Add symbols for intrinsic function to the global namespace. */
4025 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
4026 sym = gfc_new_symbol (expr->value.function.name, NULL);
4028 sym->ts = expr->ts;
4029 sym->attr.external = 1;
4030 sym->attr.function = 1;
4031 sym->attr.always_explicit = 1;
4032 sym->attr.proc = PROC_INTRINSIC;
4033 sym->attr.flavor = FL_PROCEDURE;
4034 sym->result = sym;
4035 if (expr->rank > 0)
4037 sym->attr.dimension = 1;
4038 sym->as = gfc_get_array_spec ();
4039 sym->as->type = AS_ASSUMED_SHAPE;
4040 sym->as->rank = expr->rank;
4043 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4044 ignore_optional ? expr->value.function.actual
4045 : NULL);
4047 return sym;
4050 /* Generate a call to an external intrinsic function. */
4051 static void
4052 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
4054 gfc_symbol *sym;
4055 vec<tree, va_gc> *append_args;
4057 gcc_assert (!se->ss || se->ss->info->expr == expr);
4059 if (se->ss)
4060 gcc_assert (expr->rank > 0);
4061 else
4062 gcc_assert (expr->rank == 0);
4064 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
4066 /* Calls to libgfortran_matmul need to be appended special arguments,
4067 to be able to call the BLAS ?gemm functions if required and possible. */
4068 append_args = NULL;
4069 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
4070 && sym->ts.type != BT_LOGICAL)
4072 tree cint = gfc_get_int_type (gfc_c_int_kind);
4074 if (flag_external_blas
4075 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
4076 && (sym->ts.kind == 4 || sym->ts.kind == 8))
4078 tree gemm_fndecl;
4080 if (sym->ts.type == BT_REAL)
4082 if (sym->ts.kind == 4)
4083 gemm_fndecl = gfor_fndecl_sgemm;
4084 else
4085 gemm_fndecl = gfor_fndecl_dgemm;
4087 else
4089 if (sym->ts.kind == 4)
4090 gemm_fndecl = gfor_fndecl_cgemm;
4091 else
4092 gemm_fndecl = gfor_fndecl_zgemm;
4095 vec_alloc (append_args, 3);
4096 append_args->quick_push (build_int_cst (cint, 1));
4097 append_args->quick_push (build_int_cst (cint,
4098 flag_blas_matmul_limit));
4099 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
4100 gemm_fndecl));
4102 else
4104 vec_alloc (append_args, 3);
4105 append_args->quick_push (build_int_cst (cint, 0));
4106 append_args->quick_push (build_int_cst (cint, 0));
4107 append_args->quick_push (null_pointer_node);
4111 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4112 append_args);
4113 gfc_free_symbol (sym);
4116 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4117 Implemented as
4118 any(a)
4120 forall (i=...)
4121 if (a[i] != 0)
4122 return 1
4123 end forall
4124 return 0
4126 all(a)
4128 forall (i=...)
4129 if (a[i] == 0)
4130 return 0
4131 end forall
4132 return 1
4135 static void
4136 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
4138 tree resvar;
4139 stmtblock_t block;
4140 stmtblock_t body;
4141 tree type;
4142 tree tmp;
4143 tree found;
4144 gfc_loopinfo loop;
4145 gfc_actual_arglist *actual;
4146 gfc_ss *arrayss;
4147 gfc_se arrayse;
4148 tree exit_label;
4150 if (se->ss)
4152 gfc_conv_intrinsic_funcall (se, expr);
4153 return;
4156 actual = expr->value.function.actual;
4157 type = gfc_typenode_for_spec (&expr->ts);
4158 /* Initialize the result. */
4159 resvar = gfc_create_var (type, "test");
4160 if (op == EQ_EXPR)
4161 tmp = convert (type, boolean_true_node);
4162 else
4163 tmp = convert (type, boolean_false_node);
4164 gfc_add_modify (&se->pre, resvar, tmp);
4166 /* Walk the arguments. */
4167 arrayss = gfc_walk_expr (actual->expr);
4168 gcc_assert (arrayss != gfc_ss_terminator);
4170 /* Initialize the scalarizer. */
4171 gfc_init_loopinfo (&loop);
4172 exit_label = gfc_build_label_decl (NULL_TREE);
4173 TREE_USED (exit_label) = 1;
4174 gfc_add_ss_to_loop (&loop, arrayss);
4176 /* Initialize the loop. */
4177 gfc_conv_ss_startstride (&loop);
4178 gfc_conv_loop_setup (&loop, &expr->where);
4180 gfc_mark_ss_chain_used (arrayss, 1);
4181 /* Generate the loop body. */
4182 gfc_start_scalarized_body (&loop, &body);
4184 /* If the condition matches then set the return value. */
4185 gfc_start_block (&block);
4186 if (op == EQ_EXPR)
4187 tmp = convert (type, boolean_false_node);
4188 else
4189 tmp = convert (type, boolean_true_node);
4190 gfc_add_modify (&block, resvar, tmp);
4192 /* And break out of the loop. */
4193 tmp = build1_v (GOTO_EXPR, exit_label);
4194 gfc_add_expr_to_block (&block, tmp);
4196 found = gfc_finish_block (&block);
4198 /* Check this element. */
4199 gfc_init_se (&arrayse, NULL);
4200 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4201 arrayse.ss = arrayss;
4202 gfc_conv_expr_val (&arrayse, actual->expr);
4204 gfc_add_block_to_block (&body, &arrayse.pre);
4205 tmp = fold_build2_loc (input_location, op, logical_type_node, arrayse.expr,
4206 build_int_cst (TREE_TYPE (arrayse.expr), 0));
4207 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
4208 gfc_add_expr_to_block (&body, tmp);
4209 gfc_add_block_to_block (&body, &arrayse.post);
4211 gfc_trans_scalarizing_loops (&loop, &body);
4213 /* Add the exit label. */
4214 tmp = build1_v (LABEL_EXPR, exit_label);
4215 gfc_add_expr_to_block (&loop.pre, tmp);
4217 gfc_add_block_to_block (&se->pre, &loop.pre);
4218 gfc_add_block_to_block (&se->pre, &loop.post);
4219 gfc_cleanup_loop (&loop);
4221 se->expr = resvar;
4224 /* COUNT(A) = Number of true elements in A. */
4225 static void
4226 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
4228 tree resvar;
4229 tree type;
4230 stmtblock_t body;
4231 tree tmp;
4232 gfc_loopinfo loop;
4233 gfc_actual_arglist *actual;
4234 gfc_ss *arrayss;
4235 gfc_se arrayse;
4237 if (se->ss)
4239 gfc_conv_intrinsic_funcall (se, expr);
4240 return;
4243 actual = expr->value.function.actual;
4245 type = gfc_typenode_for_spec (&expr->ts);
4246 /* Initialize the result. */
4247 resvar = gfc_create_var (type, "count");
4248 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4250 /* Walk the arguments. */
4251 arrayss = gfc_walk_expr (actual->expr);
4252 gcc_assert (arrayss != gfc_ss_terminator);
4254 /* Initialize the scalarizer. */
4255 gfc_init_loopinfo (&loop);
4256 gfc_add_ss_to_loop (&loop, arrayss);
4258 /* Initialize the loop. */
4259 gfc_conv_ss_startstride (&loop);
4260 gfc_conv_loop_setup (&loop, &expr->where);
4262 gfc_mark_ss_chain_used (arrayss, 1);
4263 /* Generate the loop body. */
4264 gfc_start_scalarized_body (&loop, &body);
4266 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
4267 resvar, build_int_cst (TREE_TYPE (resvar), 1));
4268 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
4270 gfc_init_se (&arrayse, NULL);
4271 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4272 arrayse.ss = arrayss;
4273 gfc_conv_expr_val (&arrayse, actual->expr);
4274 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
4275 build_empty_stmt (input_location));
4277 gfc_add_block_to_block (&body, &arrayse.pre);
4278 gfc_add_expr_to_block (&body, tmp);
4279 gfc_add_block_to_block (&body, &arrayse.post);
4281 gfc_trans_scalarizing_loops (&loop, &body);
4283 gfc_add_block_to_block (&se->pre, &loop.pre);
4284 gfc_add_block_to_block (&se->pre, &loop.post);
4285 gfc_cleanup_loop (&loop);
4287 se->expr = resvar;
4291 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4292 struct and return the corresponding loopinfo. */
4294 static gfc_loopinfo *
4295 enter_nested_loop (gfc_se *se)
4297 se->ss = se->ss->nested_ss;
4298 gcc_assert (se->ss == se->ss->loop->ss);
4300 return se->ss->loop;
4304 /* Inline implementation of the sum and product intrinsics. */
4305 static void
4306 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
4307 bool norm2)
4309 tree resvar;
4310 tree scale = NULL_TREE;
4311 tree type;
4312 stmtblock_t body;
4313 stmtblock_t block;
4314 tree tmp;
4315 gfc_loopinfo loop, *ploop;
4316 gfc_actual_arglist *arg_array, *arg_mask;
4317 gfc_ss *arrayss = NULL;
4318 gfc_ss *maskss = NULL;
4319 gfc_se arrayse;
4320 gfc_se maskse;
4321 gfc_se *parent_se;
4322 gfc_expr *arrayexpr;
4323 gfc_expr *maskexpr;
4325 if (expr->rank > 0)
4327 gcc_assert (gfc_inline_intrinsic_function_p (expr));
4328 parent_se = se;
4330 else
4331 parent_se = NULL;
4333 type = gfc_typenode_for_spec (&expr->ts);
4334 /* Initialize the result. */
4335 resvar = gfc_create_var (type, "val");
4336 if (norm2)
4338 /* result = 0.0;
4339 scale = 1.0. */
4340 scale = gfc_create_var (type, "scale");
4341 gfc_add_modify (&se->pre, scale,
4342 gfc_build_const (type, integer_one_node));
4343 tmp = gfc_build_const (type, integer_zero_node);
4345 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4346 tmp = gfc_build_const (type, integer_zero_node);
4347 else if (op == NE_EXPR)
4348 /* PARITY. */
4349 tmp = convert (type, boolean_false_node);
4350 else if (op == BIT_AND_EXPR)
4351 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
4352 type, integer_one_node));
4353 else
4354 tmp = gfc_build_const (type, integer_one_node);
4356 gfc_add_modify (&se->pre, resvar, tmp);
4358 arg_array = expr->value.function.actual;
4360 arrayexpr = arg_array->expr;
4362 if (op == NE_EXPR || norm2)
4363 /* PARITY and NORM2. */
4364 maskexpr = NULL;
4365 else
4367 arg_mask = arg_array->next->next;
4368 gcc_assert (arg_mask != NULL);
4369 maskexpr = arg_mask->expr;
4372 if (expr->rank == 0)
4374 /* Walk the arguments. */
4375 arrayss = gfc_walk_expr (arrayexpr);
4376 gcc_assert (arrayss != gfc_ss_terminator);
4378 if (maskexpr && maskexpr->rank > 0)
4380 maskss = gfc_walk_expr (maskexpr);
4381 gcc_assert (maskss != gfc_ss_terminator);
4383 else
4384 maskss = NULL;
4386 /* Initialize the scalarizer. */
4387 gfc_init_loopinfo (&loop);
4388 gfc_add_ss_to_loop (&loop, arrayss);
4389 if (maskexpr && maskexpr->rank > 0)
4390 gfc_add_ss_to_loop (&loop, maskss);
4392 /* Initialize the loop. */
4393 gfc_conv_ss_startstride (&loop);
4394 gfc_conv_loop_setup (&loop, &expr->where);
4396 gfc_mark_ss_chain_used (arrayss, 1);
4397 if (maskexpr && maskexpr->rank > 0)
4398 gfc_mark_ss_chain_used (maskss, 1);
4400 ploop = &loop;
4402 else
4403 /* All the work has been done in the parent loops. */
4404 ploop = enter_nested_loop (se);
4406 gcc_assert (ploop);
4408 /* Generate the loop body. */
4409 gfc_start_scalarized_body (ploop, &body);
4411 /* If we have a mask, only add this element if the mask is set. */
4412 if (maskexpr && maskexpr->rank > 0)
4414 gfc_init_se (&maskse, parent_se);
4415 gfc_copy_loopinfo_to_se (&maskse, ploop);
4416 if (expr->rank == 0)
4417 maskse.ss = maskss;
4418 gfc_conv_expr_val (&maskse, maskexpr);
4419 gfc_add_block_to_block (&body, &maskse.pre);
4421 gfc_start_block (&block);
4423 else
4424 gfc_init_block (&block);
4426 /* Do the actual summation/product. */
4427 gfc_init_se (&arrayse, parent_se);
4428 gfc_copy_loopinfo_to_se (&arrayse, ploop);
4429 if (expr->rank == 0)
4430 arrayse.ss = arrayss;
4431 gfc_conv_expr_val (&arrayse, arrayexpr);
4432 gfc_add_block_to_block (&block, &arrayse.pre);
4434 if (norm2)
4436 /* if (x (i) != 0.0)
4438 absX = abs(x(i))
4439 if (absX > scale)
4441 val = scale/absX;
4442 result = 1.0 + result * val * val;
4443 scale = absX;
4445 else
4447 val = absX/scale;
4448 result += val * val;
4450 } */
4451 tree res1, res2, cond, absX, val;
4452 stmtblock_t ifblock1, ifblock2, ifblock3;
4454 gfc_init_block (&ifblock1);
4456 absX = gfc_create_var (type, "absX");
4457 gfc_add_modify (&ifblock1, absX,
4458 fold_build1_loc (input_location, ABS_EXPR, type,
4459 arrayse.expr));
4460 val = gfc_create_var (type, "val");
4461 gfc_add_expr_to_block (&ifblock1, val);
4463 gfc_init_block (&ifblock2);
4464 gfc_add_modify (&ifblock2, val,
4465 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
4466 absX));
4467 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4468 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
4469 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
4470 gfc_build_const (type, integer_one_node));
4471 gfc_add_modify (&ifblock2, resvar, res1);
4472 gfc_add_modify (&ifblock2, scale, absX);
4473 res1 = gfc_finish_block (&ifblock2);
4475 gfc_init_block (&ifblock3);
4476 gfc_add_modify (&ifblock3, val,
4477 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
4478 scale));
4479 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4480 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
4481 gfc_add_modify (&ifblock3, resvar, res2);
4482 res2 = gfc_finish_block (&ifblock3);
4484 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4485 absX, scale);
4486 tmp = build3_v (COND_EXPR, cond, res1, res2);
4487 gfc_add_expr_to_block (&ifblock1, tmp);
4488 tmp = gfc_finish_block (&ifblock1);
4490 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
4491 arrayse.expr,
4492 gfc_build_const (type, integer_zero_node));
4494 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4495 gfc_add_expr_to_block (&block, tmp);
4497 else
4499 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
4500 gfc_add_modify (&block, resvar, tmp);
4503 gfc_add_block_to_block (&block, &arrayse.post);
4505 if (maskexpr && maskexpr->rank > 0)
4507 /* We enclose the above in if (mask) {...} . */
4509 tmp = gfc_finish_block (&block);
4510 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4511 build_empty_stmt (input_location));
4513 else
4514 tmp = gfc_finish_block (&block);
4515 gfc_add_expr_to_block (&body, tmp);
4517 gfc_trans_scalarizing_loops (ploop, &body);
4519 /* For a scalar mask, enclose the loop in an if statement. */
4520 if (maskexpr && maskexpr->rank == 0)
4522 gfc_init_block (&block);
4523 gfc_add_block_to_block (&block, &ploop->pre);
4524 gfc_add_block_to_block (&block, &ploop->post);
4525 tmp = gfc_finish_block (&block);
4527 if (expr->rank > 0)
4529 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
4530 build_empty_stmt (input_location));
4531 gfc_advance_se_ss_chain (se);
4533 else
4535 gcc_assert (expr->rank == 0);
4536 gfc_init_se (&maskse, NULL);
4537 gfc_conv_expr_val (&maskse, maskexpr);
4538 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4539 build_empty_stmt (input_location));
4542 gfc_add_expr_to_block (&block, tmp);
4543 gfc_add_block_to_block (&se->pre, &block);
4544 gcc_assert (se->post.head == NULL);
4546 else
4548 gfc_add_block_to_block (&se->pre, &ploop->pre);
4549 gfc_add_block_to_block (&se->pre, &ploop->post);
4552 if (expr->rank == 0)
4553 gfc_cleanup_loop (ploop);
4555 if (norm2)
4557 /* result = scale * sqrt(result). */
4558 tree sqrt;
4559 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
4560 resvar = build_call_expr_loc (input_location,
4561 sqrt, 1, resvar);
4562 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
4565 se->expr = resvar;
4569 /* Inline implementation of the dot_product intrinsic. This function
4570 is based on gfc_conv_intrinsic_arith (the previous function). */
4571 static void
4572 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
4574 tree resvar;
4575 tree type;
4576 stmtblock_t body;
4577 stmtblock_t block;
4578 tree tmp;
4579 gfc_loopinfo loop;
4580 gfc_actual_arglist *actual;
4581 gfc_ss *arrayss1, *arrayss2;
4582 gfc_se arrayse1, arrayse2;
4583 gfc_expr *arrayexpr1, *arrayexpr2;
4585 type = gfc_typenode_for_spec (&expr->ts);
4587 /* Initialize the result. */
4588 resvar = gfc_create_var (type, "val");
4589 if (expr->ts.type == BT_LOGICAL)
4590 tmp = build_int_cst (type, 0);
4591 else
4592 tmp = gfc_build_const (type, integer_zero_node);
4594 gfc_add_modify (&se->pre, resvar, tmp);
4596 /* Walk argument #1. */
4597 actual = expr->value.function.actual;
4598 arrayexpr1 = actual->expr;
4599 arrayss1 = gfc_walk_expr (arrayexpr1);
4600 gcc_assert (arrayss1 != gfc_ss_terminator);
4602 /* Walk argument #2. */
4603 actual = actual->next;
4604 arrayexpr2 = actual->expr;
4605 arrayss2 = gfc_walk_expr (arrayexpr2);
4606 gcc_assert (arrayss2 != gfc_ss_terminator);
4608 /* Initialize the scalarizer. */
4609 gfc_init_loopinfo (&loop);
4610 gfc_add_ss_to_loop (&loop, arrayss1);
4611 gfc_add_ss_to_loop (&loop, arrayss2);
4613 /* Initialize the loop. */
4614 gfc_conv_ss_startstride (&loop);
4615 gfc_conv_loop_setup (&loop, &expr->where);
4617 gfc_mark_ss_chain_used (arrayss1, 1);
4618 gfc_mark_ss_chain_used (arrayss2, 1);
4620 /* Generate the loop body. */
4621 gfc_start_scalarized_body (&loop, &body);
4622 gfc_init_block (&block);
4624 /* Make the tree expression for [conjg(]array1[)]. */
4625 gfc_init_se (&arrayse1, NULL);
4626 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
4627 arrayse1.ss = arrayss1;
4628 gfc_conv_expr_val (&arrayse1, arrayexpr1);
4629 if (expr->ts.type == BT_COMPLEX)
4630 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
4631 arrayse1.expr);
4632 gfc_add_block_to_block (&block, &arrayse1.pre);
4634 /* Make the tree expression for array2. */
4635 gfc_init_se (&arrayse2, NULL);
4636 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
4637 arrayse2.ss = arrayss2;
4638 gfc_conv_expr_val (&arrayse2, arrayexpr2);
4639 gfc_add_block_to_block (&block, &arrayse2.pre);
4641 /* Do the actual product and sum. */
4642 if (expr->ts.type == BT_LOGICAL)
4644 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
4645 arrayse1.expr, arrayse2.expr);
4646 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
4648 else
4650 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
4651 arrayse2.expr);
4652 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
4654 gfc_add_modify (&block, resvar, tmp);
4656 /* Finish up the loop block and the loop. */
4657 tmp = gfc_finish_block (&block);
4658 gfc_add_expr_to_block (&body, tmp);
4660 gfc_trans_scalarizing_loops (&loop, &body);
4661 gfc_add_block_to_block (&se->pre, &loop.pre);
4662 gfc_add_block_to_block (&se->pre, &loop.post);
4663 gfc_cleanup_loop (&loop);
4665 se->expr = resvar;
4669 /* Emit code for minloc or maxloc intrinsic. There are many different cases
4670 we need to handle. For performance reasons we sometimes create two
4671 loops instead of one, where the second one is much simpler.
4672 Examples for minloc intrinsic:
4673 1) Result is an array, a call is generated
4674 2) Array mask is used and NaNs need to be supported:
4675 limit = Infinity;
4676 pos = 0;
4677 S = from;
4678 while (S <= to) {
4679 if (mask[S]) {
4680 if (pos == 0) pos = S + (1 - from);
4681 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4683 S++;
4685 goto lab2;
4686 lab1:;
4687 while (S <= to) {
4688 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4689 S++;
4691 lab2:;
4692 3) NaNs need to be supported, but it is known at compile time or cheaply
4693 at runtime whether array is nonempty or not:
4694 limit = Infinity;
4695 pos = 0;
4696 S = from;
4697 while (S <= to) {
4698 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4699 S++;
4701 if (from <= to) pos = 1;
4702 goto lab2;
4703 lab1:;
4704 while (S <= to) {
4705 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4706 S++;
4708 lab2:;
4709 4) NaNs aren't supported, array mask is used:
4710 limit = infinities_supported ? Infinity : huge (limit);
4711 pos = 0;
4712 S = from;
4713 while (S <= to) {
4714 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4715 S++;
4717 goto lab2;
4718 lab1:;
4719 while (S <= to) {
4720 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4721 S++;
4723 lab2:;
4724 5) Same without array mask:
4725 limit = infinities_supported ? Infinity : huge (limit);
4726 pos = (from <= to) ? 1 : 0;
4727 S = from;
4728 while (S <= to) {
4729 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4730 S++;
4732 For 3) and 5), if mask is scalar, this all goes into a conditional,
4733 setting pos = 0; in the else branch.
4735 Since we now also support the BACK argument, instead of using
4736 if (a[S] < limit), we now use
4738 if (back)
4739 cond = a[S] <= limit;
4740 else
4741 cond = a[S] < limit;
4742 if (cond) {
4743 ....
4745 The optimizer is smart enough to move the condition out of the loop.
4746 The are now marked as unlikely to for further speedup. */
4748 static void
4749 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
4751 stmtblock_t body;
4752 stmtblock_t block;
4753 stmtblock_t ifblock;
4754 stmtblock_t elseblock;
4755 tree limit;
4756 tree type;
4757 tree tmp;
4758 tree cond;
4759 tree elsetmp;
4760 tree ifbody;
4761 tree offset;
4762 tree nonempty;
4763 tree lab1, lab2;
4764 tree b_if, b_else;
4765 gfc_loopinfo loop;
4766 gfc_actual_arglist *actual;
4767 gfc_ss *arrayss;
4768 gfc_ss *maskss;
4769 gfc_se arrayse;
4770 gfc_se maskse;
4771 gfc_expr *arrayexpr;
4772 gfc_expr *maskexpr;
4773 gfc_expr *backexpr;
4774 gfc_se backse;
4775 tree pos;
4776 int n;
4778 actual = expr->value.function.actual;
4780 /* The last argument, BACK, is passed by value. Ensure that
4781 by setting its name to %VAL. */
4782 for (gfc_actual_arglist *a = actual; a; a = a->next)
4784 if (a->next == NULL)
4785 a->name = "%VAL";
4788 if (se->ss)
4790 gfc_conv_intrinsic_funcall (se, expr);
4791 return;
4794 arrayexpr = actual->expr;
4796 /* Special case for character maxloc. Remove unneeded actual
4797 arguments, then call a library function. */
4799 if (arrayexpr->ts.type == BT_CHARACTER)
4801 gfc_actual_arglist *a, *b;
4802 a = actual;
4803 while (a->next)
4805 b = a->next;
4806 if (b->expr == NULL || strcmp (b->name, "dim") == 0)
4808 a->next = b->next;
4809 b->next = NULL;
4810 gfc_free_actual_arglist (b);
4812 else
4813 a = b;
4815 gfc_conv_intrinsic_funcall (se, expr);
4816 return;
4819 /* Initialize the result. */
4820 pos = gfc_create_var (gfc_array_index_type, "pos");
4821 offset = gfc_create_var (gfc_array_index_type, "offset");
4822 type = gfc_typenode_for_spec (&expr->ts);
4824 /* Walk the arguments. */
4825 arrayss = gfc_walk_expr (arrayexpr);
4826 gcc_assert (arrayss != gfc_ss_terminator);
4828 actual = actual->next->next;
4829 gcc_assert (actual);
4830 maskexpr = actual->expr;
4831 backexpr = actual->next->next->expr;
4832 nonempty = NULL;
4833 if (maskexpr && maskexpr->rank != 0)
4835 maskss = gfc_walk_expr (maskexpr);
4836 gcc_assert (maskss != gfc_ss_terminator);
4838 else
4840 mpz_t asize;
4841 if (gfc_array_size (arrayexpr, &asize))
4843 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
4844 mpz_clear (asize);
4845 nonempty = fold_build2_loc (input_location, GT_EXPR,
4846 logical_type_node, nonempty,
4847 gfc_index_zero_node);
4849 maskss = NULL;
4852 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
4853 switch (arrayexpr->ts.type)
4855 case BT_REAL:
4856 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
4857 break;
4859 case BT_INTEGER:
4860 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
4861 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
4862 arrayexpr->ts.kind);
4863 break;
4865 default:
4866 gcc_unreachable ();
4869 /* We start with the most negative possible value for MAXLOC, and the most
4870 positive possible value for MINLOC. The most negative possible value is
4871 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
4872 possible value is HUGE in both cases. */
4873 if (op == GT_EXPR)
4874 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
4875 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
4876 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
4877 build_int_cst (TREE_TYPE (tmp), 1));
4879 gfc_add_modify (&se->pre, limit, tmp);
4881 /* Initialize the scalarizer. */
4882 gfc_init_loopinfo (&loop);
4883 gfc_add_ss_to_loop (&loop, arrayss);
4884 if (maskss)
4885 gfc_add_ss_to_loop (&loop, maskss);
4887 /* Initialize the loop. */
4888 gfc_conv_ss_startstride (&loop);
4890 /* The code generated can have more than one loop in sequence (see the
4891 comment at the function header). This doesn't work well with the
4892 scalarizer, which changes arrays' offset when the scalarization loops
4893 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
4894 are currently inlined in the scalar case only (for which loop is of rank
4895 one). As there is no dependency to care about in that case, there is no
4896 temporary, so that we can use the scalarizer temporary code to handle
4897 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
4898 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
4899 to restore offset.
4900 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
4901 should eventually go away. We could either create two loops properly,
4902 or find another way to save/restore the array offsets between the two
4903 loops (without conflicting with temporary management), or use a single
4904 loop minmaxloc implementation. See PR 31067. */
4905 loop.temp_dim = loop.dimen;
4906 gfc_conv_loop_setup (&loop, &expr->where);
4908 gcc_assert (loop.dimen == 1);
4909 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
4910 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
4911 loop.from[0], loop.to[0]);
4913 lab1 = NULL;
4914 lab2 = NULL;
4915 /* Initialize the position to zero, following Fortran 2003. We are free
4916 to do this because Fortran 95 allows the result of an entirely false
4917 mask to be processor dependent. If we know at compile time the array
4918 is non-empty and no MASK is used, we can initialize to 1 to simplify
4919 the inner loop. */
4920 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
4921 gfc_add_modify (&loop.pre, pos,
4922 fold_build3_loc (input_location, COND_EXPR,
4923 gfc_array_index_type,
4924 nonempty, gfc_index_one_node,
4925 gfc_index_zero_node));
4926 else
4928 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
4929 lab1 = gfc_build_label_decl (NULL_TREE);
4930 TREE_USED (lab1) = 1;
4931 lab2 = gfc_build_label_decl (NULL_TREE);
4932 TREE_USED (lab2) = 1;
4935 /* An offset must be added to the loop
4936 counter to obtain the required position. */
4937 gcc_assert (loop.from[0]);
4939 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4940 gfc_index_one_node, loop.from[0]);
4941 gfc_add_modify (&loop.pre, offset, tmp);
4943 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
4944 if (maskss)
4945 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
4946 /* Generate the loop body. */
4947 gfc_start_scalarized_body (&loop, &body);
4949 /* If we have a mask, only check this element if the mask is set. */
4950 if (maskss)
4952 gfc_init_se (&maskse, NULL);
4953 gfc_copy_loopinfo_to_se (&maskse, &loop);
4954 maskse.ss = maskss;
4955 gfc_conv_expr_val (&maskse, maskexpr);
4956 gfc_add_block_to_block (&body, &maskse.pre);
4958 gfc_start_block (&block);
4960 else
4961 gfc_init_block (&block);
4963 /* Compare with the current limit. */
4964 gfc_init_se (&arrayse, NULL);
4965 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4966 arrayse.ss = arrayss;
4967 gfc_conv_expr_val (&arrayse, arrayexpr);
4968 gfc_add_block_to_block (&block, &arrayse.pre);
4970 gfc_init_se (&backse, NULL);
4971 gfc_conv_expr_val (&backse, backexpr);
4972 gfc_add_block_to_block (&block, &backse.pre);
4974 /* We do the following if this is a more extreme value. */
4975 gfc_start_block (&ifblock);
4977 /* Assign the value to the limit... */
4978 gfc_add_modify (&ifblock, limit, arrayse.expr);
4980 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
4982 stmtblock_t ifblock2;
4983 tree ifbody2;
4985 gfc_start_block (&ifblock2);
4986 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4987 loop.loopvar[0], offset);
4988 gfc_add_modify (&ifblock2, pos, tmp);
4989 ifbody2 = gfc_finish_block (&ifblock2);
4990 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pos,
4991 gfc_index_zero_node);
4992 tmp = build3_v (COND_EXPR, cond, ifbody2,
4993 build_empty_stmt (input_location));
4994 gfc_add_expr_to_block (&block, tmp);
4997 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4998 loop.loopvar[0], offset);
4999 gfc_add_modify (&ifblock, pos, tmp);
5001 if (lab1)
5002 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
5004 ifbody = gfc_finish_block (&ifblock);
5006 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
5008 if (lab1)
5009 cond = fold_build2_loc (input_location,
5010 op == GT_EXPR ? GE_EXPR : LE_EXPR,
5011 logical_type_node, arrayse.expr, limit);
5012 else
5014 tree ifbody2, elsebody2;
5016 /* We switch to > or >= depending on the value of the BACK argument. */
5017 cond = gfc_create_var (logical_type_node, "cond");
5019 gfc_start_block (&ifblock);
5020 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5021 logical_type_node, arrayse.expr, limit);
5023 gfc_add_modify (&ifblock, cond, b_if);
5024 ifbody2 = gfc_finish_block (&ifblock);
5026 gfc_start_block (&elseblock);
5027 b_else = fold_build2_loc (input_location, op, logical_type_node,
5028 arrayse.expr, limit);
5030 gfc_add_modify (&elseblock, cond, b_else);
5031 elsebody2 = gfc_finish_block (&elseblock);
5033 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5034 backse.expr, ifbody2, elsebody2);
5036 gfc_add_expr_to_block (&block, tmp);
5039 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5040 ifbody = build3_v (COND_EXPR, cond, ifbody,
5041 build_empty_stmt (input_location));
5043 gfc_add_expr_to_block (&block, ifbody);
5045 if (maskss)
5047 /* We enclose the above in if (mask) {...}. */
5048 tmp = gfc_finish_block (&block);
5050 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5051 build_empty_stmt (input_location));
5053 else
5054 tmp = gfc_finish_block (&block);
5055 gfc_add_expr_to_block (&body, tmp);
5057 if (lab1)
5059 gfc_trans_scalarized_loop_boundary (&loop, &body);
5061 if (HONOR_NANS (DECL_MODE (limit)))
5063 if (nonempty != NULL)
5065 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
5066 tmp = build3_v (COND_EXPR, nonempty, ifbody,
5067 build_empty_stmt (input_location));
5068 gfc_add_expr_to_block (&loop.code[0], tmp);
5072 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
5073 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
5075 /* If we have a mask, only check this element if the mask is set. */
5076 if (maskss)
5078 gfc_init_se (&maskse, NULL);
5079 gfc_copy_loopinfo_to_se (&maskse, &loop);
5080 maskse.ss = maskss;
5081 gfc_conv_expr_val (&maskse, maskexpr);
5082 gfc_add_block_to_block (&body, &maskse.pre);
5084 gfc_start_block (&block);
5086 else
5087 gfc_init_block (&block);
5089 /* Compare with the current limit. */
5090 gfc_init_se (&arrayse, NULL);
5091 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5092 arrayse.ss = arrayss;
5093 gfc_conv_expr_val (&arrayse, arrayexpr);
5094 gfc_add_block_to_block (&block, &arrayse.pre);
5096 /* We do the following if this is a more extreme value. */
5097 gfc_start_block (&ifblock);
5099 /* Assign the value to the limit... */
5100 gfc_add_modify (&ifblock, limit, arrayse.expr);
5102 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
5103 loop.loopvar[0], offset);
5104 gfc_add_modify (&ifblock, pos, tmp);
5106 ifbody = gfc_finish_block (&ifblock);
5108 /* We switch to > or >= depending on the value of the BACK argument. */
5110 tree ifbody2, elsebody2;
5112 cond = gfc_create_var (logical_type_node, "cond");
5114 gfc_start_block (&ifblock);
5115 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5116 logical_type_node, arrayse.expr, limit);
5118 gfc_add_modify (&ifblock, cond, b_if);
5119 ifbody2 = gfc_finish_block (&ifblock);
5121 gfc_start_block (&elseblock);
5122 b_else = fold_build2_loc (input_location, op, logical_type_node,
5123 arrayse.expr, limit);
5125 gfc_add_modify (&elseblock, cond, b_else);
5126 elsebody2 = gfc_finish_block (&elseblock);
5128 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5129 backse.expr, ifbody2, elsebody2);
5132 gfc_add_expr_to_block (&block, tmp);
5133 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5134 tmp = build3_v (COND_EXPR, cond, ifbody,
5135 build_empty_stmt (input_location));
5137 gfc_add_expr_to_block (&block, tmp);
5139 if (maskss)
5141 /* We enclose the above in if (mask) {...}. */
5142 tmp = gfc_finish_block (&block);
5144 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5145 build_empty_stmt (input_location));
5147 else
5148 tmp = gfc_finish_block (&block);
5149 gfc_add_expr_to_block (&body, tmp);
5150 /* Avoid initializing loopvar[0] again, it should be left where
5151 it finished by the first loop. */
5152 loop.from[0] = loop.loopvar[0];
5155 gfc_trans_scalarizing_loops (&loop, &body);
5157 if (lab2)
5158 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
5160 /* For a scalar mask, enclose the loop in an if statement. */
5161 if (maskexpr && maskss == NULL)
5163 gfc_init_se (&maskse, NULL);
5164 gfc_conv_expr_val (&maskse, maskexpr);
5165 gfc_init_block (&block);
5166 gfc_add_block_to_block (&block, &loop.pre);
5167 gfc_add_block_to_block (&block, &loop.post);
5168 tmp = gfc_finish_block (&block);
5170 /* For the else part of the scalar mask, just initialize
5171 the pos variable the same way as above. */
5173 gfc_init_block (&elseblock);
5174 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
5175 elsetmp = gfc_finish_block (&elseblock);
5177 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
5178 gfc_add_expr_to_block (&block, tmp);
5179 gfc_add_block_to_block (&se->pre, &block);
5181 else
5183 gfc_add_block_to_block (&se->pre, &loop.pre);
5184 gfc_add_block_to_block (&se->pre, &loop.post);
5186 gfc_cleanup_loop (&loop);
5188 se->expr = convert (type, pos);
5191 /* Emit code for minval or maxval intrinsic. There are many different cases
5192 we need to handle. For performance reasons we sometimes create two
5193 loops instead of one, where the second one is much simpler.
5194 Examples for minval intrinsic:
5195 1) Result is an array, a call is generated
5196 2) Array mask is used and NaNs need to be supported, rank 1:
5197 limit = Infinity;
5198 nonempty = false;
5199 S = from;
5200 while (S <= to) {
5201 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
5202 S++;
5204 limit = nonempty ? NaN : huge (limit);
5205 lab:
5206 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
5207 3) NaNs need to be supported, but it is known at compile time or cheaply
5208 at runtime whether array is nonempty or not, rank 1:
5209 limit = Infinity;
5210 S = from;
5211 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
5212 limit = (from <= to) ? NaN : huge (limit);
5213 lab:
5214 while (S <= to) { limit = min (a[S], limit); S++; }
5215 4) Array mask is used and NaNs need to be supported, rank > 1:
5216 limit = Infinity;
5217 nonempty = false;
5218 fast = false;
5219 S1 = from1;
5220 while (S1 <= to1) {
5221 S2 = from2;
5222 while (S2 <= to2) {
5223 if (mask[S1][S2]) {
5224 if (fast) limit = min (a[S1][S2], limit);
5225 else {
5226 nonempty = true;
5227 if (a[S1][S2] <= limit) {
5228 limit = a[S1][S2];
5229 fast = true;
5233 S2++;
5235 S1++;
5237 if (!fast)
5238 limit = nonempty ? NaN : huge (limit);
5239 5) NaNs need to be supported, but it is known at compile time or cheaply
5240 at runtime whether array is nonempty or not, rank > 1:
5241 limit = Infinity;
5242 fast = false;
5243 S1 = from1;
5244 while (S1 <= to1) {
5245 S2 = from2;
5246 while (S2 <= to2) {
5247 if (fast) limit = min (a[S1][S2], limit);
5248 else {
5249 if (a[S1][S2] <= limit) {
5250 limit = a[S1][S2];
5251 fast = true;
5254 S2++;
5256 S1++;
5258 if (!fast)
5259 limit = (nonempty_array) ? NaN : huge (limit);
5260 6) NaNs aren't supported, but infinities are. Array mask is used:
5261 limit = Infinity;
5262 nonempty = false;
5263 S = from;
5264 while (S <= to) {
5265 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
5266 S++;
5268 limit = nonempty ? limit : huge (limit);
5269 7) Same without array mask:
5270 limit = Infinity;
5271 S = from;
5272 while (S <= to) { limit = min (a[S], limit); S++; }
5273 limit = (from <= to) ? limit : huge (limit);
5274 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
5275 limit = huge (limit);
5276 S = from;
5277 while (S <= to) { limit = min (a[S], limit); S++); }
5279 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
5280 with array mask instead).
5281 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
5282 setting limit = huge (limit); in the else branch. */
5284 static void
5285 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
5287 tree limit;
5288 tree type;
5289 tree tmp;
5290 tree ifbody;
5291 tree nonempty;
5292 tree nonempty_var;
5293 tree lab;
5294 tree fast;
5295 tree huge_cst = NULL, nan_cst = NULL;
5296 stmtblock_t body;
5297 stmtblock_t block, block2;
5298 gfc_loopinfo loop;
5299 gfc_actual_arglist *actual;
5300 gfc_ss *arrayss;
5301 gfc_ss *maskss;
5302 gfc_se arrayse;
5303 gfc_se maskse;
5304 gfc_expr *arrayexpr;
5305 gfc_expr *maskexpr;
5306 int n;
5308 if (se->ss)
5310 gfc_conv_intrinsic_funcall (se, expr);
5311 return;
5314 actual = expr->value.function.actual;
5315 arrayexpr = actual->expr;
5317 if (arrayexpr->ts.type == BT_CHARACTER)
5319 gfc_actual_arglist *a2, *a3;
5320 a2 = actual->next; /* dim */
5321 a3 = a2->next; /* mask */
5322 if (a2->expr == NULL || expr->rank == 0)
5324 if (a3->expr == NULL)
5325 actual->next = NULL;
5326 else
5328 actual->next = a3;
5329 a2->next = NULL;
5331 gfc_free_actual_arglist (a2);
5333 else
5334 if (a3->expr == NULL)
5336 a2->next = NULL;
5337 gfc_free_actual_arglist (a3);
5339 gfc_conv_intrinsic_funcall (se, expr);
5340 return;
5342 type = gfc_typenode_for_spec (&expr->ts);
5343 /* Initialize the result. */
5344 limit = gfc_create_var (type, "limit");
5345 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
5346 switch (expr->ts.type)
5348 case BT_REAL:
5349 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
5350 expr->ts.kind, 0);
5351 if (HONOR_INFINITIES (DECL_MODE (limit)))
5353 REAL_VALUE_TYPE real;
5354 real_inf (&real);
5355 tmp = build_real (type, real);
5357 else
5358 tmp = huge_cst;
5359 if (HONOR_NANS (DECL_MODE (limit)))
5360 nan_cst = gfc_build_nan (type, "");
5361 break;
5363 case BT_INTEGER:
5364 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
5365 break;
5367 default:
5368 gcc_unreachable ();
5371 /* We start with the most negative possible value for MAXVAL, and the most
5372 positive possible value for MINVAL. The most negative possible value is
5373 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5374 possible value is HUGE in both cases. */
5375 if (op == GT_EXPR)
5377 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
5378 if (huge_cst)
5379 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
5380 TREE_TYPE (huge_cst), huge_cst);
5383 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
5384 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
5385 tmp, build_int_cst (type, 1));
5387 gfc_add_modify (&se->pre, limit, tmp);
5389 /* Walk the arguments. */
5390 arrayss = gfc_walk_expr (arrayexpr);
5391 gcc_assert (arrayss != gfc_ss_terminator);
5393 actual = actual->next->next;
5394 gcc_assert (actual);
5395 maskexpr = actual->expr;
5396 nonempty = NULL;
5397 if (maskexpr && maskexpr->rank != 0)
5399 maskss = gfc_walk_expr (maskexpr);
5400 gcc_assert (maskss != gfc_ss_terminator);
5402 else
5404 mpz_t asize;
5405 if (gfc_array_size (arrayexpr, &asize))
5407 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
5408 mpz_clear (asize);
5409 nonempty = fold_build2_loc (input_location, GT_EXPR,
5410 logical_type_node, nonempty,
5411 gfc_index_zero_node);
5413 maskss = NULL;
5416 /* Initialize the scalarizer. */
5417 gfc_init_loopinfo (&loop);
5418 gfc_add_ss_to_loop (&loop, arrayss);
5419 if (maskss)
5420 gfc_add_ss_to_loop (&loop, maskss);
5422 /* Initialize the loop. */
5423 gfc_conv_ss_startstride (&loop);
5425 /* The code generated can have more than one loop in sequence (see the
5426 comment at the function header). This doesn't work well with the
5427 scalarizer, which changes arrays' offset when the scalarization loops
5428 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
5429 are currently inlined in the scalar case only. As there is no dependency
5430 to care about in that case, there is no temporary, so that we can use the
5431 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
5432 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
5433 gfc_trans_scalarized_loop_boundary even later to restore offset.
5434 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
5435 should eventually go away. We could either create two loops properly,
5436 or find another way to save/restore the array offsets between the two
5437 loops (without conflicting with temporary management), or use a single
5438 loop minmaxval implementation. See PR 31067. */
5439 loop.temp_dim = loop.dimen;
5440 gfc_conv_loop_setup (&loop, &expr->where);
5442 if (nonempty == NULL && maskss == NULL
5443 && loop.dimen == 1 && loop.from[0] && loop.to[0])
5444 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
5445 loop.from[0], loop.to[0]);
5446 nonempty_var = NULL;
5447 if (nonempty == NULL
5448 && (HONOR_INFINITIES (DECL_MODE (limit))
5449 || HONOR_NANS (DECL_MODE (limit))))
5451 nonempty_var = gfc_create_var (logical_type_node, "nonempty");
5452 gfc_add_modify (&se->pre, nonempty_var, logical_false_node);
5453 nonempty = nonempty_var;
5455 lab = NULL;
5456 fast = NULL;
5457 if (HONOR_NANS (DECL_MODE (limit)))
5459 if (loop.dimen == 1)
5461 lab = gfc_build_label_decl (NULL_TREE);
5462 TREE_USED (lab) = 1;
5464 else
5466 fast = gfc_create_var (logical_type_node, "fast");
5467 gfc_add_modify (&se->pre, fast, logical_false_node);
5471 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
5472 if (maskss)
5473 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
5474 /* Generate the loop body. */
5475 gfc_start_scalarized_body (&loop, &body);
5477 /* If we have a mask, only add this element if the mask is set. */
5478 if (maskss)
5480 gfc_init_se (&maskse, NULL);
5481 gfc_copy_loopinfo_to_se (&maskse, &loop);
5482 maskse.ss = maskss;
5483 gfc_conv_expr_val (&maskse, maskexpr);
5484 gfc_add_block_to_block (&body, &maskse.pre);
5486 gfc_start_block (&block);
5488 else
5489 gfc_init_block (&block);
5491 /* Compare with the current limit. */
5492 gfc_init_se (&arrayse, NULL);
5493 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5494 arrayse.ss = arrayss;
5495 gfc_conv_expr_val (&arrayse, arrayexpr);
5496 gfc_add_block_to_block (&block, &arrayse.pre);
5498 gfc_init_block (&block2);
5500 if (nonempty_var)
5501 gfc_add_modify (&block2, nonempty_var, logical_true_node);
5503 if (HONOR_NANS (DECL_MODE (limit)))
5505 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5506 logical_type_node, arrayse.expr, limit);
5507 if (lab)
5508 ifbody = build1_v (GOTO_EXPR, lab);
5509 else
5511 stmtblock_t ifblock;
5513 gfc_init_block (&ifblock);
5514 gfc_add_modify (&ifblock, limit, arrayse.expr);
5515 gfc_add_modify (&ifblock, fast, logical_true_node);
5516 ifbody = gfc_finish_block (&ifblock);
5518 tmp = build3_v (COND_EXPR, tmp, ifbody,
5519 build_empty_stmt (input_location));
5520 gfc_add_expr_to_block (&block2, tmp);
5522 else
5524 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5525 signed zeros. */
5526 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5528 tmp = fold_build2_loc (input_location, op, logical_type_node,
5529 arrayse.expr, limit);
5530 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5531 tmp = build3_v (COND_EXPR, tmp, ifbody,
5532 build_empty_stmt (input_location));
5533 gfc_add_expr_to_block (&block2, tmp);
5535 else
5537 tmp = fold_build2_loc (input_location,
5538 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5539 type, arrayse.expr, limit);
5540 gfc_add_modify (&block2, limit, tmp);
5544 if (fast)
5546 tree elsebody = gfc_finish_block (&block2);
5548 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5549 signed zeros. */
5550 if (HONOR_NANS (DECL_MODE (limit))
5551 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5553 tmp = fold_build2_loc (input_location, op, logical_type_node,
5554 arrayse.expr, limit);
5555 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5556 ifbody = build3_v (COND_EXPR, tmp, ifbody,
5557 build_empty_stmt (input_location));
5559 else
5561 tmp = fold_build2_loc (input_location,
5562 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5563 type, arrayse.expr, limit);
5564 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5566 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
5567 gfc_add_expr_to_block (&block, tmp);
5569 else
5570 gfc_add_block_to_block (&block, &block2);
5572 gfc_add_block_to_block (&block, &arrayse.post);
5574 tmp = gfc_finish_block (&block);
5575 if (maskss)
5576 /* We enclose the above in if (mask) {...}. */
5577 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5578 build_empty_stmt (input_location));
5579 gfc_add_expr_to_block (&body, tmp);
5581 if (lab)
5583 gfc_trans_scalarized_loop_boundary (&loop, &body);
5585 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5586 nan_cst, huge_cst);
5587 gfc_add_modify (&loop.code[0], limit, tmp);
5588 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
5590 /* If we have a mask, only add this element if the mask is set. */
5591 if (maskss)
5593 gfc_init_se (&maskse, NULL);
5594 gfc_copy_loopinfo_to_se (&maskse, &loop);
5595 maskse.ss = maskss;
5596 gfc_conv_expr_val (&maskse, maskexpr);
5597 gfc_add_block_to_block (&body, &maskse.pre);
5599 gfc_start_block (&block);
5601 else
5602 gfc_init_block (&block);
5604 /* Compare with the current limit. */
5605 gfc_init_se (&arrayse, NULL);
5606 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5607 arrayse.ss = arrayss;
5608 gfc_conv_expr_val (&arrayse, arrayexpr);
5609 gfc_add_block_to_block (&block, &arrayse.pre);
5611 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5612 signed zeros. */
5613 if (HONOR_NANS (DECL_MODE (limit))
5614 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5616 tmp = fold_build2_loc (input_location, op, logical_type_node,
5617 arrayse.expr, limit);
5618 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5619 tmp = build3_v (COND_EXPR, tmp, ifbody,
5620 build_empty_stmt (input_location));
5621 gfc_add_expr_to_block (&block, tmp);
5623 else
5625 tmp = fold_build2_loc (input_location,
5626 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5627 type, arrayse.expr, limit);
5628 gfc_add_modify (&block, limit, tmp);
5631 gfc_add_block_to_block (&block, &arrayse.post);
5633 tmp = gfc_finish_block (&block);
5634 if (maskss)
5635 /* We enclose the above in if (mask) {...}. */
5636 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5637 build_empty_stmt (input_location));
5638 gfc_add_expr_to_block (&body, tmp);
5639 /* Avoid initializing loopvar[0] again, it should be left where
5640 it finished by the first loop. */
5641 loop.from[0] = loop.loopvar[0];
5643 gfc_trans_scalarizing_loops (&loop, &body);
5645 if (fast)
5647 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5648 nan_cst, huge_cst);
5649 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5650 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
5651 ifbody);
5652 gfc_add_expr_to_block (&loop.pre, tmp);
5654 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
5656 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
5657 huge_cst);
5658 gfc_add_modify (&loop.pre, limit, tmp);
5661 /* For a scalar mask, enclose the loop in an if statement. */
5662 if (maskexpr && maskss == NULL)
5664 tree else_stmt;
5666 gfc_init_se (&maskse, NULL);
5667 gfc_conv_expr_val (&maskse, maskexpr);
5668 gfc_init_block (&block);
5669 gfc_add_block_to_block (&block, &loop.pre);
5670 gfc_add_block_to_block (&block, &loop.post);
5671 tmp = gfc_finish_block (&block);
5673 if (HONOR_INFINITIES (DECL_MODE (limit)))
5674 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
5675 else
5676 else_stmt = build_empty_stmt (input_location);
5677 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
5678 gfc_add_expr_to_block (&block, tmp);
5679 gfc_add_block_to_block (&se->pre, &block);
5681 else
5683 gfc_add_block_to_block (&se->pre, &loop.pre);
5684 gfc_add_block_to_block (&se->pre, &loop.post);
5687 gfc_cleanup_loop (&loop);
5689 se->expr = limit;
5692 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
5693 static void
5694 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
5696 tree args[2];
5697 tree type;
5698 tree tmp;
5700 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5701 type = TREE_TYPE (args[0]);
5703 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5704 build_int_cst (type, 1), args[1]);
5705 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
5706 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
5707 build_int_cst (type, 0));
5708 type = gfc_typenode_for_spec (&expr->ts);
5709 se->expr = convert (type, tmp);
5713 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
5714 static void
5715 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
5717 tree args[2];
5719 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5721 /* Convert both arguments to the unsigned type of the same size. */
5722 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
5723 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
5725 /* If they have unequal type size, convert to the larger one. */
5726 if (TYPE_PRECISION (TREE_TYPE (args[0]))
5727 > TYPE_PRECISION (TREE_TYPE (args[1])))
5728 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
5729 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
5730 > TYPE_PRECISION (TREE_TYPE (args[0])))
5731 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
5733 /* Now, we compare them. */
5734 se->expr = fold_build2_loc (input_location, op, logical_type_node,
5735 args[0], args[1]);
5739 /* Generate code to perform the specified operation. */
5740 static void
5741 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
5743 tree args[2];
5745 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5746 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
5747 args[0], args[1]);
5750 /* Bitwise not. */
5751 static void
5752 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
5754 tree arg;
5756 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5757 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
5758 TREE_TYPE (arg), arg);
5761 /* Set or clear a single bit. */
5762 static void
5763 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
5765 tree args[2];
5766 tree type;
5767 tree tmp;
5768 enum tree_code op;
5770 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5771 type = TREE_TYPE (args[0]);
5773 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5774 build_int_cst (type, 1), args[1]);
5775 if (set)
5776 op = BIT_IOR_EXPR;
5777 else
5779 op = BIT_AND_EXPR;
5780 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
5782 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
5785 /* Extract a sequence of bits.
5786 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
5787 static void
5788 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
5790 tree args[3];
5791 tree type;
5792 tree tmp;
5793 tree mask;
5795 gfc_conv_intrinsic_function_args (se, expr, args, 3);
5796 type = TREE_TYPE (args[0]);
5798 mask = build_int_cst (type, -1);
5799 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
5800 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
5802 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
5804 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
5807 static void
5808 gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
5810 gfc_actual_arglist *s, *k;
5811 gfc_expr *e;
5813 /* Remove the KIND argument, if present. */
5814 s = expr->value.function.actual;
5815 k = s->next;
5816 e = k->expr;
5817 gfc_free_expr (e);
5818 k->expr = NULL;
5820 gfc_conv_intrinsic_funcall (se, expr);
5823 static void
5824 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
5825 bool arithmetic)
5827 tree args[2], type, num_bits, cond;
5829 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5831 args[0] = gfc_evaluate_now (args[0], &se->pre);
5832 args[1] = gfc_evaluate_now (args[1], &se->pre);
5833 type = TREE_TYPE (args[0]);
5835 if (!arithmetic)
5836 args[0] = fold_convert (unsigned_type_for (type), args[0]);
5837 else
5838 gcc_assert (right_shift);
5840 se->expr = fold_build2_loc (input_location,
5841 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
5842 TREE_TYPE (args[0]), args[0], args[1]);
5844 if (!arithmetic)
5845 se->expr = fold_convert (type, se->expr);
5847 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5848 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5849 special case. */
5850 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
5851 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
5852 args[1], num_bits);
5854 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5855 build_int_cst (type, 0), se->expr);
5858 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
5860 : ((shift >= 0) ? i << shift : i >> -shift)
5861 where all shifts are logical shifts. */
5862 static void
5863 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
5865 tree args[2];
5866 tree type;
5867 tree utype;
5868 tree tmp;
5869 tree width;
5870 tree num_bits;
5871 tree cond;
5872 tree lshift;
5873 tree rshift;
5875 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5877 args[0] = gfc_evaluate_now (args[0], &se->pre);
5878 args[1] = gfc_evaluate_now (args[1], &se->pre);
5880 type = TREE_TYPE (args[0]);
5881 utype = unsigned_type_for (type);
5883 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
5884 args[1]);
5886 /* Left shift if positive. */
5887 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
5889 /* Right shift if negative.
5890 We convert to an unsigned type because we want a logical shift.
5891 The standard doesn't define the case of shifting negative
5892 numbers, and we try to be compatible with other compilers, most
5893 notably g77, here. */
5894 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
5895 utype, convert (utype, args[0]), width));
5897 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[1],
5898 build_int_cst (TREE_TYPE (args[1]), 0));
5899 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
5901 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5902 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5903 special case. */
5904 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
5905 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, width,
5906 num_bits);
5907 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5908 build_int_cst (type, 0), tmp);
5912 /* Circular shift. AKA rotate or barrel shift. */
5914 static void
5915 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
5917 tree *args;
5918 tree type;
5919 tree tmp;
5920 tree lrot;
5921 tree rrot;
5922 tree zero;
5923 unsigned int num_args;
5925 num_args = gfc_intrinsic_argument_list_length (expr);
5926 args = XALLOCAVEC (tree, num_args);
5928 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
5930 if (num_args == 3)
5932 /* Use a library function for the 3 parameter version. */
5933 tree int4type = gfc_get_int_type (4);
5935 type = TREE_TYPE (args[0]);
5936 /* We convert the first argument to at least 4 bytes, and
5937 convert back afterwards. This removes the need for library
5938 functions for all argument sizes, and function will be
5939 aligned to at least 32 bits, so there's no loss. */
5940 if (expr->ts.kind < 4)
5941 args[0] = convert (int4type, args[0]);
5943 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
5944 need loads of library functions. They cannot have values >
5945 BIT_SIZE (I) so the conversion is safe. */
5946 args[1] = convert (int4type, args[1]);
5947 args[2] = convert (int4type, args[2]);
5949 switch (expr->ts.kind)
5951 case 1:
5952 case 2:
5953 case 4:
5954 tmp = gfor_fndecl_math_ishftc4;
5955 break;
5956 case 8:
5957 tmp = gfor_fndecl_math_ishftc8;
5958 break;
5959 case 16:
5960 tmp = gfor_fndecl_math_ishftc16;
5961 break;
5962 default:
5963 gcc_unreachable ();
5965 se->expr = build_call_expr_loc (input_location,
5966 tmp, 3, args[0], args[1], args[2]);
5967 /* Convert the result back to the original type, if we extended
5968 the first argument's width above. */
5969 if (expr->ts.kind < 4)
5970 se->expr = convert (type, se->expr);
5972 return;
5974 type = TREE_TYPE (args[0]);
5976 /* Evaluate arguments only once. */
5977 args[0] = gfc_evaluate_now (args[0], &se->pre);
5978 args[1] = gfc_evaluate_now (args[1], &se->pre);
5980 /* Rotate left if positive. */
5981 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
5983 /* Rotate right if negative. */
5984 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
5985 args[1]);
5986 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
5988 zero = build_int_cst (TREE_TYPE (args[1]), 0);
5989 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, args[1],
5990 zero);
5991 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
5993 /* Do nothing if shift == 0. */
5994 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, args[1],
5995 zero);
5996 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
5997 rrot);
6001 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
6002 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
6004 The conditional expression is necessary because the result of LEADZ(0)
6005 is defined, but the result of __builtin_clz(0) is undefined for most
6006 targets.
6008 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
6009 difference in bit size between the argument of LEADZ and the C int. */
6011 static void
6012 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
6014 tree arg;
6015 tree arg_type;
6016 tree cond;
6017 tree result_type;
6018 tree leadz;
6019 tree bit_size;
6020 tree tmp;
6021 tree func;
6022 int s, argsize;
6024 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6025 argsize = TYPE_PRECISION (TREE_TYPE (arg));
6027 /* Which variant of __builtin_clz* should we call? */
6028 if (argsize <= INT_TYPE_SIZE)
6030 arg_type = unsigned_type_node;
6031 func = builtin_decl_explicit (BUILT_IN_CLZ);
6033 else if (argsize <= LONG_TYPE_SIZE)
6035 arg_type = long_unsigned_type_node;
6036 func = builtin_decl_explicit (BUILT_IN_CLZL);
6038 else if (argsize <= LONG_LONG_TYPE_SIZE)
6040 arg_type = long_long_unsigned_type_node;
6041 func = builtin_decl_explicit (BUILT_IN_CLZLL);
6043 else
6045 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6046 arg_type = gfc_build_uint_type (argsize);
6047 func = NULL_TREE;
6050 /* Convert the actual argument twice: first, to the unsigned type of the
6051 same size; then, to the proper argument type for the built-in
6052 function. But the return type is of the default INTEGER kind. */
6053 arg = fold_convert (gfc_build_uint_type (argsize), arg);
6054 arg = fold_convert (arg_type, arg);
6055 arg = gfc_evaluate_now (arg, &se->pre);
6056 result_type = gfc_get_int_type (gfc_default_integer_kind);
6058 /* Compute LEADZ for the case i .ne. 0. */
6059 if (func)
6061 s = TYPE_PRECISION (arg_type) - argsize;
6062 tmp = fold_convert (result_type,
6063 build_call_expr_loc (input_location, func,
6064 1, arg));
6065 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
6066 tmp, build_int_cst (result_type, s));
6068 else
6070 /* We end up here if the argument type is larger than 'long long'.
6071 We generate this code:
6073 if (x & (ULL_MAX << ULL_SIZE) != 0)
6074 return clzll ((unsigned long long) (x >> ULLSIZE));
6075 else
6076 return ULL_SIZE + clzll ((unsigned long long) x);
6077 where ULL_MAX is the largest value that a ULL_MAX can hold
6078 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
6079 is the bit-size of the long long type (64 in this example). */
6080 tree ullsize, ullmax, tmp1, tmp2, btmp;
6082 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
6083 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
6084 long_long_unsigned_type_node,
6085 build_int_cst (long_long_unsigned_type_node,
6086 0));
6088 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
6089 fold_convert (arg_type, ullmax), ullsize);
6090 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
6091 arg, cond);
6092 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6093 cond, build_int_cst (arg_type, 0));
6095 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
6096 arg, ullsize);
6097 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
6098 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
6099 tmp1 = fold_convert (result_type,
6100 build_call_expr_loc (input_location, btmp, 1, tmp1));
6102 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
6103 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
6104 tmp2 = fold_convert (result_type,
6105 build_call_expr_loc (input_location, btmp, 1, tmp2));
6106 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6107 tmp2, ullsize);
6109 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
6110 cond, tmp1, tmp2);
6113 /* Build BIT_SIZE. */
6114 bit_size = build_int_cst (result_type, argsize);
6116 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6117 arg, build_int_cst (arg_type, 0));
6118 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
6119 bit_size, leadz);
6123 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
6125 The conditional expression is necessary because the result of TRAILZ(0)
6126 is defined, but the result of __builtin_ctz(0) is undefined for most
6127 targets. */
6129 static void
6130 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
6132 tree arg;
6133 tree arg_type;
6134 tree cond;
6135 tree result_type;
6136 tree trailz;
6137 tree bit_size;
6138 tree func;
6139 int argsize;
6141 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6142 argsize = TYPE_PRECISION (TREE_TYPE (arg));
6144 /* Which variant of __builtin_ctz* should we call? */
6145 if (argsize <= INT_TYPE_SIZE)
6147 arg_type = unsigned_type_node;
6148 func = builtin_decl_explicit (BUILT_IN_CTZ);
6150 else if (argsize <= LONG_TYPE_SIZE)
6152 arg_type = long_unsigned_type_node;
6153 func = builtin_decl_explicit (BUILT_IN_CTZL);
6155 else if (argsize <= LONG_LONG_TYPE_SIZE)
6157 arg_type = long_long_unsigned_type_node;
6158 func = builtin_decl_explicit (BUILT_IN_CTZLL);
6160 else
6162 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6163 arg_type = gfc_build_uint_type (argsize);
6164 func = NULL_TREE;
6167 /* Convert the actual argument twice: first, to the unsigned type of the
6168 same size; then, to the proper argument type for the built-in
6169 function. But the return type is of the default INTEGER kind. */
6170 arg = fold_convert (gfc_build_uint_type (argsize), arg);
6171 arg = fold_convert (arg_type, arg);
6172 arg = gfc_evaluate_now (arg, &se->pre);
6173 result_type = gfc_get_int_type (gfc_default_integer_kind);
6175 /* Compute TRAILZ for the case i .ne. 0. */
6176 if (func)
6177 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
6178 func, 1, arg));
6179 else
6181 /* We end up here if the argument type is larger than 'long long'.
6182 We generate this code:
6184 if ((x & ULL_MAX) == 0)
6185 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
6186 else
6187 return ctzll ((unsigned long long) x);
6189 where ULL_MAX is the largest value that a ULL_MAX can hold
6190 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
6191 is the bit-size of the long long type (64 in this example). */
6192 tree ullsize, ullmax, tmp1, tmp2, btmp;
6194 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
6195 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
6196 long_long_unsigned_type_node,
6197 build_int_cst (long_long_unsigned_type_node, 0));
6199 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
6200 fold_convert (arg_type, ullmax));
6201 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, cond,
6202 build_int_cst (arg_type, 0));
6204 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
6205 arg, ullsize);
6206 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
6207 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
6208 tmp1 = fold_convert (result_type,
6209 build_call_expr_loc (input_location, btmp, 1, tmp1));
6210 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6211 tmp1, ullsize);
6213 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
6214 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
6215 tmp2 = fold_convert (result_type,
6216 build_call_expr_loc (input_location, btmp, 1, tmp2));
6218 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
6219 cond, tmp1, tmp2);
6222 /* Build BIT_SIZE. */
6223 bit_size = build_int_cst (result_type, argsize);
6225 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6226 arg, build_int_cst (arg_type, 0));
6227 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
6228 bit_size, trailz);
6231 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
6232 for types larger than "long long", we call the long long built-in for
6233 the lower and higher bits and combine the result. */
6235 static void
6236 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
6238 tree arg;
6239 tree arg_type;
6240 tree result_type;
6241 tree func;
6242 int argsize;
6244 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6245 argsize = TYPE_PRECISION (TREE_TYPE (arg));
6246 result_type = gfc_get_int_type (gfc_default_integer_kind);
6248 /* Which variant of the builtin should we call? */
6249 if (argsize <= INT_TYPE_SIZE)
6251 arg_type = unsigned_type_node;
6252 func = builtin_decl_explicit (parity
6253 ? BUILT_IN_PARITY
6254 : BUILT_IN_POPCOUNT);
6256 else if (argsize <= LONG_TYPE_SIZE)
6258 arg_type = long_unsigned_type_node;
6259 func = builtin_decl_explicit (parity
6260 ? BUILT_IN_PARITYL
6261 : BUILT_IN_POPCOUNTL);
6263 else if (argsize <= LONG_LONG_TYPE_SIZE)
6265 arg_type = long_long_unsigned_type_node;
6266 func = builtin_decl_explicit (parity
6267 ? BUILT_IN_PARITYLL
6268 : BUILT_IN_POPCOUNTLL);
6270 else
6272 /* Our argument type is larger than 'long long', which mean none
6273 of the POPCOUNT builtins covers it. We thus call the 'long long'
6274 variant multiple times, and add the results. */
6275 tree utype, arg2, call1, call2;
6277 /* For now, we only cover the case where argsize is twice as large
6278 as 'long long'. */
6279 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6281 func = builtin_decl_explicit (parity
6282 ? BUILT_IN_PARITYLL
6283 : BUILT_IN_POPCOUNTLL);
6285 /* Convert it to an integer, and store into a variable. */
6286 utype = gfc_build_uint_type (argsize);
6287 arg = fold_convert (utype, arg);
6288 arg = gfc_evaluate_now (arg, &se->pre);
6290 /* Call the builtin twice. */
6291 call1 = build_call_expr_loc (input_location, func, 1,
6292 fold_convert (long_long_unsigned_type_node,
6293 arg));
6295 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
6296 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
6297 call2 = build_call_expr_loc (input_location, func, 1,
6298 fold_convert (long_long_unsigned_type_node,
6299 arg2));
6301 /* Combine the results. */
6302 if (parity)
6303 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
6304 call1, call2);
6305 else
6306 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6307 call1, call2);
6309 return;
6312 /* Convert the actual argument twice: first, to the unsigned type of the
6313 same size; then, to the proper argument type for the built-in
6314 function. */
6315 arg = fold_convert (gfc_build_uint_type (argsize), arg);
6316 arg = fold_convert (arg_type, arg);
6318 se->expr = fold_convert (result_type,
6319 build_call_expr_loc (input_location, func, 1, arg));
6323 /* Process an intrinsic with unspecified argument-types that has an optional
6324 argument (which could be of type character), e.g. EOSHIFT. For those, we
6325 need to append the string length of the optional argument if it is not
6326 present and the type is really character.
6327 primary specifies the position (starting at 1) of the non-optional argument
6328 specifying the type and optional gives the position of the optional
6329 argument in the arglist. */
6331 static void
6332 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
6333 unsigned primary, unsigned optional)
6335 gfc_actual_arglist* prim_arg;
6336 gfc_actual_arglist* opt_arg;
6337 unsigned cur_pos;
6338 gfc_actual_arglist* arg;
6339 gfc_symbol* sym;
6340 vec<tree, va_gc> *append_args;
6342 /* Find the two arguments given as position. */
6343 cur_pos = 0;
6344 prim_arg = NULL;
6345 opt_arg = NULL;
6346 for (arg = expr->value.function.actual; arg; arg = arg->next)
6348 ++cur_pos;
6350 if (cur_pos == primary)
6351 prim_arg = arg;
6352 if (cur_pos == optional)
6353 opt_arg = arg;
6355 if (cur_pos >= primary && cur_pos >= optional)
6356 break;
6358 gcc_assert (prim_arg);
6359 gcc_assert (prim_arg->expr);
6360 gcc_assert (opt_arg);
6362 /* If we do have type CHARACTER and the optional argument is really absent,
6363 append a dummy 0 as string length. */
6364 append_args = NULL;
6365 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
6367 tree dummy;
6369 dummy = build_int_cst (gfc_charlen_type_node, 0);
6370 vec_alloc (append_args, 1);
6371 append_args->quick_push (dummy);
6374 /* Build the call itself. */
6375 gcc_assert (!se->ignore_optional);
6376 sym = gfc_get_symbol_for_expr (expr, false);
6377 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
6378 append_args);
6379 gfc_free_symbol (sym);
6382 /* The length of a character string. */
6383 static void
6384 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
6386 tree len;
6387 tree type;
6388 tree decl;
6389 gfc_symbol *sym;
6390 gfc_se argse;
6391 gfc_expr *arg;
6393 gcc_assert (!se->ss);
6395 arg = expr->value.function.actual->expr;
6397 type = gfc_typenode_for_spec (&expr->ts);
6398 switch (arg->expr_type)
6400 case EXPR_CONSTANT:
6401 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
6402 break;
6404 case EXPR_ARRAY:
6405 /* Obtain the string length from the function used by
6406 trans-array.c(gfc_trans_array_constructor). */
6407 len = NULL_TREE;
6408 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
6409 break;
6411 case EXPR_VARIABLE:
6412 if (arg->ref == NULL
6413 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
6415 /* This doesn't catch all cases.
6416 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
6417 and the surrounding thread. */
6418 sym = arg->symtree->n.sym;
6419 decl = gfc_get_symbol_decl (sym);
6420 if (decl == current_function_decl && sym->attr.function
6421 && (sym->result == sym))
6422 decl = gfc_get_fake_result_decl (sym, 0);
6424 len = sym->ts.u.cl->backend_decl;
6425 gcc_assert (len);
6426 break;
6429 /* Fall through. */
6431 default:
6432 /* Anybody stupid enough to do this deserves inefficient code. */
6433 gfc_init_se (&argse, se);
6434 if (arg->rank == 0)
6435 gfc_conv_expr (&argse, arg);
6436 else
6437 gfc_conv_expr_descriptor (&argse, arg);
6438 gfc_add_block_to_block (&se->pre, &argse.pre);
6439 gfc_add_block_to_block (&se->post, &argse.post);
6440 len = argse.string_length;
6441 break;
6443 se->expr = convert (type, len);
6446 /* The length of a character string not including trailing blanks. */
6447 static void
6448 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
6450 int kind = expr->value.function.actual->expr->ts.kind;
6451 tree args[2], type, fndecl;
6453 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6454 type = gfc_typenode_for_spec (&expr->ts);
6456 if (kind == 1)
6457 fndecl = gfor_fndecl_string_len_trim;
6458 else if (kind == 4)
6459 fndecl = gfor_fndecl_string_len_trim_char4;
6460 else
6461 gcc_unreachable ();
6463 se->expr = build_call_expr_loc (input_location,
6464 fndecl, 2, args[0], args[1]);
6465 se->expr = convert (type, se->expr);
6469 /* Returns the starting position of a substring within a string. */
6471 static void
6472 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
6473 tree function)
6475 tree logical4_type_node = gfc_get_logical_type (4);
6476 tree type;
6477 tree fndecl;
6478 tree *args;
6479 unsigned int num_args;
6481 args = XALLOCAVEC (tree, 5);
6483 /* Get number of arguments; characters count double due to the
6484 string length argument. Kind= is not passed to the library
6485 and thus ignored. */
6486 if (expr->value.function.actual->next->next->expr == NULL)
6487 num_args = 4;
6488 else
6489 num_args = 5;
6491 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6492 type = gfc_typenode_for_spec (&expr->ts);
6494 if (num_args == 4)
6495 args[4] = build_int_cst (logical4_type_node, 0);
6496 else
6497 args[4] = convert (logical4_type_node, args[4]);
6499 fndecl = build_addr (function);
6500 se->expr = build_call_array_loc (input_location,
6501 TREE_TYPE (TREE_TYPE (function)), fndecl,
6502 5, args);
6503 se->expr = convert (type, se->expr);
6507 /* The ascii value for a single character. */
6508 static void
6509 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
6511 tree args[3], type, pchartype;
6512 int nargs;
6514 nargs = gfc_intrinsic_argument_list_length (expr);
6515 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6516 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
6517 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
6518 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
6519 type = gfc_typenode_for_spec (&expr->ts);
6521 se->expr = build_fold_indirect_ref_loc (input_location,
6522 args[1]);
6523 se->expr = convert (type, se->expr);
6527 /* Intrinsic ISNAN calls __builtin_isnan. */
6529 static void
6530 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
6532 tree arg;
6534 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6535 se->expr = build_call_expr_loc (input_location,
6536 builtin_decl_explicit (BUILT_IN_ISNAN),
6537 1, arg);
6538 STRIP_TYPE_NOPS (se->expr);
6539 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6543 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
6544 their argument against a constant integer value. */
6546 static void
6547 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
6549 tree arg;
6551 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6552 se->expr = fold_build2_loc (input_location, EQ_EXPR,
6553 gfc_typenode_for_spec (&expr->ts),
6554 arg, build_int_cst (TREE_TYPE (arg), value));
6559 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
6561 static void
6562 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
6564 tree tsource;
6565 tree fsource;
6566 tree mask;
6567 tree type;
6568 tree len, len2;
6569 tree *args;
6570 unsigned int num_args;
6572 num_args = gfc_intrinsic_argument_list_length (expr);
6573 args = XALLOCAVEC (tree, num_args);
6575 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6576 if (expr->ts.type != BT_CHARACTER)
6578 tsource = args[0];
6579 fsource = args[1];
6580 mask = args[2];
6582 else
6584 /* We do the same as in the non-character case, but the argument
6585 list is different because of the string length arguments. We
6586 also have to set the string length for the result. */
6587 len = args[0];
6588 tsource = args[1];
6589 len2 = args[2];
6590 fsource = args[3];
6591 mask = args[4];
6593 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
6594 &se->pre);
6595 se->string_length = len;
6597 type = TREE_TYPE (tsource);
6598 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
6599 fold_convert (type, fsource));
6603 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
6605 static void
6606 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
6608 tree args[3], mask, type;
6610 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6611 mask = gfc_evaluate_now (args[2], &se->pre);
6613 type = TREE_TYPE (args[0]);
6614 gcc_assert (TREE_TYPE (args[1]) == type);
6615 gcc_assert (TREE_TYPE (mask) == type);
6617 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
6618 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
6619 fold_build1_loc (input_location, BIT_NOT_EXPR,
6620 type, mask));
6621 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
6622 args[0], args[1]);
6626 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
6627 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
6629 static void
6630 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
6632 tree arg, allones, type, utype, res, cond, bitsize;
6633 int i;
6635 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6636 arg = gfc_evaluate_now (arg, &se->pre);
6638 type = gfc_get_int_type (expr->ts.kind);
6639 utype = unsigned_type_for (type);
6641 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
6642 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
6644 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
6645 build_int_cst (utype, 0));
6647 if (left)
6649 /* Left-justified mask. */
6650 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
6651 bitsize, arg);
6652 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6653 fold_convert (utype, res));
6655 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
6656 smaller than type width. */
6657 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
6658 build_int_cst (TREE_TYPE (arg), 0));
6659 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
6660 build_int_cst (utype, 0), res);
6662 else
6664 /* Right-justified mask. */
6665 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6666 fold_convert (utype, arg));
6667 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
6669 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
6670 strictly smaller than type width. */
6671 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6672 arg, bitsize);
6673 res = fold_build3_loc (input_location, COND_EXPR, utype,
6674 cond, allones, res);
6677 se->expr = fold_convert (type, res);
6681 /* FRACTION (s) is translated into:
6682 isfinite (s) ? frexp (s, &dummy_int) : NaN */
6683 static void
6684 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
6686 tree arg, type, tmp, res, frexp, cond;
6688 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6690 type = gfc_typenode_for_spec (&expr->ts);
6691 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6692 arg = gfc_evaluate_now (arg, &se->pre);
6694 cond = build_call_expr_loc (input_location,
6695 builtin_decl_explicit (BUILT_IN_ISFINITE),
6696 1, arg);
6698 tmp = gfc_create_var (integer_type_node, NULL);
6699 res = build_call_expr_loc (input_location, frexp, 2,
6700 fold_convert (type, arg),
6701 gfc_build_addr_expr (NULL_TREE, tmp));
6702 res = fold_convert (type, res);
6704 se->expr = fold_build3_loc (input_location, COND_EXPR, type,
6705 cond, res, gfc_build_nan (type, ""));
6709 /* NEAREST (s, dir) is translated into
6710 tmp = copysign (HUGE_VAL, dir);
6711 return nextafter (s, tmp);
6713 static void
6714 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
6716 tree args[2], type, tmp, nextafter, copysign, huge_val;
6718 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
6719 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
6721 type = gfc_typenode_for_spec (&expr->ts);
6722 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6724 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
6725 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
6726 fold_convert (type, args[1]));
6727 se->expr = build_call_expr_loc (input_location, nextafter, 2,
6728 fold_convert (type, args[0]), tmp);
6729 se->expr = fold_convert (type, se->expr);
6733 /* SPACING (s) is translated into
6734 int e;
6735 if (!isfinite (s))
6736 res = NaN;
6737 else if (s == 0)
6738 res = tiny;
6739 else
6741 frexp (s, &e);
6742 e = e - prec;
6743 e = MAX_EXPR (e, emin);
6744 res = scalbn (1., e);
6746 return res;
6748 where prec is the precision of s, gfc_real_kinds[k].digits,
6749 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
6750 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
6752 static void
6753 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
6755 tree arg, type, prec, emin, tiny, res, e;
6756 tree cond, nan, tmp, frexp, scalbn;
6757 int k;
6758 stmtblock_t block;
6760 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
6761 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
6762 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
6763 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
6765 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6766 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6768 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6769 arg = gfc_evaluate_now (arg, &se->pre);
6771 type = gfc_typenode_for_spec (&expr->ts);
6772 e = gfc_create_var (integer_type_node, NULL);
6773 res = gfc_create_var (type, NULL);
6776 /* Build the block for s /= 0. */
6777 gfc_start_block (&block);
6778 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
6779 gfc_build_addr_expr (NULL_TREE, e));
6780 gfc_add_expr_to_block (&block, tmp);
6782 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
6783 prec);
6784 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
6785 integer_type_node, tmp, emin));
6787 tmp = build_call_expr_loc (input_location, scalbn, 2,
6788 build_real_from_int_cst (type, integer_one_node), e);
6789 gfc_add_modify (&block, res, tmp);
6791 /* Finish by building the IF statement for value zero. */
6792 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
6793 build_real_from_int_cst (type, integer_zero_node));
6794 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
6795 gfc_finish_block (&block));
6797 /* And deal with infinities and NaNs. */
6798 cond = build_call_expr_loc (input_location,
6799 builtin_decl_explicit (BUILT_IN_ISFINITE),
6800 1, arg);
6801 nan = gfc_build_nan (type, "");
6802 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
6804 gfc_add_expr_to_block (&se->pre, tmp);
6805 se->expr = res;
6809 /* RRSPACING (s) is translated into
6810 int e;
6811 real x;
6812 x = fabs (s);
6813 if (isfinite (x))
6815 if (x != 0)
6817 frexp (s, &e);
6818 x = scalbn (x, precision - e);
6821 else
6822 x = NaN;
6823 return x;
6825 where precision is gfc_real_kinds[k].digits. */
6827 static void
6828 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
6830 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
6831 int prec, k;
6832 stmtblock_t block;
6834 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
6835 prec = gfc_real_kinds[k].digits;
6837 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6838 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6839 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
6841 type = gfc_typenode_for_spec (&expr->ts);
6842 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6843 arg = gfc_evaluate_now (arg, &se->pre);
6845 e = gfc_create_var (integer_type_node, NULL);
6846 x = gfc_create_var (type, NULL);
6847 gfc_add_modify (&se->pre, x,
6848 build_call_expr_loc (input_location, fabs, 1, arg));
6851 gfc_start_block (&block);
6852 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
6853 gfc_build_addr_expr (NULL_TREE, e));
6854 gfc_add_expr_to_block (&block, tmp);
6856 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
6857 build_int_cst (integer_type_node, prec), e);
6858 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
6859 gfc_add_modify (&block, x, tmp);
6860 stmt = gfc_finish_block (&block);
6862 /* if (x != 0) */
6863 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, x,
6864 build_real_from_int_cst (type, integer_zero_node));
6865 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
6867 /* And deal with infinities and NaNs. */
6868 cond = build_call_expr_loc (input_location,
6869 builtin_decl_explicit (BUILT_IN_ISFINITE),
6870 1, x);
6871 nan = gfc_build_nan (type, "");
6872 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
6874 gfc_add_expr_to_block (&se->pre, tmp);
6875 se->expr = fold_convert (type, x);
6879 /* SCALE (s, i) is translated into scalbn (s, i). */
6880 static void
6881 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
6883 tree args[2], type, scalbn;
6885 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6887 type = gfc_typenode_for_spec (&expr->ts);
6888 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6889 se->expr = build_call_expr_loc (input_location, scalbn, 2,
6890 fold_convert (type, args[0]),
6891 fold_convert (integer_type_node, args[1]));
6892 se->expr = fold_convert (type, se->expr);
6896 /* SET_EXPONENT (s, i) is translated into
6897 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
6898 static void
6899 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
6901 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
6903 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6904 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6906 type = gfc_typenode_for_spec (&expr->ts);
6907 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6908 args[0] = gfc_evaluate_now (args[0], &se->pre);
6910 tmp = gfc_create_var (integer_type_node, NULL);
6911 tmp = build_call_expr_loc (input_location, frexp, 2,
6912 fold_convert (type, args[0]),
6913 gfc_build_addr_expr (NULL_TREE, tmp));
6914 res = build_call_expr_loc (input_location, scalbn, 2, tmp,
6915 fold_convert (integer_type_node, args[1]));
6916 res = fold_convert (type, res);
6918 /* Call to isfinite */
6919 cond = build_call_expr_loc (input_location,
6920 builtin_decl_explicit (BUILT_IN_ISFINITE),
6921 1, args[0]);
6922 nan = gfc_build_nan (type, "");
6924 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
6925 res, nan);
6929 static void
6930 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
6932 gfc_actual_arglist *actual;
6933 tree arg1;
6934 tree type;
6935 tree fncall0;
6936 tree fncall1;
6937 gfc_se argse;
6939 gfc_init_se (&argse, NULL);
6940 actual = expr->value.function.actual;
6942 if (actual->expr->ts.type == BT_CLASS)
6943 gfc_add_class_array_ref (actual->expr);
6945 argse.data_not_needed = 1;
6946 if (gfc_is_class_array_function (actual->expr))
6948 /* For functions that return a class array conv_expr_descriptor is not
6949 able to get the descriptor right. Therefore this special case. */
6950 gfc_conv_expr_reference (&argse, actual->expr);
6951 argse.expr = gfc_build_addr_expr (NULL_TREE,
6952 gfc_class_data_get (argse.expr));
6954 else
6956 argse.want_pointer = 1;
6957 gfc_conv_expr_descriptor (&argse, actual->expr);
6959 gfc_add_block_to_block (&se->pre, &argse.pre);
6960 gfc_add_block_to_block (&se->post, &argse.post);
6961 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
6963 /* Build the call to size0. */
6964 fncall0 = build_call_expr_loc (input_location,
6965 gfor_fndecl_size0, 1, arg1);
6967 actual = actual->next;
6969 if (actual->expr)
6971 gfc_init_se (&argse, NULL);
6972 gfc_conv_expr_type (&argse, actual->expr,
6973 gfc_array_index_type);
6974 gfc_add_block_to_block (&se->pre, &argse.pre);
6976 /* Unusually, for an intrinsic, size does not exclude
6977 an optional arg2, so we must test for it. */
6978 if (actual->expr->expr_type == EXPR_VARIABLE
6979 && actual->expr->symtree->n.sym->attr.dummy
6980 && actual->expr->symtree->n.sym->attr.optional)
6982 tree tmp;
6983 /* Build the call to size1. */
6984 fncall1 = build_call_expr_loc (input_location,
6985 gfor_fndecl_size1, 2,
6986 arg1, argse.expr);
6988 gfc_init_se (&argse, NULL);
6989 argse.want_pointer = 1;
6990 argse.data_not_needed = 1;
6991 gfc_conv_expr (&argse, actual->expr);
6992 gfc_add_block_to_block (&se->pre, &argse.pre);
6993 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6994 argse.expr, null_pointer_node);
6995 tmp = gfc_evaluate_now (tmp, &se->pre);
6996 se->expr = fold_build3_loc (input_location, COND_EXPR,
6997 pvoid_type_node, tmp, fncall1, fncall0);
6999 else
7001 se->expr = NULL_TREE;
7002 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
7003 gfc_array_index_type,
7004 argse.expr, gfc_index_one_node);
7007 else if (expr->value.function.actual->expr->rank == 1)
7009 argse.expr = gfc_index_zero_node;
7010 se->expr = NULL_TREE;
7012 else
7013 se->expr = fncall0;
7015 if (se->expr == NULL_TREE)
7017 tree ubound, lbound;
7019 arg1 = build_fold_indirect_ref_loc (input_location,
7020 arg1);
7021 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
7022 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
7023 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
7024 gfc_array_index_type, ubound, lbound);
7025 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
7026 gfc_array_index_type,
7027 se->expr, gfc_index_one_node);
7028 se->expr = fold_build2_loc (input_location, MAX_EXPR,
7029 gfc_array_index_type, se->expr,
7030 gfc_index_zero_node);
7033 type = gfc_typenode_for_spec (&expr->ts);
7034 se->expr = convert (type, se->expr);
7038 /* Helper function to compute the size of a character variable,
7039 excluding the terminating null characters. The result has
7040 gfc_array_index_type type. */
7042 tree
7043 size_of_string_in_bytes (int kind, tree string_length)
7045 tree bytesize;
7046 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
7048 bytesize = build_int_cst (gfc_array_index_type,
7049 gfc_character_kinds[i].bit_size / 8);
7051 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7052 bytesize,
7053 fold_convert (gfc_array_index_type, string_length));
7057 static void
7058 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
7060 gfc_expr *arg;
7061 gfc_se argse;
7062 tree source_bytes;
7063 tree tmp;
7064 tree lower;
7065 tree upper;
7066 tree byte_size;
7067 tree field;
7068 int n;
7070 gfc_init_se (&argse, NULL);
7071 arg = expr->value.function.actual->expr;
7073 if (arg->rank || arg->ts.type == BT_ASSUMED)
7074 gfc_conv_expr_descriptor (&argse, arg);
7075 else
7076 gfc_conv_expr_reference (&argse, arg);
7078 if (arg->ts.type == BT_ASSUMED)
7080 /* This only works if an array descriptor has been passed; thus, extract
7081 the size from the descriptor. */
7082 gcc_assert (TYPE_PRECISION (gfc_array_index_type)
7083 == TYPE_PRECISION (size_type_node));
7084 tmp = arg->symtree->n.sym->backend_decl;
7085 tmp = DECL_LANG_SPECIFIC (tmp)
7086 && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
7087 ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
7088 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
7089 tmp = build_fold_indirect_ref_loc (input_location, tmp);
7091 tmp = gfc_conv_descriptor_dtype (tmp);
7092 field = gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
7093 GFC_DTYPE_ELEM_LEN);
7094 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
7095 tmp, field, NULL_TREE);
7097 byte_size = fold_convert (gfc_array_index_type, tmp);
7099 else if (arg->ts.type == BT_CLASS)
7101 /* Conv_expr_descriptor returns a component_ref to _data component of the
7102 class object. The class object may be a non-pointer object, e.g.
7103 located on the stack, or a memory location pointed to, e.g. a
7104 parameter, i.e., an indirect_ref. */
7105 if (arg->rank < 0
7106 || (arg->rank > 0 && !VAR_P (argse.expr)
7107 && ((INDIRECT_REF_P (TREE_OPERAND (argse.expr, 0))
7108 && GFC_DECL_CLASS (TREE_OPERAND (
7109 TREE_OPERAND (argse.expr, 0), 0)))
7110 || GFC_DECL_CLASS (TREE_OPERAND (argse.expr, 0)))))
7111 byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
7112 else if (arg->rank > 0
7113 || (arg->rank == 0
7114 && arg->ref && arg->ref->type == REF_COMPONENT))
7115 /* The scalarizer added an additional temp. To get the class' vptr
7116 one has to look at the original backend_decl. */
7117 byte_size = gfc_class_vtab_size_get (
7118 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
7119 else
7120 byte_size = gfc_class_vtab_size_get (argse.expr);
7122 else
7124 if (arg->ts.type == BT_CHARACTER)
7125 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
7126 else
7128 if (arg->rank == 0)
7129 byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7130 argse.expr));
7131 else
7132 byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
7133 byte_size = fold_convert (gfc_array_index_type,
7134 size_in_bytes (byte_size));
7138 if (arg->rank == 0)
7139 se->expr = byte_size;
7140 else
7142 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
7143 gfc_add_modify (&argse.pre, source_bytes, byte_size);
7145 if (arg->rank == -1)
7147 tree cond, loop_var, exit_label;
7148 stmtblock_t body;
7150 tmp = fold_convert (gfc_array_index_type,
7151 gfc_conv_descriptor_rank (argse.expr));
7152 loop_var = gfc_create_var (gfc_array_index_type, "i");
7153 gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
7154 exit_label = gfc_build_label_decl (NULL_TREE);
7156 /* Create loop:
7157 for (;;)
7159 if (i >= rank)
7160 goto exit;
7161 source_bytes = source_bytes * array.dim[i].extent;
7162 i = i + 1;
7164 exit: */
7165 gfc_start_block (&body);
7166 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
7167 loop_var, tmp);
7168 tmp = build1_v (GOTO_EXPR, exit_label);
7169 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
7170 cond, tmp, build_empty_stmt (input_location));
7171 gfc_add_expr_to_block (&body, tmp);
7173 lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
7174 upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
7175 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
7176 tmp = fold_build2_loc (input_location, MULT_EXPR,
7177 gfc_array_index_type, tmp, source_bytes);
7178 gfc_add_modify (&body, source_bytes, tmp);
7180 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7181 gfc_array_index_type, loop_var,
7182 gfc_index_one_node);
7183 gfc_add_modify_loc (input_location, &body, loop_var, tmp);
7185 tmp = gfc_finish_block (&body);
7187 tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
7188 tmp);
7189 gfc_add_expr_to_block (&argse.pre, tmp);
7191 tmp = build1_v (LABEL_EXPR, exit_label);
7192 gfc_add_expr_to_block (&argse.pre, tmp);
7194 else
7196 /* Obtain the size of the array in bytes. */
7197 for (n = 0; n < arg->rank; n++)
7199 tree idx;
7200 idx = gfc_rank_cst[n];
7201 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
7202 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
7203 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
7204 tmp = fold_build2_loc (input_location, MULT_EXPR,
7205 gfc_array_index_type, tmp, source_bytes);
7206 gfc_add_modify (&argse.pre, source_bytes, tmp);
7209 se->expr = source_bytes;
7212 gfc_add_block_to_block (&se->pre, &argse.pre);
7216 static void
7217 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
7219 gfc_expr *arg;
7220 gfc_se argse;
7221 tree type, result_type, tmp;
7223 arg = expr->value.function.actual->expr;
7225 gfc_init_se (&argse, NULL);
7226 result_type = gfc_get_int_type (expr->ts.kind);
7228 if (arg->rank == 0)
7230 if (arg->ts.type == BT_CLASS)
7232 gfc_add_vptr_component (arg);
7233 gfc_add_size_component (arg);
7234 gfc_conv_expr (&argse, arg);
7235 tmp = fold_convert (result_type, argse.expr);
7236 goto done;
7239 gfc_conv_expr_reference (&argse, arg);
7240 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7241 argse.expr));
7243 else
7245 argse.want_pointer = 0;
7246 gfc_conv_expr_descriptor (&argse, arg);
7247 if (arg->ts.type == BT_CLASS)
7249 if (arg->rank > 0)
7250 tmp = gfc_class_vtab_size_get (
7251 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
7252 else
7253 tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
7254 tmp = fold_convert (result_type, tmp);
7255 goto done;
7257 type = gfc_get_element_type (TREE_TYPE (argse.expr));
7260 /* Obtain the argument's word length. */
7261 if (arg->ts.type == BT_CHARACTER)
7262 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
7263 else
7264 tmp = size_in_bytes (type);
7265 tmp = fold_convert (result_type, tmp);
7267 done:
7268 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
7269 build_int_cst (result_type, BITS_PER_UNIT));
7270 gfc_add_block_to_block (&se->pre, &argse.pre);
7274 /* Intrinsic string comparison functions. */
7276 static void
7277 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
7279 tree args[4];
7281 gfc_conv_intrinsic_function_args (se, expr, args, 4);
7283 se->expr
7284 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
7285 expr->value.function.actual->expr->ts.kind,
7286 op);
7287 se->expr = fold_build2_loc (input_location, op,
7288 gfc_typenode_for_spec (&expr->ts), se->expr,
7289 build_int_cst (TREE_TYPE (se->expr), 0));
7292 /* Generate a call to the adjustl/adjustr library function. */
7293 static void
7294 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
7296 tree args[3];
7297 tree len;
7298 tree type;
7299 tree var;
7300 tree tmp;
7302 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
7303 len = args[1];
7305 type = TREE_TYPE (args[2]);
7306 var = gfc_conv_string_tmp (se, type, len);
7307 args[0] = var;
7309 tmp = build_call_expr_loc (input_location,
7310 fndecl, 3, args[0], args[1], args[2]);
7311 gfc_add_expr_to_block (&se->pre, tmp);
7312 se->expr = var;
7313 se->string_length = len;
7317 /* Generate code for the TRANSFER intrinsic:
7318 For scalar results:
7319 DEST = TRANSFER (SOURCE, MOLD)
7320 where:
7321 typeof<DEST> = typeof<MOLD>
7322 and:
7323 MOLD is scalar.
7325 For array results:
7326 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
7327 where:
7328 typeof<DEST> = typeof<MOLD>
7329 and:
7330 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
7331 sizeof (DEST(0) * SIZE). */
7332 static void
7333 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
7335 tree tmp;
7336 tree tmpdecl;
7337 tree ptr;
7338 tree extent;
7339 tree source;
7340 tree source_type;
7341 tree source_bytes;
7342 tree mold_type;
7343 tree dest_word_len;
7344 tree size_words;
7345 tree size_bytes;
7346 tree upper;
7347 tree lower;
7348 tree stmt;
7349 gfc_actual_arglist *arg;
7350 gfc_se argse;
7351 gfc_array_info *info;
7352 stmtblock_t block;
7353 int n;
7354 bool scalar_mold;
7355 gfc_expr *source_expr, *mold_expr;
7357 info = NULL;
7358 if (se->loop)
7359 info = &se->ss->info->data.array;
7361 /* Convert SOURCE. The output from this stage is:-
7362 source_bytes = length of the source in bytes
7363 source = pointer to the source data. */
7364 arg = expr->value.function.actual;
7365 source_expr = arg->expr;
7367 /* Ensure double transfer through LOGICAL preserves all
7368 the needed bits. */
7369 if (arg->expr->expr_type == EXPR_FUNCTION
7370 && arg->expr->value.function.esym == NULL
7371 && arg->expr->value.function.isym != NULL
7372 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
7373 && arg->expr->ts.type == BT_LOGICAL
7374 && expr->ts.type != arg->expr->ts.type)
7375 arg->expr->value.function.name = "__transfer_in_transfer";
7377 gfc_init_se (&argse, NULL);
7379 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
7381 /* Obtain the pointer to source and the length of source in bytes. */
7382 if (arg->expr->rank == 0)
7384 gfc_conv_expr_reference (&argse, arg->expr);
7385 if (arg->expr->ts.type == BT_CLASS)
7386 source = gfc_class_data_get (argse.expr);
7387 else
7388 source = argse.expr;
7390 /* Obtain the source word length. */
7391 switch (arg->expr->ts.type)
7393 case BT_CHARACTER:
7394 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7395 argse.string_length);
7396 break;
7397 case BT_CLASS:
7398 tmp = gfc_class_vtab_size_get (argse.expr);
7399 break;
7400 default:
7401 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7402 source));
7403 tmp = fold_convert (gfc_array_index_type,
7404 size_in_bytes (source_type));
7405 break;
7408 else
7410 argse.want_pointer = 0;
7411 gfc_conv_expr_descriptor (&argse, arg->expr);
7412 source = gfc_conv_descriptor_data_get (argse.expr);
7413 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7415 /* Repack the source if not simply contiguous. */
7416 if (!gfc_is_simply_contiguous (arg->expr, false, true))
7418 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
7420 if (warn_array_temporaries)
7421 gfc_warning (OPT_Warray_temporaries,
7422 "Creating array temporary at %L", &expr->where);
7424 source = build_call_expr_loc (input_location,
7425 gfor_fndecl_in_pack, 1, tmp);
7426 source = gfc_evaluate_now (source, &argse.pre);
7428 /* Free the temporary. */
7429 gfc_start_block (&block);
7430 tmp = gfc_call_free (source);
7431 gfc_add_expr_to_block (&block, tmp);
7432 stmt = gfc_finish_block (&block);
7434 /* Clean up if it was repacked. */
7435 gfc_init_block (&block);
7436 tmp = gfc_conv_array_data (argse.expr);
7437 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7438 source, tmp);
7439 tmp = build3_v (COND_EXPR, tmp, stmt,
7440 build_empty_stmt (input_location));
7441 gfc_add_expr_to_block (&block, tmp);
7442 gfc_add_block_to_block (&block, &se->post);
7443 gfc_init_block (&se->post);
7444 gfc_add_block_to_block (&se->post, &block);
7447 /* Obtain the source word length. */
7448 if (arg->expr->ts.type == BT_CHARACTER)
7449 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7450 argse.string_length);
7451 else
7452 tmp = fold_convert (gfc_array_index_type,
7453 size_in_bytes (source_type));
7455 /* Obtain the size of the array in bytes. */
7456 extent = gfc_create_var (gfc_array_index_type, NULL);
7457 for (n = 0; n < arg->expr->rank; n++)
7459 tree idx;
7460 idx = gfc_rank_cst[n];
7461 gfc_add_modify (&argse.pre, source_bytes, tmp);
7462 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
7463 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
7464 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7465 gfc_array_index_type, upper, lower);
7466 gfc_add_modify (&argse.pre, extent, tmp);
7467 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7468 gfc_array_index_type, extent,
7469 gfc_index_one_node);
7470 tmp = fold_build2_loc (input_location, MULT_EXPR,
7471 gfc_array_index_type, tmp, source_bytes);
7475 gfc_add_modify (&argse.pre, source_bytes, tmp);
7476 gfc_add_block_to_block (&se->pre, &argse.pre);
7477 gfc_add_block_to_block (&se->post, &argse.post);
7479 /* Now convert MOLD. The outputs are:
7480 mold_type = the TREE type of MOLD
7481 dest_word_len = destination word length in bytes. */
7482 arg = arg->next;
7483 mold_expr = arg->expr;
7485 gfc_init_se (&argse, NULL);
7487 scalar_mold = arg->expr->rank == 0;
7489 if (arg->expr->rank == 0)
7491 gfc_conv_expr_reference (&argse, arg->expr);
7492 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7493 argse.expr));
7495 else
7497 gfc_init_se (&argse, NULL);
7498 argse.want_pointer = 0;
7499 gfc_conv_expr_descriptor (&argse, arg->expr);
7500 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7503 gfc_add_block_to_block (&se->pre, &argse.pre);
7504 gfc_add_block_to_block (&se->post, &argse.post);
7506 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
7508 /* If this TRANSFER is nested in another TRANSFER, use a type
7509 that preserves all bits. */
7510 if (arg->expr->ts.type == BT_LOGICAL)
7511 mold_type = gfc_get_int_type (arg->expr->ts.kind);
7514 /* Obtain the destination word length. */
7515 switch (arg->expr->ts.type)
7517 case BT_CHARACTER:
7518 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
7519 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
7520 break;
7521 case BT_CLASS:
7522 tmp = gfc_class_vtab_size_get (argse.expr);
7523 break;
7524 default:
7525 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
7526 break;
7528 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
7529 gfc_add_modify (&se->pre, dest_word_len, tmp);
7531 /* Finally convert SIZE, if it is present. */
7532 arg = arg->next;
7533 size_words = gfc_create_var (gfc_array_index_type, NULL);
7535 if (arg->expr)
7537 gfc_init_se (&argse, NULL);
7538 gfc_conv_expr_reference (&argse, arg->expr);
7539 tmp = convert (gfc_array_index_type,
7540 build_fold_indirect_ref_loc (input_location,
7541 argse.expr));
7542 gfc_add_block_to_block (&se->pre, &argse.pre);
7543 gfc_add_block_to_block (&se->post, &argse.post);
7545 else
7546 tmp = NULL_TREE;
7548 /* Separate array and scalar results. */
7549 if (scalar_mold && tmp == NULL_TREE)
7550 goto scalar_transfer;
7552 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
7553 if (tmp != NULL_TREE)
7554 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7555 tmp, dest_word_len);
7556 else
7557 tmp = source_bytes;
7559 gfc_add_modify (&se->pre, size_bytes, tmp);
7560 gfc_add_modify (&se->pre, size_words,
7561 fold_build2_loc (input_location, CEIL_DIV_EXPR,
7562 gfc_array_index_type,
7563 size_bytes, dest_word_len));
7565 /* Evaluate the bounds of the result. If the loop range exists, we have
7566 to check if it is too large. If so, we modify loop->to be consistent
7567 with min(size, size(source)). Otherwise, size is made consistent with
7568 the loop range, so that the right number of bytes is transferred.*/
7569 n = se->loop->order[0];
7570 if (se->loop->to[n] != NULL_TREE)
7572 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7573 se->loop->to[n], se->loop->from[n]);
7574 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7575 tmp, gfc_index_one_node);
7576 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7577 tmp, size_words);
7578 gfc_add_modify (&se->pre, size_words, tmp);
7579 gfc_add_modify (&se->pre, size_bytes,
7580 fold_build2_loc (input_location, MULT_EXPR,
7581 gfc_array_index_type,
7582 size_words, dest_word_len));
7583 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7584 size_words, se->loop->from[n]);
7585 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7586 upper, gfc_index_one_node);
7588 else
7590 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7591 size_words, gfc_index_one_node);
7592 se->loop->from[n] = gfc_index_zero_node;
7595 se->loop->to[n] = upper;
7597 /* Build a destination descriptor, using the pointer, source, as the
7598 data field. */
7599 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
7600 NULL_TREE, false, true, false, &expr->where);
7602 /* Cast the pointer to the result. */
7603 tmp = gfc_conv_descriptor_data_get (info->descriptor);
7604 tmp = fold_convert (pvoid_type_node, tmp);
7606 /* Use memcpy to do the transfer. */
7608 = build_call_expr_loc (input_location,
7609 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
7610 fold_convert (pvoid_type_node, source),
7611 fold_convert (size_type_node,
7612 fold_build2_loc (input_location,
7613 MIN_EXPR,
7614 gfc_array_index_type,
7615 size_bytes,
7616 source_bytes)));
7617 gfc_add_expr_to_block (&se->pre, tmp);
7619 se->expr = info->descriptor;
7620 if (expr->ts.type == BT_CHARACTER)
7621 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7623 return;
7625 /* Deal with scalar results. */
7626 scalar_transfer:
7627 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7628 dest_word_len, source_bytes);
7629 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
7630 extent, gfc_index_zero_node);
7632 if (expr->ts.type == BT_CHARACTER)
7634 tree direct, indirect, free;
7636 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
7637 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
7638 "transfer");
7640 /* If source is longer than the destination, use a pointer to
7641 the source directly. */
7642 gfc_init_block (&block);
7643 gfc_add_modify (&block, tmpdecl, ptr);
7644 direct = gfc_finish_block (&block);
7646 /* Otherwise, allocate a string with the length of the destination
7647 and copy the source into it. */
7648 gfc_init_block (&block);
7649 tmp = gfc_get_pchar_type (expr->ts.kind);
7650 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
7651 gfc_add_modify (&block, tmpdecl,
7652 fold_convert (TREE_TYPE (ptr), tmp));
7653 tmp = build_call_expr_loc (input_location,
7654 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7655 fold_convert (pvoid_type_node, tmpdecl),
7656 fold_convert (pvoid_type_node, ptr),
7657 fold_convert (size_type_node, extent));
7658 gfc_add_expr_to_block (&block, tmp);
7659 indirect = gfc_finish_block (&block);
7661 /* Wrap it up with the condition. */
7662 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
7663 dest_word_len, source_bytes);
7664 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
7665 gfc_add_expr_to_block (&se->pre, tmp);
7667 /* Free the temporary string, if necessary. */
7668 free = gfc_call_free (tmpdecl);
7669 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
7670 dest_word_len, source_bytes);
7671 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
7672 gfc_add_expr_to_block (&se->post, tmp);
7674 se->expr = tmpdecl;
7675 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7677 else
7679 tmpdecl = gfc_create_var (mold_type, "transfer");
7681 ptr = convert (build_pointer_type (mold_type), source);
7683 /* For CLASS results, allocate the needed memory first. */
7684 if (mold_expr->ts.type == BT_CLASS)
7686 tree cdata;
7687 cdata = gfc_class_data_get (tmpdecl);
7688 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
7689 gfc_add_modify (&se->pre, cdata, tmp);
7692 /* Use memcpy to do the transfer. */
7693 if (mold_expr->ts.type == BT_CLASS)
7694 tmp = gfc_class_data_get (tmpdecl);
7695 else
7696 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
7698 tmp = build_call_expr_loc (input_location,
7699 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7700 fold_convert (pvoid_type_node, tmp),
7701 fold_convert (pvoid_type_node, ptr),
7702 fold_convert (size_type_node, extent));
7703 gfc_add_expr_to_block (&se->pre, tmp);
7705 /* For CLASS results, set the _vptr. */
7706 if (mold_expr->ts.type == BT_CLASS)
7708 tree vptr;
7709 gfc_symbol *vtab;
7710 vptr = gfc_class_vptr_get (tmpdecl);
7711 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
7712 gcc_assert (vtab);
7713 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7714 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
7717 se->expr = tmpdecl;
7722 /* Generate a call to caf_is_present. */
7724 static tree
7725 trans_caf_is_present (gfc_se *se, gfc_expr *expr)
7727 tree caf_reference, caf_decl, token, image_index;
7729 /* Compile the reference chain. */
7730 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
7731 gcc_assert (caf_reference != NULL_TREE);
7733 caf_decl = gfc_get_tree_for_caf_expr (expr);
7734 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
7735 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
7736 image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
7737 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
7738 expr);
7740 return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
7741 3, token, image_index, caf_reference);
7745 /* Test whether this ref-chain refs this image only. */
7747 static bool
7748 caf_this_image_ref (gfc_ref *ref)
7750 for ( ; ref; ref = ref->next)
7751 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
7752 return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
7754 return false;
7758 /* Generate code for the ALLOCATED intrinsic.
7759 Generate inline code that directly check the address of the argument. */
7761 static void
7762 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
7764 gfc_actual_arglist *arg1;
7765 gfc_se arg1se;
7766 tree tmp;
7767 symbol_attribute caf_attr;
7769 gfc_init_se (&arg1se, NULL);
7770 arg1 = expr->value.function.actual;
7772 if (arg1->expr->ts.type == BT_CLASS)
7774 /* Make sure that class array expressions have both a _data
7775 component reference and an array reference.... */
7776 if (CLASS_DATA (arg1->expr)->attr.dimension)
7777 gfc_add_class_array_ref (arg1->expr);
7778 /* .... whilst scalars only need the _data component. */
7779 else
7780 gfc_add_data_component (arg1->expr);
7783 /* When arg1 references an allocatable component in a coarray, then call
7784 the caf-library function caf_is_present (). */
7785 if (flag_coarray == GFC_FCOARRAY_LIB && arg1->expr->expr_type == EXPR_FUNCTION
7786 && arg1->expr->value.function.isym
7787 && arg1->expr->value.function.isym->id == GFC_ISYM_CAF_GET)
7788 caf_attr = gfc_caf_attr (arg1->expr->value.function.actual->expr);
7789 else
7790 gfc_clear_attr (&caf_attr);
7791 if (flag_coarray == GFC_FCOARRAY_LIB && caf_attr.codimension
7792 && !caf_this_image_ref (arg1->expr->value.function.actual->expr->ref))
7793 tmp = trans_caf_is_present (se, arg1->expr->value.function.actual->expr);
7794 else
7796 if (arg1->expr->rank == 0)
7798 /* Allocatable scalar. */
7799 arg1se.want_pointer = 1;
7800 gfc_conv_expr (&arg1se, arg1->expr);
7801 tmp = arg1se.expr;
7803 else
7805 /* Allocatable array. */
7806 arg1se.descriptor_only = 1;
7807 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7808 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
7811 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
7812 fold_convert (TREE_TYPE (tmp), null_pointer_node));
7815 /* Components of pointer array references sometimes come back with a pre block. */
7816 if (arg1se.pre.head)
7817 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7819 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
7823 /* Generate code for the ASSOCIATED intrinsic.
7824 If both POINTER and TARGET are arrays, generate a call to library function
7825 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
7826 In other cases, generate inline code that directly compare the address of
7827 POINTER with the address of TARGET. */
7829 static void
7830 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
7832 gfc_actual_arglist *arg1;
7833 gfc_actual_arglist *arg2;
7834 gfc_se arg1se;
7835 gfc_se arg2se;
7836 tree tmp2;
7837 tree tmp;
7838 tree nonzero_charlen;
7839 tree nonzero_arraylen;
7840 gfc_ss *ss;
7841 bool scalar;
7843 gfc_init_se (&arg1se, NULL);
7844 gfc_init_se (&arg2se, NULL);
7845 arg1 = expr->value.function.actual;
7846 arg2 = arg1->next;
7848 /* Check whether the expression is a scalar or not; we cannot use
7849 arg1->expr->rank as it can be nonzero for proc pointers. */
7850 ss = gfc_walk_expr (arg1->expr);
7851 scalar = ss == gfc_ss_terminator;
7852 if (!scalar)
7853 gfc_free_ss_chain (ss);
7855 if (!arg2->expr)
7857 /* No optional target. */
7858 if (scalar)
7860 /* A pointer to a scalar. */
7861 arg1se.want_pointer = 1;
7862 gfc_conv_expr (&arg1se, arg1->expr);
7863 if (arg1->expr->symtree->n.sym->attr.proc_pointer
7864 && arg1->expr->symtree->n.sym->attr.dummy)
7865 arg1se.expr = build_fold_indirect_ref_loc (input_location,
7866 arg1se.expr);
7867 if (arg1->expr->ts.type == BT_CLASS)
7869 tmp2 = gfc_class_data_get (arg1se.expr);
7870 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
7871 tmp2 = gfc_conv_descriptor_data_get (tmp2);
7873 else
7874 tmp2 = arg1se.expr;
7876 else
7878 /* A pointer to an array. */
7879 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7880 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
7882 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7883 gfc_add_block_to_block (&se->post, &arg1se.post);
7884 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp2,
7885 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
7886 se->expr = tmp;
7888 else
7890 /* An optional target. */
7891 if (arg2->expr->ts.type == BT_CLASS)
7892 gfc_add_data_component (arg2->expr);
7894 nonzero_charlen = NULL_TREE;
7895 if (arg1->expr->ts.type == BT_CHARACTER)
7896 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
7897 logical_type_node,
7898 arg1->expr->ts.u.cl->backend_decl,
7899 build_zero_cst
7900 (TREE_TYPE (arg1->expr->ts.u.cl->backend_decl)));
7901 if (scalar)
7903 /* A pointer to a scalar. */
7904 arg1se.want_pointer = 1;
7905 gfc_conv_expr (&arg1se, arg1->expr);
7906 if (arg1->expr->symtree->n.sym->attr.proc_pointer
7907 && arg1->expr->symtree->n.sym->attr.dummy)
7908 arg1se.expr = build_fold_indirect_ref_loc (input_location,
7909 arg1se.expr);
7910 if (arg1->expr->ts.type == BT_CLASS)
7911 arg1se.expr = gfc_class_data_get (arg1se.expr);
7913 arg2se.want_pointer = 1;
7914 gfc_conv_expr (&arg2se, arg2->expr);
7915 if (arg2->expr->symtree->n.sym->attr.proc_pointer
7916 && arg2->expr->symtree->n.sym->attr.dummy)
7917 arg2se.expr = build_fold_indirect_ref_loc (input_location,
7918 arg2se.expr);
7919 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7920 gfc_add_block_to_block (&se->post, &arg1se.post);
7921 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7922 gfc_add_block_to_block (&se->post, &arg2se.post);
7923 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7924 arg1se.expr, arg2se.expr);
7925 tmp2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7926 arg1se.expr, null_pointer_node);
7927 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7928 logical_type_node, tmp, tmp2);
7930 else
7932 /* An array pointer of zero length is not associated if target is
7933 present. */
7934 arg1se.descriptor_only = 1;
7935 gfc_conv_expr_lhs (&arg1se, arg1->expr);
7936 if (arg1->expr->rank == -1)
7938 tmp = gfc_conv_descriptor_rank (arg1se.expr);
7939 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7940 TREE_TYPE (tmp), tmp, gfc_index_one_node);
7942 else
7943 tmp = gfc_rank_cst[arg1->expr->rank - 1];
7944 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
7945 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
7946 logical_type_node, tmp,
7947 build_int_cst (TREE_TYPE (tmp), 0));
7949 /* A pointer to an array, call library function _gfor_associated. */
7950 arg1se.want_pointer = 1;
7951 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7952 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7953 gfc_add_block_to_block (&se->post, &arg1se.post);
7955 arg2se.want_pointer = 1;
7956 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
7957 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7958 gfc_add_block_to_block (&se->post, &arg2se.post);
7959 se->expr = build_call_expr_loc (input_location,
7960 gfor_fndecl_associated, 2,
7961 arg1se.expr, arg2se.expr);
7962 se->expr = convert (logical_type_node, se->expr);
7963 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7964 logical_type_node, se->expr,
7965 nonzero_arraylen);
7968 /* If target is present zero character length pointers cannot
7969 be associated. */
7970 if (nonzero_charlen != NULL_TREE)
7971 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7972 logical_type_node,
7973 se->expr, nonzero_charlen);
7976 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7980 /* Generate code for the SAME_TYPE_AS intrinsic.
7981 Generate inline code that directly checks the vindices. */
7983 static void
7984 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
7986 gfc_expr *a, *b;
7987 gfc_se se1, se2;
7988 tree tmp;
7989 tree conda = NULL_TREE, condb = NULL_TREE;
7991 gfc_init_se (&se1, NULL);
7992 gfc_init_se (&se2, NULL);
7994 a = expr->value.function.actual->expr;
7995 b = expr->value.function.actual->next->expr;
7997 if (UNLIMITED_POLY (a))
7999 tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
8000 conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8001 tmp, build_int_cst (TREE_TYPE (tmp), 0));
8004 if (UNLIMITED_POLY (b))
8006 tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
8007 condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8008 tmp, build_int_cst (TREE_TYPE (tmp), 0));
8011 if (a->ts.type == BT_CLASS)
8013 gfc_add_vptr_component (a);
8014 gfc_add_hash_component (a);
8016 else if (a->ts.type == BT_DERIVED)
8017 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
8018 a->ts.u.derived->hash_value);
8020 if (b->ts.type == BT_CLASS)
8022 gfc_add_vptr_component (b);
8023 gfc_add_hash_component (b);
8025 else if (b->ts.type == BT_DERIVED)
8026 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
8027 b->ts.u.derived->hash_value);
8029 gfc_conv_expr (&se1, a);
8030 gfc_conv_expr (&se2, b);
8032 tmp = fold_build2_loc (input_location, EQ_EXPR,
8033 logical_type_node, se1.expr,
8034 fold_convert (TREE_TYPE (se1.expr), se2.expr));
8036 if (conda)
8037 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
8038 logical_type_node, conda, tmp);
8040 if (condb)
8041 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
8042 logical_type_node, condb, tmp);
8044 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
8048 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
8050 static void
8051 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
8053 tree args[2];
8055 gfc_conv_intrinsic_function_args (se, expr, args, 2);
8056 se->expr = build_call_expr_loc (input_location,
8057 gfor_fndecl_sc_kind, 2, args[0], args[1]);
8058 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8062 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
8064 static void
8065 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
8067 tree arg, type;
8069 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8071 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
8072 type = gfc_get_int_type (4);
8073 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
8075 /* Convert it to the required type. */
8076 type = gfc_typenode_for_spec (&expr->ts);
8077 se->expr = build_call_expr_loc (input_location,
8078 gfor_fndecl_si_kind, 1, arg);
8079 se->expr = fold_convert (type, se->expr);
8083 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
8085 static void
8086 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
8088 gfc_actual_arglist *actual;
8089 tree type;
8090 gfc_se argse;
8091 vec<tree, va_gc> *args = NULL;
8093 for (actual = expr->value.function.actual; actual; actual = actual->next)
8095 gfc_init_se (&argse, se);
8097 /* Pass a NULL pointer for an absent arg. */
8098 if (actual->expr == NULL)
8099 argse.expr = null_pointer_node;
8100 else
8102 gfc_typespec ts;
8103 gfc_clear_ts (&ts);
8105 if (actual->expr->ts.kind != gfc_c_int_kind)
8107 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
8108 ts.type = BT_INTEGER;
8109 ts.kind = gfc_c_int_kind;
8110 gfc_convert_type (actual->expr, &ts, 2);
8112 gfc_conv_expr_reference (&argse, actual->expr);
8115 gfc_add_block_to_block (&se->pre, &argse.pre);
8116 gfc_add_block_to_block (&se->post, &argse.post);
8117 vec_safe_push (args, argse.expr);
8120 /* Convert it to the required type. */
8121 type = gfc_typenode_for_spec (&expr->ts);
8122 se->expr = build_call_expr_loc_vec (input_location,
8123 gfor_fndecl_sr_kind, args);
8124 se->expr = fold_convert (type, se->expr);
8128 /* Generate code for TRIM (A) intrinsic function. */
8130 static void
8131 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
8133 tree var;
8134 tree len;
8135 tree addr;
8136 tree tmp;
8137 tree cond;
8138 tree fndecl;
8139 tree function;
8140 tree *args;
8141 unsigned int num_args;
8143 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
8144 args = XALLOCAVEC (tree, num_args);
8146 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
8147 addr = gfc_build_addr_expr (ppvoid_type_node, var);
8148 len = gfc_create_var (gfc_charlen_type_node, "len");
8150 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
8151 args[0] = gfc_build_addr_expr (NULL_TREE, len);
8152 args[1] = addr;
8154 if (expr->ts.kind == 1)
8155 function = gfor_fndecl_string_trim;
8156 else if (expr->ts.kind == 4)
8157 function = gfor_fndecl_string_trim_char4;
8158 else
8159 gcc_unreachable ();
8161 fndecl = build_addr (function);
8162 tmp = build_call_array_loc (input_location,
8163 TREE_TYPE (TREE_TYPE (function)), fndecl,
8164 num_args, args);
8165 gfc_add_expr_to_block (&se->pre, tmp);
8167 /* Free the temporary afterwards, if necessary. */
8168 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
8169 len, build_int_cst (TREE_TYPE (len), 0));
8170 tmp = gfc_call_free (var);
8171 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
8172 gfc_add_expr_to_block (&se->post, tmp);
8174 se->expr = var;
8175 se->string_length = len;
8179 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
8181 static void
8182 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
8184 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
8185 tree type, cond, tmp, count, exit_label, n, max, largest;
8186 tree size;
8187 stmtblock_t block, body;
8188 int i;
8190 /* We store in charsize the size of a character. */
8191 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
8192 size = build_int_cst (sizetype, gfc_character_kinds[i].bit_size / 8);
8194 /* Get the arguments. */
8195 gfc_conv_intrinsic_function_args (se, expr, args, 3);
8196 slen = fold_convert (sizetype, gfc_evaluate_now (args[0], &se->pre));
8197 src = args[1];
8198 ncopies = gfc_evaluate_now (args[2], &se->pre);
8199 ncopies_type = TREE_TYPE (ncopies);
8201 /* Check that NCOPIES is not negative. */
8202 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, ncopies,
8203 build_int_cst (ncopies_type, 0));
8204 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
8205 "Argument NCOPIES of REPEAT intrinsic is negative "
8206 "(its value is %ld)",
8207 fold_convert (long_integer_type_node, ncopies));
8209 /* If the source length is zero, any non negative value of NCOPIES
8210 is valid, and nothing happens. */
8211 n = gfc_create_var (ncopies_type, "ncopies");
8212 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
8213 size_zero_node);
8214 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
8215 build_int_cst (ncopies_type, 0), ncopies);
8216 gfc_add_modify (&se->pre, n, tmp);
8217 ncopies = n;
8219 /* Check that ncopies is not too large: ncopies should be less than
8220 (or equal to) MAX / slen, where MAX is the maximal integer of
8221 the gfc_charlen_type_node type. If slen == 0, we need a special
8222 case to avoid the division by zero. */
8223 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, sizetype,
8224 fold_convert (sizetype,
8225 TYPE_MAX_VALUE (gfc_charlen_type_node)),
8226 slen);
8227 largest = TYPE_PRECISION (sizetype) > TYPE_PRECISION (ncopies_type)
8228 ? sizetype : ncopies_type;
8229 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
8230 fold_convert (largest, ncopies),
8231 fold_convert (largest, max));
8232 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
8233 size_zero_node);
8234 cond = fold_build3_loc (input_location, COND_EXPR, logical_type_node, tmp,
8235 logical_false_node, cond);
8236 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
8237 "Argument NCOPIES of REPEAT intrinsic is too large");
8239 /* Compute the destination length. */
8240 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
8241 fold_convert (gfc_charlen_type_node, slen),
8242 fold_convert (gfc_charlen_type_node, ncopies));
8243 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
8244 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
8246 /* Generate the code to do the repeat operation:
8247 for (i = 0; i < ncopies; i++)
8248 memmove (dest + (i * slen * size), src, slen*size); */
8249 gfc_start_block (&block);
8250 count = gfc_create_var (sizetype, "count");
8251 gfc_add_modify (&block, count, size_zero_node);
8252 exit_label = gfc_build_label_decl (NULL_TREE);
8254 /* Start the loop body. */
8255 gfc_start_block (&body);
8257 /* Exit the loop if count >= ncopies. */
8258 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, count,
8259 fold_convert (sizetype, ncopies));
8260 tmp = build1_v (GOTO_EXPR, exit_label);
8261 TREE_USED (exit_label) = 1;
8262 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
8263 build_empty_stmt (input_location));
8264 gfc_add_expr_to_block (&body, tmp);
8266 /* Call memmove (dest + (i*slen*size), src, slen*size). */
8267 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, slen,
8268 count);
8269 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, tmp,
8270 size);
8271 tmp = fold_build_pointer_plus_loc (input_location,
8272 fold_convert (pvoid_type_node, dest), tmp);
8273 tmp = build_call_expr_loc (input_location,
8274 builtin_decl_explicit (BUILT_IN_MEMMOVE),
8275 3, tmp, src,
8276 fold_build2_loc (input_location, MULT_EXPR,
8277 size_type_node, slen, size));
8278 gfc_add_expr_to_block (&body, tmp);
8280 /* Increment count. */
8281 tmp = fold_build2_loc (input_location, PLUS_EXPR, sizetype,
8282 count, size_one_node);
8283 gfc_add_modify (&body, count, tmp);
8285 /* Build the loop. */
8286 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
8287 gfc_add_expr_to_block (&block, tmp);
8289 /* Add the exit label. */
8290 tmp = build1_v (LABEL_EXPR, exit_label);
8291 gfc_add_expr_to_block (&block, tmp);
8293 /* Finish the block. */
8294 tmp = gfc_finish_block (&block);
8295 gfc_add_expr_to_block (&se->pre, tmp);
8297 /* Set the result value. */
8298 se->expr = dest;
8299 se->string_length = dlen;
8303 /* Generate code for the IARGC intrinsic. */
8305 static void
8306 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
8308 tree tmp;
8309 tree fndecl;
8310 tree type;
8312 /* Call the library function. This always returns an INTEGER(4). */
8313 fndecl = gfor_fndecl_iargc;
8314 tmp = build_call_expr_loc (input_location,
8315 fndecl, 0);
8317 /* Convert it to the required type. */
8318 type = gfc_typenode_for_spec (&expr->ts);
8319 tmp = fold_convert (type, tmp);
8321 se->expr = tmp;
8325 /* Generate code for the KILL intrinsic. */
8327 static void
8328 conv_intrinsic_kill (gfc_se *se, gfc_expr *expr)
8330 tree *args;
8331 tree int4_type_node = gfc_get_int_type (4);
8332 tree pid;
8333 tree sig;
8334 tree tmp;
8335 unsigned int num_args;
8337 num_args = gfc_intrinsic_argument_list_length (expr);
8338 args = XALLOCAVEC (tree, num_args);
8339 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
8341 /* Convert PID to a INTEGER(4) entity. */
8342 pid = convert (int4_type_node, args[0]);
8344 /* Convert SIG to a INTEGER(4) entity. */
8345 sig = convert (int4_type_node, args[1]);
8347 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill, 2, pid, sig);
8349 se->expr = fold_convert (TREE_TYPE (args[0]), tmp);
8353 static tree
8354 conv_intrinsic_kill_sub (gfc_code *code)
8356 stmtblock_t block;
8357 gfc_se se, se_stat;
8358 tree int4_type_node = gfc_get_int_type (4);
8359 tree pid;
8360 tree sig;
8361 tree statp;
8362 tree tmp;
8364 /* Make the function call. */
8365 gfc_init_block (&block);
8366 gfc_init_se (&se, NULL);
8368 /* Convert PID to a INTEGER(4) entity. */
8369 gfc_conv_expr (&se, code->ext.actual->expr);
8370 gfc_add_block_to_block (&block, &se.pre);
8371 pid = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
8372 gfc_add_block_to_block (&block, &se.post);
8374 /* Convert SIG to a INTEGER(4) entity. */
8375 gfc_conv_expr (&se, code->ext.actual->next->expr);
8376 gfc_add_block_to_block (&block, &se.pre);
8377 sig = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
8378 gfc_add_block_to_block (&block, &se.post);
8380 /* Deal with an optional STATUS. */
8381 if (code->ext.actual->next->next->expr)
8383 gfc_init_se (&se_stat, NULL);
8384 gfc_conv_expr (&se_stat, code->ext.actual->next->next->expr);
8385 statp = gfc_create_var (gfc_get_int_type (4), "_statp");
8387 else
8388 statp = NULL_TREE;
8390 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill_sub, 3, pid, sig,
8391 statp ? gfc_build_addr_expr (NULL_TREE, statp) : null_pointer_node);
8393 gfc_add_expr_to_block (&block, tmp);
8395 if (statp && statp != se_stat.expr)
8396 gfc_add_modify (&block, se_stat.expr,
8397 fold_convert (TREE_TYPE (se_stat.expr), statp));
8399 return gfc_finish_block (&block);
8404 /* The loc intrinsic returns the address of its argument as
8405 gfc_index_integer_kind integer. */
8407 static void
8408 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
8410 tree temp_var;
8411 gfc_expr *arg_expr;
8413 gcc_assert (!se->ss);
8415 arg_expr = expr->value.function.actual->expr;
8416 if (arg_expr->rank == 0)
8418 if (arg_expr->ts.type == BT_CLASS)
8419 gfc_add_data_component (arg_expr);
8420 gfc_conv_expr_reference (se, arg_expr);
8422 else
8423 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
8424 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
8426 /* Create a temporary variable for loc return value. Without this,
8427 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
8428 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
8429 gfc_add_modify (&se->pre, temp_var, se->expr);
8430 se->expr = temp_var;
8434 /* The following routine generates code for the intrinsic
8435 functions from the ISO_C_BINDING module:
8436 * C_LOC
8437 * C_FUNLOC
8438 * C_ASSOCIATED */
8440 static void
8441 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
8443 gfc_actual_arglist *arg = expr->value.function.actual;
8445 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
8447 if (arg->expr->rank == 0)
8448 gfc_conv_expr_reference (se, arg->expr);
8449 else if (gfc_is_simply_contiguous (arg->expr, false, false))
8450 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
8451 else
8453 gfc_conv_expr_descriptor (se, arg->expr);
8454 se->expr = gfc_conv_descriptor_data_get (se->expr);
8457 /* TODO -- the following two lines shouldn't be necessary, but if
8458 they're removed, a bug is exposed later in the code path.
8459 This workaround was thus introduced, but will have to be
8460 removed; please see PR 35150 for details about the issue. */
8461 se->expr = convert (pvoid_type_node, se->expr);
8462 se->expr = gfc_evaluate_now (se->expr, &se->pre);
8464 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
8465 gfc_conv_expr_reference (se, arg->expr);
8466 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
8468 gfc_se arg1se;
8469 gfc_se arg2se;
8471 /* Build the addr_expr for the first argument. The argument is
8472 already an *address* so we don't need to set want_pointer in
8473 the gfc_se. */
8474 gfc_init_se (&arg1se, NULL);
8475 gfc_conv_expr (&arg1se, arg->expr);
8476 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8477 gfc_add_block_to_block (&se->post, &arg1se.post);
8479 /* See if we were given two arguments. */
8480 if (arg->next->expr == NULL)
8481 /* Only given one arg so generate a null and do a
8482 not-equal comparison against the first arg. */
8483 se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8484 arg1se.expr,
8485 fold_convert (TREE_TYPE (arg1se.expr),
8486 null_pointer_node));
8487 else
8489 tree eq_expr;
8490 tree not_null_expr;
8492 /* Given two arguments so build the arg2se from second arg. */
8493 gfc_init_se (&arg2se, NULL);
8494 gfc_conv_expr (&arg2se, arg->next->expr);
8495 gfc_add_block_to_block (&se->pre, &arg2se.pre);
8496 gfc_add_block_to_block (&se->post, &arg2se.post);
8498 /* Generate test to compare that the two args are equal. */
8499 eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
8500 arg1se.expr, arg2se.expr);
8501 /* Generate test to ensure that the first arg is not null. */
8502 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
8503 logical_type_node,
8504 arg1se.expr, null_pointer_node);
8506 /* Finally, the generated test must check that both arg1 is not
8507 NULL and that it is equal to the second arg. */
8508 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8509 logical_type_node,
8510 not_null_expr, eq_expr);
8513 else
8514 gcc_unreachable ();
8518 /* The following routine generates code for the intrinsic
8519 subroutines from the ISO_C_BINDING module:
8520 * C_F_POINTER
8521 * C_F_PROCPOINTER. */
8523 static tree
8524 conv_isocbinding_subroutine (gfc_code *code)
8526 gfc_se se;
8527 gfc_se cptrse;
8528 gfc_se fptrse;
8529 gfc_se shapese;
8530 gfc_ss *shape_ss;
8531 tree desc, dim, tmp, stride, offset;
8532 stmtblock_t body, block;
8533 gfc_loopinfo loop;
8534 gfc_actual_arglist *arg = code->ext.actual;
8536 gfc_init_se (&se, NULL);
8537 gfc_init_se (&cptrse, NULL);
8538 gfc_conv_expr (&cptrse, arg->expr);
8539 gfc_add_block_to_block (&se.pre, &cptrse.pre);
8540 gfc_add_block_to_block (&se.post, &cptrse.post);
8542 gfc_init_se (&fptrse, NULL);
8543 if (arg->next->expr->rank == 0)
8545 fptrse.want_pointer = 1;
8546 gfc_conv_expr (&fptrse, arg->next->expr);
8547 gfc_add_block_to_block (&se.pre, &fptrse.pre);
8548 gfc_add_block_to_block (&se.post, &fptrse.post);
8549 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
8550 && arg->next->expr->symtree->n.sym->attr.dummy)
8551 fptrse.expr = build_fold_indirect_ref_loc (input_location,
8552 fptrse.expr);
8553 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
8554 TREE_TYPE (fptrse.expr),
8555 fptrse.expr,
8556 fold_convert (TREE_TYPE (fptrse.expr),
8557 cptrse.expr));
8558 gfc_add_expr_to_block (&se.pre, se.expr);
8559 gfc_add_block_to_block (&se.pre, &se.post);
8560 return gfc_finish_block (&se.pre);
8563 gfc_start_block (&block);
8565 /* Get the descriptor of the Fortran pointer. */
8566 fptrse.descriptor_only = 1;
8567 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
8568 gfc_add_block_to_block (&block, &fptrse.pre);
8569 desc = fptrse.expr;
8571 /* Set the span field. */
8572 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
8573 tmp = fold_convert (gfc_array_index_type, tmp);
8574 gfc_conv_descriptor_span_set (&block, desc, tmp);
8576 /* Set data value, dtype, and offset. */
8577 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
8578 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
8579 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
8580 gfc_get_dtype (TREE_TYPE (desc)));
8582 /* Start scalarization of the bounds, using the shape argument. */
8584 shape_ss = gfc_walk_expr (arg->next->next->expr);
8585 gcc_assert (shape_ss != gfc_ss_terminator);
8586 gfc_init_se (&shapese, NULL);
8588 gfc_init_loopinfo (&loop);
8589 gfc_add_ss_to_loop (&loop, shape_ss);
8590 gfc_conv_ss_startstride (&loop);
8591 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
8592 gfc_mark_ss_chain_used (shape_ss, 1);
8594 gfc_copy_loopinfo_to_se (&shapese, &loop);
8595 shapese.ss = shape_ss;
8597 stride = gfc_create_var (gfc_array_index_type, "stride");
8598 offset = gfc_create_var (gfc_array_index_type, "offset");
8599 gfc_add_modify (&block, stride, gfc_index_one_node);
8600 gfc_add_modify (&block, offset, gfc_index_zero_node);
8602 /* Loop body. */
8603 gfc_start_scalarized_body (&loop, &body);
8605 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8606 loop.loopvar[0], loop.from[0]);
8608 /* Set bounds and stride. */
8609 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
8610 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
8612 gfc_conv_expr (&shapese, arg->next->next->expr);
8613 gfc_add_block_to_block (&body, &shapese.pre);
8614 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
8615 gfc_add_block_to_block (&body, &shapese.post);
8617 /* Calculate offset. */
8618 gfc_add_modify (&body, offset,
8619 fold_build2_loc (input_location, PLUS_EXPR,
8620 gfc_array_index_type, offset, stride));
8621 /* Update stride. */
8622 gfc_add_modify (&body, stride,
8623 fold_build2_loc (input_location, MULT_EXPR,
8624 gfc_array_index_type, stride,
8625 fold_convert (gfc_array_index_type,
8626 shapese.expr)));
8627 /* Finish scalarization loop. */
8628 gfc_trans_scalarizing_loops (&loop, &body);
8629 gfc_add_block_to_block (&block, &loop.pre);
8630 gfc_add_block_to_block (&block, &loop.post);
8631 gfc_add_block_to_block (&block, &fptrse.post);
8632 gfc_cleanup_loop (&loop);
8634 gfc_add_modify (&block, offset,
8635 fold_build1_loc (input_location, NEGATE_EXPR,
8636 gfc_array_index_type, offset));
8637 gfc_conv_descriptor_offset_set (&block, desc, offset);
8639 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
8640 gfc_add_block_to_block (&se.pre, &se.post);
8641 return gfc_finish_block (&se.pre);
8645 /* Save and restore floating-point state. */
8647 tree
8648 gfc_save_fp_state (stmtblock_t *block)
8650 tree type, fpstate, tmp;
8652 type = build_array_type (char_type_node,
8653 build_range_type (size_type_node, size_zero_node,
8654 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
8655 fpstate = gfc_create_var (type, "fpstate");
8656 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
8658 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
8659 1, fpstate);
8660 gfc_add_expr_to_block (block, tmp);
8662 return fpstate;
8666 void
8667 gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
8669 tree tmp;
8671 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
8672 1, fpstate);
8673 gfc_add_expr_to_block (block, tmp);
8677 /* Generate code for arguments of IEEE functions. */
8679 static void
8680 conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
8681 int nargs)
8683 gfc_actual_arglist *actual;
8684 gfc_expr *e;
8685 gfc_se argse;
8686 int arg;
8688 actual = expr->value.function.actual;
8689 for (arg = 0; arg < nargs; arg++, actual = actual->next)
8691 gcc_assert (actual);
8692 e = actual->expr;
8694 gfc_init_se (&argse, se);
8695 gfc_conv_expr_val (&argse, e);
8697 gfc_add_block_to_block (&se->pre, &argse.pre);
8698 gfc_add_block_to_block (&se->post, &argse.post);
8699 argarray[arg] = argse.expr;
8704 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
8705 and IEEE_UNORDERED, which translate directly to GCC type-generic
8706 built-ins. */
8708 static void
8709 conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
8710 enum built_in_function code, int nargs)
8712 tree args[2];
8713 gcc_assert ((unsigned) nargs <= sizeof(args)/sizeof(args[0]));
8715 conv_ieee_function_args (se, expr, args, nargs);
8716 se->expr = build_call_expr_loc_array (input_location,
8717 builtin_decl_explicit (code),
8718 nargs, args);
8719 STRIP_TYPE_NOPS (se->expr);
8720 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8724 /* Generate code for IEEE_IS_NORMAL intrinsic:
8725 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
8727 static void
8728 conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
8730 tree arg, isnormal, iszero;
8732 /* Convert arg, evaluate it only once. */
8733 conv_ieee_function_args (se, expr, &arg, 1);
8734 arg = gfc_evaluate_now (arg, &se->pre);
8736 isnormal = build_call_expr_loc (input_location,
8737 builtin_decl_explicit (BUILT_IN_ISNORMAL),
8738 1, arg);
8739 iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
8740 build_real_from_int_cst (TREE_TYPE (arg),
8741 integer_zero_node));
8742 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
8743 logical_type_node, isnormal, iszero);
8744 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8748 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
8749 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
8751 static void
8752 conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
8754 tree arg, signbit, isnan;
8756 /* Convert arg, evaluate it only once. */
8757 conv_ieee_function_args (se, expr, &arg, 1);
8758 arg = gfc_evaluate_now (arg, &se->pre);
8760 isnan = build_call_expr_loc (input_location,
8761 builtin_decl_explicit (BUILT_IN_ISNAN),
8762 1, arg);
8763 STRIP_TYPE_NOPS (isnan);
8765 signbit = build_call_expr_loc (input_location,
8766 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8767 1, arg);
8768 signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8769 signbit, integer_zero_node);
8771 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8772 logical_type_node, signbit,
8773 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
8774 TREE_TYPE(isnan), isnan));
8776 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8780 /* Generate code for IEEE_LOGB and IEEE_RINT. */
8782 static void
8783 conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
8784 enum built_in_function code)
8786 tree arg, decl, call, fpstate;
8787 int argprec;
8789 conv_ieee_function_args (se, expr, &arg, 1);
8790 argprec = TYPE_PRECISION (TREE_TYPE (arg));
8791 decl = builtin_decl_for_precision (code, argprec);
8793 /* Save floating-point state. */
8794 fpstate = gfc_save_fp_state (&se->pre);
8796 /* Make the function call. */
8797 call = build_call_expr_loc (input_location, decl, 1, arg);
8798 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
8800 /* Restore floating-point state. */
8801 gfc_restore_fp_state (&se->post, fpstate);
8805 /* Generate code for IEEE_REM. */
8807 static void
8808 conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
8810 tree args[2], decl, call, fpstate;
8811 int argprec;
8813 conv_ieee_function_args (se, expr, args, 2);
8815 /* If arguments have unequal size, convert them to the larger. */
8816 if (TYPE_PRECISION (TREE_TYPE (args[0]))
8817 > TYPE_PRECISION (TREE_TYPE (args[1])))
8818 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8819 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
8820 > TYPE_PRECISION (TREE_TYPE (args[0])))
8821 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
8823 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8824 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
8826 /* Save floating-point state. */
8827 fpstate = gfc_save_fp_state (&se->pre);
8829 /* Make the function call. */
8830 call = build_call_expr_loc_array (input_location, decl, 2, args);
8831 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8833 /* Restore floating-point state. */
8834 gfc_restore_fp_state (&se->post, fpstate);
8838 /* Generate code for IEEE_NEXT_AFTER. */
8840 static void
8841 conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
8843 tree args[2], decl, call, fpstate;
8844 int argprec;
8846 conv_ieee_function_args (se, expr, args, 2);
8848 /* Result has the characteristics of first argument. */
8849 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8850 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8851 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
8853 /* Save floating-point state. */
8854 fpstate = gfc_save_fp_state (&se->pre);
8856 /* Make the function call. */
8857 call = build_call_expr_loc_array (input_location, decl, 2, args);
8858 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8860 /* Restore floating-point state. */
8861 gfc_restore_fp_state (&se->post, fpstate);
8865 /* Generate code for IEEE_SCALB. */
8867 static void
8868 conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
8870 tree args[2], decl, call, huge, type;
8871 int argprec, n;
8873 conv_ieee_function_args (se, expr, args, 2);
8875 /* Result has the characteristics of first argument. */
8876 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8877 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
8879 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
8881 /* We need to fold the integer into the range of a C int. */
8882 args[1] = gfc_evaluate_now (args[1], &se->pre);
8883 type = TREE_TYPE (args[1]);
8885 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
8886 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
8887 gfc_c_int_kind);
8888 huge = fold_convert (type, huge);
8889 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
8890 huge);
8891 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
8892 fold_build1_loc (input_location, NEGATE_EXPR,
8893 type, huge));
8896 args[1] = fold_convert (integer_type_node, args[1]);
8898 /* Make the function call. */
8899 call = build_call_expr_loc_array (input_location, decl, 2, args);
8900 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8904 /* Generate code for IEEE_COPY_SIGN. */
8906 static void
8907 conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
8909 tree args[2], decl, sign;
8910 int argprec;
8912 conv_ieee_function_args (se, expr, args, 2);
8914 /* Get the sign of the second argument. */
8915 sign = build_call_expr_loc (input_location,
8916 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8917 1, args[1]);
8918 sign = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8919 sign, integer_zero_node);
8921 /* Create a value of one, with the right sign. */
8922 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
8923 sign,
8924 fold_build1_loc (input_location, NEGATE_EXPR,
8925 integer_type_node,
8926 integer_one_node),
8927 integer_one_node);
8928 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
8930 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8931 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
8933 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
8937 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
8938 module. */
8940 bool
8941 gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
8943 const char *name = expr->value.function.name;
8945 #define STARTS_WITH(A,B) (strncmp((A), (B), strlen(B)) == 0)
8947 if (STARTS_WITH (name, "_gfortran_ieee_is_nan"))
8948 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
8949 else if (STARTS_WITH (name, "_gfortran_ieee_is_finite"))
8950 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
8951 else if (STARTS_WITH (name, "_gfortran_ieee_unordered"))
8952 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
8953 else if (STARTS_WITH (name, "_gfortran_ieee_is_normal"))
8954 conv_intrinsic_ieee_is_normal (se, expr);
8955 else if (STARTS_WITH (name, "_gfortran_ieee_is_negative"))
8956 conv_intrinsic_ieee_is_negative (se, expr);
8957 else if (STARTS_WITH (name, "_gfortran_ieee_copy_sign"))
8958 conv_intrinsic_ieee_copy_sign (se, expr);
8959 else if (STARTS_WITH (name, "_gfortran_ieee_scalb"))
8960 conv_intrinsic_ieee_scalb (se, expr);
8961 else if (STARTS_WITH (name, "_gfortran_ieee_next_after"))
8962 conv_intrinsic_ieee_next_after (se, expr);
8963 else if (STARTS_WITH (name, "_gfortran_ieee_rem"))
8964 conv_intrinsic_ieee_rem (se, expr);
8965 else if (STARTS_WITH (name, "_gfortran_ieee_logb"))
8966 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
8967 else if (STARTS_WITH (name, "_gfortran_ieee_rint"))
8968 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
8969 else
8970 /* It is not among the functions we translate directly. We return
8971 false, so a library function call is emitted. */
8972 return false;
8974 #undef STARTS_WITH
8976 return true;
8980 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
8982 static void
8983 gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
8985 tree arg, res, restype;
8987 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8988 arg = fold_convert (size_type_node, arg);
8989 res = build_call_expr_loc (input_location,
8990 builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
8991 restype = gfc_typenode_for_spec (&expr->ts);
8992 se->expr = fold_convert (restype, res);
8996 /* Generate code for an intrinsic function. Some map directly to library
8997 calls, others get special handling. In some cases the name of the function
8998 used depends on the type specifiers. */
9000 void
9001 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
9003 const char *name;
9004 int lib, kind;
9005 tree fndecl;
9007 name = &expr->value.function.name[2];
9009 if (expr->rank > 0)
9011 lib = gfc_is_intrinsic_libcall (expr);
9012 if (lib != 0)
9014 if (lib == 1)
9015 se->ignore_optional = 1;
9017 switch (expr->value.function.isym->id)
9019 case GFC_ISYM_EOSHIFT:
9020 case GFC_ISYM_PACK:
9021 case GFC_ISYM_RESHAPE:
9022 /* For all of those the first argument specifies the type and the
9023 third is optional. */
9024 conv_generic_with_optional_char_arg (se, expr, 1, 3);
9025 break;
9027 case GFC_ISYM_MINLOC:
9028 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
9029 break;
9031 case GFC_ISYM_MAXLOC:
9032 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
9033 break;
9035 case GFC_ISYM_SHAPE:
9036 gfc_conv_intrinsic_shape (se, expr);
9037 break;
9039 default:
9040 gfc_conv_intrinsic_funcall (se, expr);
9041 break;
9044 return;
9048 switch (expr->value.function.isym->id)
9050 case GFC_ISYM_NONE:
9051 gcc_unreachable ();
9053 case GFC_ISYM_REPEAT:
9054 gfc_conv_intrinsic_repeat (se, expr);
9055 break;
9057 case GFC_ISYM_TRIM:
9058 gfc_conv_intrinsic_trim (se, expr);
9059 break;
9061 case GFC_ISYM_SC_KIND:
9062 gfc_conv_intrinsic_sc_kind (se, expr);
9063 break;
9065 case GFC_ISYM_SI_KIND:
9066 gfc_conv_intrinsic_si_kind (se, expr);
9067 break;
9069 case GFC_ISYM_SR_KIND:
9070 gfc_conv_intrinsic_sr_kind (se, expr);
9071 break;
9073 case GFC_ISYM_EXPONENT:
9074 gfc_conv_intrinsic_exponent (se, expr);
9075 break;
9077 case GFC_ISYM_SCAN:
9078 kind = expr->value.function.actual->expr->ts.kind;
9079 if (kind == 1)
9080 fndecl = gfor_fndecl_string_scan;
9081 else if (kind == 4)
9082 fndecl = gfor_fndecl_string_scan_char4;
9083 else
9084 gcc_unreachable ();
9086 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
9087 break;
9089 case GFC_ISYM_VERIFY:
9090 kind = expr->value.function.actual->expr->ts.kind;
9091 if (kind == 1)
9092 fndecl = gfor_fndecl_string_verify;
9093 else if (kind == 4)
9094 fndecl = gfor_fndecl_string_verify_char4;
9095 else
9096 gcc_unreachable ();
9098 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
9099 break;
9101 case GFC_ISYM_ALLOCATED:
9102 gfc_conv_allocated (se, expr);
9103 break;
9105 case GFC_ISYM_ASSOCIATED:
9106 gfc_conv_associated(se, expr);
9107 break;
9109 case GFC_ISYM_SAME_TYPE_AS:
9110 gfc_conv_same_type_as (se, expr);
9111 break;
9113 case GFC_ISYM_ABS:
9114 gfc_conv_intrinsic_abs (se, expr);
9115 break;
9117 case GFC_ISYM_ADJUSTL:
9118 if (expr->ts.kind == 1)
9119 fndecl = gfor_fndecl_adjustl;
9120 else if (expr->ts.kind == 4)
9121 fndecl = gfor_fndecl_adjustl_char4;
9122 else
9123 gcc_unreachable ();
9125 gfc_conv_intrinsic_adjust (se, expr, fndecl);
9126 break;
9128 case GFC_ISYM_ADJUSTR:
9129 if (expr->ts.kind == 1)
9130 fndecl = gfor_fndecl_adjustr;
9131 else if (expr->ts.kind == 4)
9132 fndecl = gfor_fndecl_adjustr_char4;
9133 else
9134 gcc_unreachable ();
9136 gfc_conv_intrinsic_adjust (se, expr, fndecl);
9137 break;
9139 case GFC_ISYM_AIMAG:
9140 gfc_conv_intrinsic_imagpart (se, expr);
9141 break;
9143 case GFC_ISYM_AINT:
9144 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
9145 break;
9147 case GFC_ISYM_ALL:
9148 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
9149 break;
9151 case GFC_ISYM_ANINT:
9152 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
9153 break;
9155 case GFC_ISYM_AND:
9156 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
9157 break;
9159 case GFC_ISYM_ANY:
9160 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
9161 break;
9163 case GFC_ISYM_BTEST:
9164 gfc_conv_intrinsic_btest (se, expr);
9165 break;
9167 case GFC_ISYM_BGE:
9168 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
9169 break;
9171 case GFC_ISYM_BGT:
9172 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
9173 break;
9175 case GFC_ISYM_BLE:
9176 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
9177 break;
9179 case GFC_ISYM_BLT:
9180 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
9181 break;
9183 case GFC_ISYM_C_ASSOCIATED:
9184 case GFC_ISYM_C_FUNLOC:
9185 case GFC_ISYM_C_LOC:
9186 conv_isocbinding_function (se, expr);
9187 break;
9189 case GFC_ISYM_ACHAR:
9190 case GFC_ISYM_CHAR:
9191 gfc_conv_intrinsic_char (se, expr);
9192 break;
9194 case GFC_ISYM_CONVERSION:
9195 case GFC_ISYM_REAL:
9196 case GFC_ISYM_LOGICAL:
9197 case GFC_ISYM_DBLE:
9198 gfc_conv_intrinsic_conversion (se, expr);
9199 break;
9201 /* Integer conversions are handled separately to make sure we get the
9202 correct rounding mode. */
9203 case GFC_ISYM_INT:
9204 case GFC_ISYM_INT2:
9205 case GFC_ISYM_INT8:
9206 case GFC_ISYM_LONG:
9207 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
9208 break;
9210 case GFC_ISYM_NINT:
9211 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
9212 break;
9214 case GFC_ISYM_CEILING:
9215 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
9216 break;
9218 case GFC_ISYM_FLOOR:
9219 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
9220 break;
9222 case GFC_ISYM_MOD:
9223 gfc_conv_intrinsic_mod (se, expr, 0);
9224 break;
9226 case GFC_ISYM_MODULO:
9227 gfc_conv_intrinsic_mod (se, expr, 1);
9228 break;
9230 case GFC_ISYM_CAF_GET:
9231 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
9232 false, NULL);
9233 break;
9235 case GFC_ISYM_CMPLX:
9236 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
9237 break;
9239 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
9240 gfc_conv_intrinsic_iargc (se, expr);
9241 break;
9243 case GFC_ISYM_COMPLEX:
9244 gfc_conv_intrinsic_cmplx (se, expr, 1);
9245 break;
9247 case GFC_ISYM_CONJG:
9248 gfc_conv_intrinsic_conjg (se, expr);
9249 break;
9251 case GFC_ISYM_COUNT:
9252 gfc_conv_intrinsic_count (se, expr);
9253 break;
9255 case GFC_ISYM_CTIME:
9256 gfc_conv_intrinsic_ctime (se, expr);
9257 break;
9259 case GFC_ISYM_DIM:
9260 gfc_conv_intrinsic_dim (se, expr);
9261 break;
9263 case GFC_ISYM_DOT_PRODUCT:
9264 gfc_conv_intrinsic_dot_product (se, expr);
9265 break;
9267 case GFC_ISYM_DPROD:
9268 gfc_conv_intrinsic_dprod (se, expr);
9269 break;
9271 case GFC_ISYM_DSHIFTL:
9272 gfc_conv_intrinsic_dshift (se, expr, true);
9273 break;
9275 case GFC_ISYM_DSHIFTR:
9276 gfc_conv_intrinsic_dshift (se, expr, false);
9277 break;
9279 case GFC_ISYM_FDATE:
9280 gfc_conv_intrinsic_fdate (se, expr);
9281 break;
9283 case GFC_ISYM_FRACTION:
9284 gfc_conv_intrinsic_fraction (se, expr);
9285 break;
9287 case GFC_ISYM_IALL:
9288 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
9289 break;
9291 case GFC_ISYM_IAND:
9292 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
9293 break;
9295 case GFC_ISYM_IANY:
9296 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
9297 break;
9299 case GFC_ISYM_IBCLR:
9300 gfc_conv_intrinsic_singlebitop (se, expr, 0);
9301 break;
9303 case GFC_ISYM_IBITS:
9304 gfc_conv_intrinsic_ibits (se, expr);
9305 break;
9307 case GFC_ISYM_IBSET:
9308 gfc_conv_intrinsic_singlebitop (se, expr, 1);
9309 break;
9311 case GFC_ISYM_IACHAR:
9312 case GFC_ISYM_ICHAR:
9313 /* We assume ASCII character sequence. */
9314 gfc_conv_intrinsic_ichar (se, expr);
9315 break;
9317 case GFC_ISYM_IARGC:
9318 gfc_conv_intrinsic_iargc (se, expr);
9319 break;
9321 case GFC_ISYM_IEOR:
9322 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9323 break;
9325 case GFC_ISYM_INDEX:
9326 kind = expr->value.function.actual->expr->ts.kind;
9327 if (kind == 1)
9328 fndecl = gfor_fndecl_string_index;
9329 else if (kind == 4)
9330 fndecl = gfor_fndecl_string_index_char4;
9331 else
9332 gcc_unreachable ();
9334 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
9335 break;
9337 case GFC_ISYM_IOR:
9338 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9339 break;
9341 case GFC_ISYM_IPARITY:
9342 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
9343 break;
9345 case GFC_ISYM_IS_IOSTAT_END:
9346 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
9347 break;
9349 case GFC_ISYM_IS_IOSTAT_EOR:
9350 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
9351 break;
9353 case GFC_ISYM_ISNAN:
9354 gfc_conv_intrinsic_isnan (se, expr);
9355 break;
9357 case GFC_ISYM_KILL:
9358 conv_intrinsic_kill (se, expr);
9359 break;
9361 case GFC_ISYM_LSHIFT:
9362 gfc_conv_intrinsic_shift (se, expr, false, false);
9363 break;
9365 case GFC_ISYM_RSHIFT:
9366 gfc_conv_intrinsic_shift (se, expr, true, true);
9367 break;
9369 case GFC_ISYM_SHIFTA:
9370 gfc_conv_intrinsic_shift (se, expr, true, true);
9371 break;
9373 case GFC_ISYM_SHIFTL:
9374 gfc_conv_intrinsic_shift (se, expr, false, false);
9375 break;
9377 case GFC_ISYM_SHIFTR:
9378 gfc_conv_intrinsic_shift (se, expr, true, false);
9379 break;
9381 case GFC_ISYM_ISHFT:
9382 gfc_conv_intrinsic_ishft (se, expr);
9383 break;
9385 case GFC_ISYM_ISHFTC:
9386 gfc_conv_intrinsic_ishftc (se, expr);
9387 break;
9389 case GFC_ISYM_LEADZ:
9390 gfc_conv_intrinsic_leadz (se, expr);
9391 break;
9393 case GFC_ISYM_TRAILZ:
9394 gfc_conv_intrinsic_trailz (se, expr);
9395 break;
9397 case GFC_ISYM_POPCNT:
9398 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
9399 break;
9401 case GFC_ISYM_POPPAR:
9402 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
9403 break;
9405 case GFC_ISYM_LBOUND:
9406 gfc_conv_intrinsic_bound (se, expr, 0);
9407 break;
9409 case GFC_ISYM_LCOBOUND:
9410 conv_intrinsic_cobound (se, expr);
9411 break;
9413 case GFC_ISYM_TRANSPOSE:
9414 /* The scalarizer has already been set up for reversed dimension access
9415 order ; now we just get the argument value normally. */
9416 gfc_conv_expr (se, expr->value.function.actual->expr);
9417 break;
9419 case GFC_ISYM_LEN:
9420 gfc_conv_intrinsic_len (se, expr);
9421 break;
9423 case GFC_ISYM_LEN_TRIM:
9424 gfc_conv_intrinsic_len_trim (se, expr);
9425 break;
9427 case GFC_ISYM_LGE:
9428 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
9429 break;
9431 case GFC_ISYM_LGT:
9432 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
9433 break;
9435 case GFC_ISYM_LLE:
9436 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
9437 break;
9439 case GFC_ISYM_LLT:
9440 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
9441 break;
9443 case GFC_ISYM_MALLOC:
9444 gfc_conv_intrinsic_malloc (se, expr);
9445 break;
9447 case GFC_ISYM_MASKL:
9448 gfc_conv_intrinsic_mask (se, expr, 1);
9449 break;
9451 case GFC_ISYM_MASKR:
9452 gfc_conv_intrinsic_mask (se, expr, 0);
9453 break;
9455 case GFC_ISYM_MAX:
9456 if (expr->ts.type == BT_CHARACTER)
9457 gfc_conv_intrinsic_minmax_char (se, expr, 1);
9458 else
9459 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
9460 break;
9462 case GFC_ISYM_MAXLOC:
9463 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
9464 break;
9466 case GFC_ISYM_MAXVAL:
9467 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
9468 break;
9470 case GFC_ISYM_MERGE:
9471 gfc_conv_intrinsic_merge (se, expr);
9472 break;
9474 case GFC_ISYM_MERGE_BITS:
9475 gfc_conv_intrinsic_merge_bits (se, expr);
9476 break;
9478 case GFC_ISYM_MIN:
9479 if (expr->ts.type == BT_CHARACTER)
9480 gfc_conv_intrinsic_minmax_char (se, expr, -1);
9481 else
9482 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
9483 break;
9485 case GFC_ISYM_MINLOC:
9486 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
9487 break;
9489 case GFC_ISYM_MINVAL:
9490 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
9491 break;
9493 case GFC_ISYM_NEAREST:
9494 gfc_conv_intrinsic_nearest (se, expr);
9495 break;
9497 case GFC_ISYM_NORM2:
9498 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
9499 break;
9501 case GFC_ISYM_NOT:
9502 gfc_conv_intrinsic_not (se, expr);
9503 break;
9505 case GFC_ISYM_OR:
9506 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9507 break;
9509 case GFC_ISYM_PARITY:
9510 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
9511 break;
9513 case GFC_ISYM_PRESENT:
9514 gfc_conv_intrinsic_present (se, expr);
9515 break;
9517 case GFC_ISYM_PRODUCT:
9518 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
9519 break;
9521 case GFC_ISYM_RANK:
9522 gfc_conv_intrinsic_rank (se, expr);
9523 break;
9525 case GFC_ISYM_RRSPACING:
9526 gfc_conv_intrinsic_rrspacing (se, expr);
9527 break;
9529 case GFC_ISYM_SET_EXPONENT:
9530 gfc_conv_intrinsic_set_exponent (se, expr);
9531 break;
9533 case GFC_ISYM_SCALE:
9534 gfc_conv_intrinsic_scale (se, expr);
9535 break;
9537 case GFC_ISYM_SIGN:
9538 gfc_conv_intrinsic_sign (se, expr);
9539 break;
9541 case GFC_ISYM_SIZE:
9542 gfc_conv_intrinsic_size (se, expr);
9543 break;
9545 case GFC_ISYM_SIZEOF:
9546 case GFC_ISYM_C_SIZEOF:
9547 gfc_conv_intrinsic_sizeof (se, expr);
9548 break;
9550 case GFC_ISYM_STORAGE_SIZE:
9551 gfc_conv_intrinsic_storage_size (se, expr);
9552 break;
9554 case GFC_ISYM_SPACING:
9555 gfc_conv_intrinsic_spacing (se, expr);
9556 break;
9558 case GFC_ISYM_STRIDE:
9559 conv_intrinsic_stride (se, expr);
9560 break;
9562 case GFC_ISYM_SUM:
9563 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
9564 break;
9566 case GFC_ISYM_TEAM_NUMBER:
9567 conv_intrinsic_team_number (se, expr);
9568 break;
9570 case GFC_ISYM_TRANSFER:
9571 if (se->ss && se->ss->info->useflags)
9572 /* Access the previously obtained result. */
9573 gfc_conv_tmp_array_ref (se);
9574 else
9575 gfc_conv_intrinsic_transfer (se, expr);
9576 break;
9578 case GFC_ISYM_TTYNAM:
9579 gfc_conv_intrinsic_ttynam (se, expr);
9580 break;
9582 case GFC_ISYM_UBOUND:
9583 gfc_conv_intrinsic_bound (se, expr, 1);
9584 break;
9586 case GFC_ISYM_UCOBOUND:
9587 conv_intrinsic_cobound (se, expr);
9588 break;
9590 case GFC_ISYM_XOR:
9591 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9592 break;
9594 case GFC_ISYM_LOC:
9595 gfc_conv_intrinsic_loc (se, expr);
9596 break;
9598 case GFC_ISYM_THIS_IMAGE:
9599 /* For num_images() == 1, handle as LCOBOUND. */
9600 if (expr->value.function.actual->expr
9601 && flag_coarray == GFC_FCOARRAY_SINGLE)
9602 conv_intrinsic_cobound (se, expr);
9603 else
9604 trans_this_image (se, expr);
9605 break;
9607 case GFC_ISYM_IMAGE_INDEX:
9608 trans_image_index (se, expr);
9609 break;
9611 case GFC_ISYM_IMAGE_STATUS:
9612 conv_intrinsic_image_status (se, expr);
9613 break;
9615 case GFC_ISYM_NUM_IMAGES:
9616 trans_num_images (se, expr);
9617 break;
9619 case GFC_ISYM_ACCESS:
9620 case GFC_ISYM_CHDIR:
9621 case GFC_ISYM_CHMOD:
9622 case GFC_ISYM_DTIME:
9623 case GFC_ISYM_ETIME:
9624 case GFC_ISYM_EXTENDS_TYPE_OF:
9625 case GFC_ISYM_FGET:
9626 case GFC_ISYM_FGETC:
9627 case GFC_ISYM_FNUM:
9628 case GFC_ISYM_FPUT:
9629 case GFC_ISYM_FPUTC:
9630 case GFC_ISYM_FSTAT:
9631 case GFC_ISYM_FTELL:
9632 case GFC_ISYM_GETCWD:
9633 case GFC_ISYM_GETGID:
9634 case GFC_ISYM_GETPID:
9635 case GFC_ISYM_GETUID:
9636 case GFC_ISYM_HOSTNM:
9637 case GFC_ISYM_IERRNO:
9638 case GFC_ISYM_IRAND:
9639 case GFC_ISYM_ISATTY:
9640 case GFC_ISYM_JN2:
9641 case GFC_ISYM_LINK:
9642 case GFC_ISYM_LSTAT:
9643 case GFC_ISYM_MATMUL:
9644 case GFC_ISYM_MCLOCK:
9645 case GFC_ISYM_MCLOCK8:
9646 case GFC_ISYM_RAND:
9647 case GFC_ISYM_RENAME:
9648 case GFC_ISYM_SECOND:
9649 case GFC_ISYM_SECNDS:
9650 case GFC_ISYM_SIGNAL:
9651 case GFC_ISYM_STAT:
9652 case GFC_ISYM_SYMLNK:
9653 case GFC_ISYM_SYSTEM:
9654 case GFC_ISYM_TIME:
9655 case GFC_ISYM_TIME8:
9656 case GFC_ISYM_UMASK:
9657 case GFC_ISYM_UNLINK:
9658 case GFC_ISYM_YN2:
9659 gfc_conv_intrinsic_funcall (se, expr);
9660 break;
9662 case GFC_ISYM_EOSHIFT:
9663 case GFC_ISYM_PACK:
9664 case GFC_ISYM_RESHAPE:
9665 /* For those, expr->rank should always be >0 and thus the if above the
9666 switch should have matched. */
9667 gcc_unreachable ();
9668 break;
9670 default:
9671 gfc_conv_intrinsic_lib_function (se, expr);
9672 break;
9677 static gfc_ss *
9678 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
9680 gfc_ss *arg_ss, *tmp_ss;
9681 gfc_actual_arglist *arg;
9683 arg = expr->value.function.actual;
9685 gcc_assert (arg->expr);
9687 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
9688 gcc_assert (arg_ss != gfc_ss_terminator);
9690 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
9692 if (tmp_ss->info->type != GFC_SS_SCALAR
9693 && tmp_ss->info->type != GFC_SS_REFERENCE)
9695 gcc_assert (tmp_ss->dimen == 2);
9697 /* We just invert dimensions. */
9698 std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
9701 /* Stop when tmp_ss points to the last valid element of the chain... */
9702 if (tmp_ss->next == gfc_ss_terminator)
9703 break;
9706 /* ... so that we can attach the rest of the chain to it. */
9707 tmp_ss->next = ss;
9709 return arg_ss;
9713 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
9714 This has the side effect of reversing the nested list, so there is no
9715 need to call gfc_reverse_ss on it (the given list is assumed not to be
9716 reversed yet). */
9718 static gfc_ss *
9719 nest_loop_dimension (gfc_ss *ss, int dim)
9721 int ss_dim, i;
9722 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
9723 gfc_loopinfo *new_loop;
9725 gcc_assert (ss != gfc_ss_terminator);
9727 for (; ss != gfc_ss_terminator; ss = ss->next)
9729 new_ss = gfc_get_ss ();
9730 new_ss->next = prev_ss;
9731 new_ss->parent = ss;
9732 new_ss->info = ss->info;
9733 new_ss->info->refcount++;
9734 if (ss->dimen != 0)
9736 gcc_assert (ss->info->type != GFC_SS_SCALAR
9737 && ss->info->type != GFC_SS_REFERENCE);
9739 new_ss->dimen = 1;
9740 new_ss->dim[0] = ss->dim[dim];
9742 gcc_assert (dim < ss->dimen);
9744 ss_dim = --ss->dimen;
9745 for (i = dim; i < ss_dim; i++)
9746 ss->dim[i] = ss->dim[i + 1];
9748 ss->dim[ss_dim] = 0;
9750 prev_ss = new_ss;
9752 if (ss->nested_ss)
9754 ss->nested_ss->parent = new_ss;
9755 new_ss->nested_ss = ss->nested_ss;
9757 ss->nested_ss = new_ss;
9760 new_loop = gfc_get_loopinfo ();
9761 gfc_init_loopinfo (new_loop);
9763 gcc_assert (prev_ss != NULL);
9764 gcc_assert (prev_ss != gfc_ss_terminator);
9765 gfc_add_ss_to_loop (new_loop, prev_ss);
9766 return new_ss->parent;
9770 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
9771 is to be inlined. */
9773 static gfc_ss *
9774 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
9776 gfc_ss *tmp_ss, *tail, *array_ss;
9777 gfc_actual_arglist *arg1, *arg2, *arg3;
9778 int sum_dim;
9779 bool scalar_mask = false;
9781 /* The rank of the result will be determined later. */
9782 arg1 = expr->value.function.actual;
9783 arg2 = arg1->next;
9784 arg3 = arg2->next;
9785 gcc_assert (arg3 != NULL);
9787 if (expr->rank == 0)
9788 return ss;
9790 tmp_ss = gfc_ss_terminator;
9792 if (arg3->expr)
9794 gfc_ss *mask_ss;
9796 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
9797 if (mask_ss == tmp_ss)
9798 scalar_mask = 1;
9800 tmp_ss = mask_ss;
9803 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
9804 gcc_assert (array_ss != tmp_ss);
9806 /* Odd thing: If the mask is scalar, it is used by the frontend after
9807 the array (to make an if around the nested loop). Thus it shall
9808 be after array_ss once the gfc_ss list is reversed. */
9809 if (scalar_mask)
9810 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
9811 else
9812 tmp_ss = array_ss;
9814 /* "Hide" the dimension on which we will sum in the first arg's scalarization
9815 chain. */
9816 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
9817 tail = nest_loop_dimension (tmp_ss, sum_dim);
9818 tail->next = ss;
9820 return tmp_ss;
9824 static gfc_ss *
9825 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
9828 switch (expr->value.function.isym->id)
9830 case GFC_ISYM_PRODUCT:
9831 case GFC_ISYM_SUM:
9832 return walk_inline_intrinsic_arith (ss, expr);
9834 case GFC_ISYM_TRANSPOSE:
9835 return walk_inline_intrinsic_transpose (ss, expr);
9837 default:
9838 gcc_unreachable ();
9840 gcc_unreachable ();
9844 /* This generates code to execute before entering the scalarization loop.
9845 Currently does nothing. */
9847 void
9848 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
9850 switch (ss->info->expr->value.function.isym->id)
9852 case GFC_ISYM_UBOUND:
9853 case GFC_ISYM_LBOUND:
9854 case GFC_ISYM_UCOBOUND:
9855 case GFC_ISYM_LCOBOUND:
9856 case GFC_ISYM_THIS_IMAGE:
9857 break;
9859 default:
9860 gcc_unreachable ();
9865 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
9866 are expanded into code inside the scalarization loop. */
9868 static gfc_ss *
9869 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
9871 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
9872 gfc_add_class_array_ref (expr->value.function.actual->expr);
9874 /* The two argument version returns a scalar. */
9875 if (expr->value.function.actual->next->expr)
9876 return ss;
9878 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
9882 /* Walk an intrinsic array libcall. */
9884 static gfc_ss *
9885 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
9887 gcc_assert (expr->rank > 0);
9888 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
9892 /* Return whether the function call expression EXPR will be expanded
9893 inline by gfc_conv_intrinsic_function. */
9895 bool
9896 gfc_inline_intrinsic_function_p (gfc_expr *expr)
9898 gfc_actual_arglist *args;
9900 if (!expr->value.function.isym)
9901 return false;
9903 switch (expr->value.function.isym->id)
9905 case GFC_ISYM_PRODUCT:
9906 case GFC_ISYM_SUM:
9907 /* Disable inline expansion if code size matters. */
9908 if (optimize_size)
9909 return false;
9911 args = expr->value.function.actual;
9912 /* We need to be able to subset the SUM argument at compile-time. */
9913 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
9914 return false;
9916 return true;
9918 case GFC_ISYM_TRANSPOSE:
9919 return true;
9921 default:
9922 return false;
9927 /* Returns nonzero if the specified intrinsic function call maps directly to
9928 an external library call. Should only be used for functions that return
9929 arrays. */
9932 gfc_is_intrinsic_libcall (gfc_expr * expr)
9934 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
9935 gcc_assert (expr->rank > 0);
9937 if (gfc_inline_intrinsic_function_p (expr))
9938 return 0;
9940 switch (expr->value.function.isym->id)
9942 case GFC_ISYM_ALL:
9943 case GFC_ISYM_ANY:
9944 case GFC_ISYM_COUNT:
9945 case GFC_ISYM_JN2:
9946 case GFC_ISYM_IANY:
9947 case GFC_ISYM_IALL:
9948 case GFC_ISYM_IPARITY:
9949 case GFC_ISYM_MATMUL:
9950 case GFC_ISYM_MAXLOC:
9951 case GFC_ISYM_MAXVAL:
9952 case GFC_ISYM_MINLOC:
9953 case GFC_ISYM_MINVAL:
9954 case GFC_ISYM_NORM2:
9955 case GFC_ISYM_PARITY:
9956 case GFC_ISYM_PRODUCT:
9957 case GFC_ISYM_SUM:
9958 case GFC_ISYM_SHAPE:
9959 case GFC_ISYM_SPREAD:
9960 case GFC_ISYM_YN2:
9961 /* Ignore absent optional parameters. */
9962 return 1;
9964 case GFC_ISYM_CSHIFT:
9965 case GFC_ISYM_EOSHIFT:
9966 case GFC_ISYM_GET_TEAM:
9967 case GFC_ISYM_FAILED_IMAGES:
9968 case GFC_ISYM_STOPPED_IMAGES:
9969 case GFC_ISYM_PACK:
9970 case GFC_ISYM_RESHAPE:
9971 case GFC_ISYM_UNPACK:
9972 /* Pass absent optional parameters. */
9973 return 2;
9975 default:
9976 return 0;
9980 /* Walk an intrinsic function. */
9981 gfc_ss *
9982 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
9983 gfc_intrinsic_sym * isym)
9985 gcc_assert (isym);
9987 if (isym->elemental)
9988 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
9989 NULL, GFC_SS_SCALAR);
9991 if (expr->rank == 0)
9992 return ss;
9994 if (gfc_inline_intrinsic_function_p (expr))
9995 return walk_inline_intrinsic_function (ss, expr);
9997 if (gfc_is_intrinsic_libcall (expr))
9998 return gfc_walk_intrinsic_libfunc (ss, expr);
10000 /* Special cases. */
10001 switch (isym->id)
10003 case GFC_ISYM_LBOUND:
10004 case GFC_ISYM_LCOBOUND:
10005 case GFC_ISYM_UBOUND:
10006 case GFC_ISYM_UCOBOUND:
10007 case GFC_ISYM_THIS_IMAGE:
10008 return gfc_walk_intrinsic_bound (ss, expr);
10010 case GFC_ISYM_TRANSFER:
10011 case GFC_ISYM_CAF_GET:
10012 return gfc_walk_intrinsic_libfunc (ss, expr);
10014 default:
10015 /* This probably meant someone forgot to add an intrinsic to the above
10016 list(s) when they implemented it, or something's gone horribly
10017 wrong. */
10018 gcc_unreachable ();
10023 static tree
10024 conv_co_collective (gfc_code *code)
10026 gfc_se argse;
10027 stmtblock_t block, post_block;
10028 tree fndecl, array, strlen, image_index, stat, errmsg, errmsg_len;
10029 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
10031 gfc_start_block (&block);
10032 gfc_init_block (&post_block);
10034 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
10036 opr_expr = code->ext.actual->next->expr;
10037 image_idx_expr = code->ext.actual->next->next->expr;
10038 stat_expr = code->ext.actual->next->next->next->expr;
10039 errmsg_expr = code->ext.actual->next->next->next->next->expr;
10041 else
10043 opr_expr = NULL;
10044 image_idx_expr = code->ext.actual->next->expr;
10045 stat_expr = code->ext.actual->next->next->expr;
10046 errmsg_expr = code->ext.actual->next->next->next->expr;
10049 /* stat. */
10050 if (stat_expr)
10052 gfc_init_se (&argse, NULL);
10053 gfc_conv_expr (&argse, stat_expr);
10054 gfc_add_block_to_block (&block, &argse.pre);
10055 gfc_add_block_to_block (&post_block, &argse.post);
10056 stat = argse.expr;
10057 if (flag_coarray != GFC_FCOARRAY_SINGLE)
10058 stat = gfc_build_addr_expr (NULL_TREE, stat);
10060 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
10061 stat = NULL_TREE;
10062 else
10063 stat = null_pointer_node;
10065 /* Early exit for GFC_FCOARRAY_SINGLE. */
10066 if (flag_coarray == GFC_FCOARRAY_SINGLE)
10068 if (stat != NULL_TREE)
10069 gfc_add_modify (&block, stat,
10070 fold_convert (TREE_TYPE (stat), integer_zero_node));
10071 return gfc_finish_block (&block);
10074 /* Handle the array. */
10075 gfc_init_se (&argse, NULL);
10076 if (code->ext.actual->expr->rank == 0)
10078 symbol_attribute attr;
10079 gfc_clear_attr (&attr);
10080 gfc_init_se (&argse, NULL);
10081 gfc_conv_expr (&argse, code->ext.actual->expr);
10082 gfc_add_block_to_block (&block, &argse.pre);
10083 gfc_add_block_to_block (&post_block, &argse.post);
10084 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
10085 array = gfc_build_addr_expr (NULL_TREE, array);
10087 else
10089 argse.want_pointer = 1;
10090 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
10091 array = argse.expr;
10093 gfc_add_block_to_block (&block, &argse.pre);
10094 gfc_add_block_to_block (&post_block, &argse.post);
10096 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
10097 strlen = argse.string_length;
10098 else
10099 strlen = integer_zero_node;
10101 /* image_index. */
10102 if (image_idx_expr)
10104 gfc_init_se (&argse, NULL);
10105 gfc_conv_expr (&argse, image_idx_expr);
10106 gfc_add_block_to_block (&block, &argse.pre);
10107 gfc_add_block_to_block (&post_block, &argse.post);
10108 image_index = fold_convert (integer_type_node, argse.expr);
10110 else
10111 image_index = integer_zero_node;
10113 /* errmsg. */
10114 if (errmsg_expr)
10116 gfc_init_se (&argse, NULL);
10117 gfc_conv_expr (&argse, errmsg_expr);
10118 gfc_add_block_to_block (&block, &argse.pre);
10119 gfc_add_block_to_block (&post_block, &argse.post);
10120 errmsg = argse.expr;
10121 errmsg_len = fold_convert (size_type_node, argse.string_length);
10123 else
10125 errmsg = null_pointer_node;
10126 errmsg_len = build_zero_cst (size_type_node);
10129 /* Generate the function call. */
10130 switch (code->resolved_isym->id)
10132 case GFC_ISYM_CO_BROADCAST:
10133 fndecl = gfor_fndecl_co_broadcast;
10134 break;
10135 case GFC_ISYM_CO_MAX:
10136 fndecl = gfor_fndecl_co_max;
10137 break;
10138 case GFC_ISYM_CO_MIN:
10139 fndecl = gfor_fndecl_co_min;
10140 break;
10141 case GFC_ISYM_CO_REDUCE:
10142 fndecl = gfor_fndecl_co_reduce;
10143 break;
10144 case GFC_ISYM_CO_SUM:
10145 fndecl = gfor_fndecl_co_sum;
10146 break;
10147 default:
10148 gcc_unreachable ();
10151 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
10152 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
10153 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
10154 image_index, stat, errmsg, errmsg_len);
10155 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
10156 fndecl = build_call_expr_loc (input_location, fndecl, 6, array, image_index,
10157 stat, errmsg, strlen, errmsg_len);
10158 else
10160 tree opr, opr_flags;
10162 // FIXME: Handle TS29113's bind(C) strings with descriptor.
10163 int opr_flag_int;
10164 if (gfc_is_proc_ptr_comp (opr_expr))
10166 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
10167 opr_flag_int = sym->attr.dimension
10168 || (sym->ts.type == BT_CHARACTER
10169 && !sym->attr.is_bind_c)
10170 ? GFC_CAF_BYREF : 0;
10171 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
10172 && !sym->attr.is_bind_c
10173 ? GFC_CAF_HIDDENLEN : 0;
10174 opr_flag_int |= sym->formal->sym->attr.value ? GFC_CAF_ARG_VALUE : 0;
10176 else
10178 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
10179 ? GFC_CAF_BYREF : 0;
10180 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
10181 && !opr_expr->symtree->n.sym->attr.is_bind_c
10182 ? GFC_CAF_HIDDENLEN : 0;
10183 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
10184 ? GFC_CAF_ARG_VALUE : 0;
10186 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
10187 gfc_conv_expr (&argse, opr_expr);
10188 opr = argse.expr;
10189 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr, opr_flags,
10190 image_index, stat, errmsg, strlen, errmsg_len);
10193 gfc_add_expr_to_block (&block, fndecl);
10194 gfc_add_block_to_block (&block, &post_block);
10196 return gfc_finish_block (&block);
10200 static tree
10201 conv_intrinsic_atomic_op (gfc_code *code)
10203 gfc_se argse;
10204 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
10205 stmtblock_t block, post_block;
10206 gfc_expr *atom_expr = code->ext.actual->expr;
10207 gfc_expr *stat_expr;
10208 built_in_function fn;
10210 if (atom_expr->expr_type == EXPR_FUNCTION
10211 && atom_expr->value.function.isym
10212 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10213 atom_expr = atom_expr->value.function.actual->expr;
10215 gfc_start_block (&block);
10216 gfc_init_block (&post_block);
10218 gfc_init_se (&argse, NULL);
10219 argse.want_pointer = 1;
10220 gfc_conv_expr (&argse, atom_expr);
10221 gfc_add_block_to_block (&block, &argse.pre);
10222 gfc_add_block_to_block (&post_block, &argse.post);
10223 atom = argse.expr;
10225 gfc_init_se (&argse, NULL);
10226 if (flag_coarray == GFC_FCOARRAY_LIB
10227 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
10228 argse.want_pointer = 1;
10229 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10230 gfc_add_block_to_block (&block, &argse.pre);
10231 gfc_add_block_to_block (&post_block, &argse.post);
10232 value = argse.expr;
10234 switch (code->resolved_isym->id)
10236 case GFC_ISYM_ATOMIC_ADD:
10237 case GFC_ISYM_ATOMIC_AND:
10238 case GFC_ISYM_ATOMIC_DEF:
10239 case GFC_ISYM_ATOMIC_OR:
10240 case GFC_ISYM_ATOMIC_XOR:
10241 stat_expr = code->ext.actual->next->next->expr;
10242 if (flag_coarray == GFC_FCOARRAY_LIB)
10243 old = null_pointer_node;
10244 break;
10245 default:
10246 gfc_init_se (&argse, NULL);
10247 if (flag_coarray == GFC_FCOARRAY_LIB)
10248 argse.want_pointer = 1;
10249 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10250 gfc_add_block_to_block (&block, &argse.pre);
10251 gfc_add_block_to_block (&post_block, &argse.post);
10252 old = argse.expr;
10253 stat_expr = code->ext.actual->next->next->next->expr;
10256 /* STAT= */
10257 if (stat_expr != NULL)
10259 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
10260 gfc_init_se (&argse, NULL);
10261 if (flag_coarray == GFC_FCOARRAY_LIB)
10262 argse.want_pointer = 1;
10263 gfc_conv_expr_val (&argse, stat_expr);
10264 gfc_add_block_to_block (&block, &argse.pre);
10265 gfc_add_block_to_block (&post_block, &argse.post);
10266 stat = argse.expr;
10268 else if (flag_coarray == GFC_FCOARRAY_LIB)
10269 stat = null_pointer_node;
10271 if (flag_coarray == GFC_FCOARRAY_LIB)
10273 tree image_index, caf_decl, offset, token;
10274 int op;
10276 switch (code->resolved_isym->id)
10278 case GFC_ISYM_ATOMIC_ADD:
10279 case GFC_ISYM_ATOMIC_FETCH_ADD:
10280 op = (int) GFC_CAF_ATOMIC_ADD;
10281 break;
10282 case GFC_ISYM_ATOMIC_AND:
10283 case GFC_ISYM_ATOMIC_FETCH_AND:
10284 op = (int) GFC_CAF_ATOMIC_AND;
10285 break;
10286 case GFC_ISYM_ATOMIC_OR:
10287 case GFC_ISYM_ATOMIC_FETCH_OR:
10288 op = (int) GFC_CAF_ATOMIC_OR;
10289 break;
10290 case GFC_ISYM_ATOMIC_XOR:
10291 case GFC_ISYM_ATOMIC_FETCH_XOR:
10292 op = (int) GFC_CAF_ATOMIC_XOR;
10293 break;
10294 case GFC_ISYM_ATOMIC_DEF:
10295 op = 0; /* Unused. */
10296 break;
10297 default:
10298 gcc_unreachable ();
10301 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10302 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10303 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10305 if (gfc_is_coindexed (atom_expr))
10306 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10307 else
10308 image_index = integer_zero_node;
10310 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10312 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10313 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
10314 value = gfc_build_addr_expr (NULL_TREE, tmp);
10317 gfc_init_se (&argse, NULL);
10318 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10319 atom_expr);
10321 gfc_add_block_to_block (&block, &argse.pre);
10322 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
10323 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
10324 token, offset, image_index, value, stat,
10325 build_int_cst (integer_type_node,
10326 (int) atom_expr->ts.type),
10327 build_int_cst (integer_type_node,
10328 (int) atom_expr->ts.kind));
10329 else
10330 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
10331 build_int_cst (integer_type_node, op),
10332 token, offset, image_index, value, old, stat,
10333 build_int_cst (integer_type_node,
10334 (int) atom_expr->ts.type),
10335 build_int_cst (integer_type_node,
10336 (int) atom_expr->ts.kind));
10338 gfc_add_expr_to_block (&block, tmp);
10339 gfc_add_block_to_block (&block, &argse.post);
10340 gfc_add_block_to_block (&block, &post_block);
10341 return gfc_finish_block (&block);
10345 switch (code->resolved_isym->id)
10347 case GFC_ISYM_ATOMIC_ADD:
10348 case GFC_ISYM_ATOMIC_FETCH_ADD:
10349 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
10350 break;
10351 case GFC_ISYM_ATOMIC_AND:
10352 case GFC_ISYM_ATOMIC_FETCH_AND:
10353 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
10354 break;
10355 case GFC_ISYM_ATOMIC_DEF:
10356 fn = BUILT_IN_ATOMIC_STORE_N;
10357 break;
10358 case GFC_ISYM_ATOMIC_OR:
10359 case GFC_ISYM_ATOMIC_FETCH_OR:
10360 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
10361 break;
10362 case GFC_ISYM_ATOMIC_XOR:
10363 case GFC_ISYM_ATOMIC_FETCH_XOR:
10364 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
10365 break;
10366 default:
10367 gcc_unreachable ();
10370 tmp = TREE_TYPE (TREE_TYPE (atom));
10371 fn = (built_in_function) ((int) fn
10372 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10373 + 1);
10374 tmp = builtin_decl_explicit (fn);
10375 tree itype = TREE_TYPE (TREE_TYPE (atom));
10376 tmp = builtin_decl_explicit (fn);
10378 switch (code->resolved_isym->id)
10380 case GFC_ISYM_ATOMIC_ADD:
10381 case GFC_ISYM_ATOMIC_AND:
10382 case GFC_ISYM_ATOMIC_DEF:
10383 case GFC_ISYM_ATOMIC_OR:
10384 case GFC_ISYM_ATOMIC_XOR:
10385 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
10386 fold_convert (itype, value),
10387 build_int_cst (NULL, MEMMODEL_RELAXED));
10388 gfc_add_expr_to_block (&block, tmp);
10389 break;
10390 default:
10391 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
10392 fold_convert (itype, value),
10393 build_int_cst (NULL, MEMMODEL_RELAXED));
10394 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
10395 break;
10398 if (stat != NULL_TREE)
10399 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10400 gfc_add_block_to_block (&block, &post_block);
10401 return gfc_finish_block (&block);
10405 static tree
10406 conv_intrinsic_atomic_ref (gfc_code *code)
10408 gfc_se argse;
10409 tree tmp, atom, value, stat = NULL_TREE;
10410 stmtblock_t block, post_block;
10411 built_in_function fn;
10412 gfc_expr *atom_expr = code->ext.actual->next->expr;
10414 if (atom_expr->expr_type == EXPR_FUNCTION
10415 && atom_expr->value.function.isym
10416 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10417 atom_expr = atom_expr->value.function.actual->expr;
10419 gfc_start_block (&block);
10420 gfc_init_block (&post_block);
10421 gfc_init_se (&argse, NULL);
10422 argse.want_pointer = 1;
10423 gfc_conv_expr (&argse, atom_expr);
10424 gfc_add_block_to_block (&block, &argse.pre);
10425 gfc_add_block_to_block (&post_block, &argse.post);
10426 atom = argse.expr;
10428 gfc_init_se (&argse, NULL);
10429 if (flag_coarray == GFC_FCOARRAY_LIB
10430 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
10431 argse.want_pointer = 1;
10432 gfc_conv_expr (&argse, code->ext.actual->expr);
10433 gfc_add_block_to_block (&block, &argse.pre);
10434 gfc_add_block_to_block (&post_block, &argse.post);
10435 value = argse.expr;
10437 /* STAT= */
10438 if (code->ext.actual->next->next->expr != NULL)
10440 gcc_assert (code->ext.actual->next->next->expr->expr_type
10441 == EXPR_VARIABLE);
10442 gfc_init_se (&argse, NULL);
10443 if (flag_coarray == GFC_FCOARRAY_LIB)
10444 argse.want_pointer = 1;
10445 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10446 gfc_add_block_to_block (&block, &argse.pre);
10447 gfc_add_block_to_block (&post_block, &argse.post);
10448 stat = argse.expr;
10450 else if (flag_coarray == GFC_FCOARRAY_LIB)
10451 stat = null_pointer_node;
10453 if (flag_coarray == GFC_FCOARRAY_LIB)
10455 tree image_index, caf_decl, offset, token;
10456 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
10458 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10459 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10460 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10462 if (gfc_is_coindexed (atom_expr))
10463 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10464 else
10465 image_index = integer_zero_node;
10467 gfc_init_se (&argse, NULL);
10468 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10469 atom_expr);
10470 gfc_add_block_to_block (&block, &argse.pre);
10472 /* Different type, need type conversion. */
10473 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10475 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10476 orig_value = value;
10477 value = gfc_build_addr_expr (NULL_TREE, vardecl);
10480 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
10481 token, offset, image_index, value, stat,
10482 build_int_cst (integer_type_node,
10483 (int) atom_expr->ts.type),
10484 build_int_cst (integer_type_node,
10485 (int) atom_expr->ts.kind));
10486 gfc_add_expr_to_block (&block, tmp);
10487 if (vardecl != NULL_TREE)
10488 gfc_add_modify (&block, orig_value,
10489 fold_convert (TREE_TYPE (orig_value), vardecl));
10490 gfc_add_block_to_block (&block, &argse.post);
10491 gfc_add_block_to_block (&block, &post_block);
10492 return gfc_finish_block (&block);
10495 tmp = TREE_TYPE (TREE_TYPE (atom));
10496 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
10497 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10498 + 1);
10499 tmp = builtin_decl_explicit (fn);
10500 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
10501 build_int_cst (integer_type_node,
10502 MEMMODEL_RELAXED));
10503 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
10505 if (stat != NULL_TREE)
10506 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10507 gfc_add_block_to_block (&block, &post_block);
10508 return gfc_finish_block (&block);
10512 static tree
10513 conv_intrinsic_atomic_cas (gfc_code *code)
10515 gfc_se argse;
10516 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
10517 stmtblock_t block, post_block;
10518 built_in_function fn;
10519 gfc_expr *atom_expr = code->ext.actual->expr;
10521 if (atom_expr->expr_type == EXPR_FUNCTION
10522 && atom_expr->value.function.isym
10523 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10524 atom_expr = atom_expr->value.function.actual->expr;
10526 gfc_init_block (&block);
10527 gfc_init_block (&post_block);
10528 gfc_init_se (&argse, NULL);
10529 argse.want_pointer = 1;
10530 gfc_conv_expr (&argse, atom_expr);
10531 atom = argse.expr;
10533 gfc_init_se (&argse, NULL);
10534 if (flag_coarray == GFC_FCOARRAY_LIB)
10535 argse.want_pointer = 1;
10536 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10537 gfc_add_block_to_block (&block, &argse.pre);
10538 gfc_add_block_to_block (&post_block, &argse.post);
10539 old = argse.expr;
10541 gfc_init_se (&argse, NULL);
10542 if (flag_coarray == GFC_FCOARRAY_LIB)
10543 argse.want_pointer = 1;
10544 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10545 gfc_add_block_to_block (&block, &argse.pre);
10546 gfc_add_block_to_block (&post_block, &argse.post);
10547 comp = argse.expr;
10549 gfc_init_se (&argse, NULL);
10550 if (flag_coarray == GFC_FCOARRAY_LIB
10551 && code->ext.actual->next->next->next->expr->ts.kind
10552 == atom_expr->ts.kind)
10553 argse.want_pointer = 1;
10554 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
10555 gfc_add_block_to_block (&block, &argse.pre);
10556 gfc_add_block_to_block (&post_block, &argse.post);
10557 new_val = argse.expr;
10559 /* STAT= */
10560 if (code->ext.actual->next->next->next->next->expr != NULL)
10562 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
10563 == EXPR_VARIABLE);
10564 gfc_init_se (&argse, NULL);
10565 if (flag_coarray == GFC_FCOARRAY_LIB)
10566 argse.want_pointer = 1;
10567 gfc_conv_expr_val (&argse,
10568 code->ext.actual->next->next->next->next->expr);
10569 gfc_add_block_to_block (&block, &argse.pre);
10570 gfc_add_block_to_block (&post_block, &argse.post);
10571 stat = argse.expr;
10573 else if (flag_coarray == GFC_FCOARRAY_LIB)
10574 stat = null_pointer_node;
10576 if (flag_coarray == GFC_FCOARRAY_LIB)
10578 tree image_index, caf_decl, offset, token;
10580 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10581 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10582 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10584 if (gfc_is_coindexed (atom_expr))
10585 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10586 else
10587 image_index = integer_zero_node;
10589 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
10591 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
10592 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
10593 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
10596 /* Convert a constant to a pointer. */
10597 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
10599 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
10600 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
10601 comp = gfc_build_addr_expr (NULL_TREE, tmp);
10604 gfc_init_se (&argse, NULL);
10605 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10606 atom_expr);
10607 gfc_add_block_to_block (&block, &argse.pre);
10609 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
10610 token, offset, image_index, old, comp, new_val,
10611 stat, build_int_cst (integer_type_node,
10612 (int) atom_expr->ts.type),
10613 build_int_cst (integer_type_node,
10614 (int) atom_expr->ts.kind));
10615 gfc_add_expr_to_block (&block, tmp);
10616 gfc_add_block_to_block (&block, &argse.post);
10617 gfc_add_block_to_block (&block, &post_block);
10618 return gfc_finish_block (&block);
10621 tmp = TREE_TYPE (TREE_TYPE (atom));
10622 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
10623 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10624 + 1);
10625 tmp = builtin_decl_explicit (fn);
10627 gfc_add_modify (&block, old, comp);
10628 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
10629 gfc_build_addr_expr (NULL, old),
10630 fold_convert (TREE_TYPE (old), new_val),
10631 boolean_false_node,
10632 build_int_cst (NULL, MEMMODEL_RELAXED),
10633 build_int_cst (NULL, MEMMODEL_RELAXED));
10634 gfc_add_expr_to_block (&block, tmp);
10636 if (stat != NULL_TREE)
10637 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10638 gfc_add_block_to_block (&block, &post_block);
10639 return gfc_finish_block (&block);
10642 static tree
10643 conv_intrinsic_event_query (gfc_code *code)
10645 gfc_se se, argse;
10646 tree stat = NULL_TREE, stat2 = NULL_TREE;
10647 tree count = NULL_TREE, count2 = NULL_TREE;
10649 gfc_expr *event_expr = code->ext.actual->expr;
10651 if (code->ext.actual->next->next->expr)
10653 gcc_assert (code->ext.actual->next->next->expr->expr_type
10654 == EXPR_VARIABLE);
10655 gfc_init_se (&argse, NULL);
10656 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10657 stat = argse.expr;
10659 else if (flag_coarray == GFC_FCOARRAY_LIB)
10660 stat = null_pointer_node;
10662 if (code->ext.actual->next->expr)
10664 gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
10665 gfc_init_se (&argse, NULL);
10666 gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
10667 count = argse.expr;
10670 gfc_start_block (&se.pre);
10671 if (flag_coarray == GFC_FCOARRAY_LIB)
10673 tree tmp, token, image_index;
10674 tree index = size_zero_node;
10676 if (event_expr->expr_type == EXPR_FUNCTION
10677 && event_expr->value.function.isym
10678 && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10679 event_expr = event_expr->value.function.actual->expr;
10681 tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
10683 if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
10684 || event_expr->symtree->n.sym->ts.u.derived->from_intmod
10685 != INTMOD_ISO_FORTRAN_ENV
10686 || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
10687 != ISOFORTRAN_EVENT_TYPE)
10689 gfc_error ("Sorry, the event component of derived type at %L is not "
10690 "yet supported", &event_expr->where);
10691 return NULL_TREE;
10694 if (gfc_is_coindexed (event_expr))
10696 gfc_error ("The event variable at %L shall not be coindexed",
10697 &event_expr->where);
10698 return NULL_TREE;
10701 image_index = integer_zero_node;
10703 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
10704 event_expr);
10706 /* For arrays, obtain the array index. */
10707 if (gfc_expr_attr (event_expr).dimension)
10709 tree desc, tmp, extent, lbound, ubound;
10710 gfc_array_ref *ar, ar2;
10711 int i;
10713 /* TODO: Extend this, once DT components are supported. */
10714 ar = &event_expr->ref->u.ar;
10715 ar2 = *ar;
10716 memset (ar, '\0', sizeof (*ar));
10717 ar->as = ar2.as;
10718 ar->type = AR_FULL;
10720 gfc_init_se (&argse, NULL);
10721 argse.descriptor_only = 1;
10722 gfc_conv_expr_descriptor (&argse, event_expr);
10723 gfc_add_block_to_block (&se.pre, &argse.pre);
10724 desc = argse.expr;
10725 *ar = ar2;
10727 extent = integer_one_node;
10728 for (i = 0; i < ar->dimen; i++)
10730 gfc_init_se (&argse, NULL);
10731 gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
10732 gfc_add_block_to_block (&argse.pre, &argse.pre);
10733 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
10734 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10735 integer_type_node, argse.expr,
10736 fold_convert(integer_type_node, lbound));
10737 tmp = fold_build2_loc (input_location, MULT_EXPR,
10738 integer_type_node, extent, tmp);
10739 index = fold_build2_loc (input_location, PLUS_EXPR,
10740 integer_type_node, index, tmp);
10741 if (i < ar->dimen - 1)
10743 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
10744 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
10745 tmp = fold_convert (integer_type_node, tmp);
10746 extent = fold_build2_loc (input_location, MULT_EXPR,
10747 integer_type_node, extent, tmp);
10752 if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
10754 count2 = count;
10755 count = gfc_create_var (integer_type_node, "count");
10758 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
10760 stat2 = stat;
10761 stat = gfc_create_var (integer_type_node, "stat");
10764 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
10765 token, index, image_index, count
10766 ? gfc_build_addr_expr (NULL, count) : count,
10767 stat != null_pointer_node
10768 ? gfc_build_addr_expr (NULL, stat) : stat);
10769 gfc_add_expr_to_block (&se.pre, tmp);
10771 if (count2 != NULL_TREE)
10772 gfc_add_modify (&se.pre, count2,
10773 fold_convert (TREE_TYPE (count2), count));
10775 if (stat2 != NULL_TREE)
10776 gfc_add_modify (&se.pre, stat2,
10777 fold_convert (TREE_TYPE (stat2), stat));
10779 return gfc_finish_block (&se.pre);
10782 gfc_init_se (&argse, NULL);
10783 gfc_conv_expr_val (&argse, code->ext.actual->expr);
10784 gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
10786 if (stat != NULL_TREE)
10787 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
10789 return gfc_finish_block (&se.pre);
10792 static tree
10793 conv_intrinsic_move_alloc (gfc_code *code)
10795 stmtblock_t block;
10796 gfc_expr *from_expr, *to_expr;
10797 gfc_expr *to_expr2, *from_expr2 = NULL;
10798 gfc_se from_se, to_se;
10799 tree tmp;
10800 bool coarray;
10802 gfc_start_block (&block);
10804 from_expr = code->ext.actual->expr;
10805 to_expr = code->ext.actual->next->expr;
10807 gfc_init_se (&from_se, NULL);
10808 gfc_init_se (&to_se, NULL);
10810 gcc_assert (from_expr->ts.type != BT_CLASS
10811 || to_expr->ts.type == BT_CLASS);
10812 coarray = gfc_get_corank (from_expr) != 0;
10814 if (from_expr->rank == 0 && !coarray)
10816 if (from_expr->ts.type != BT_CLASS)
10817 from_expr2 = from_expr;
10818 else
10820 from_expr2 = gfc_copy_expr (from_expr);
10821 gfc_add_data_component (from_expr2);
10824 if (to_expr->ts.type != BT_CLASS)
10825 to_expr2 = to_expr;
10826 else
10828 to_expr2 = gfc_copy_expr (to_expr);
10829 gfc_add_data_component (to_expr2);
10832 from_se.want_pointer = 1;
10833 to_se.want_pointer = 1;
10834 gfc_conv_expr (&from_se, from_expr2);
10835 gfc_conv_expr (&to_se, to_expr2);
10836 gfc_add_block_to_block (&block, &from_se.pre);
10837 gfc_add_block_to_block (&block, &to_se.pre);
10839 /* Deallocate "to". */
10840 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10841 true, to_expr, to_expr->ts);
10842 gfc_add_expr_to_block (&block, tmp);
10844 /* Assign (_data) pointers. */
10845 gfc_add_modify_loc (input_location, &block, to_se.expr,
10846 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
10848 /* Set "from" to NULL. */
10849 gfc_add_modify_loc (input_location, &block, from_se.expr,
10850 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
10852 gfc_add_block_to_block (&block, &from_se.post);
10853 gfc_add_block_to_block (&block, &to_se.post);
10855 /* Set _vptr. */
10856 if (to_expr->ts.type == BT_CLASS)
10858 gfc_symbol *vtab;
10860 gfc_free_expr (to_expr2);
10861 gfc_init_se (&to_se, NULL);
10862 to_se.want_pointer = 1;
10863 gfc_add_vptr_component (to_expr);
10864 gfc_conv_expr (&to_se, to_expr);
10866 if (from_expr->ts.type == BT_CLASS)
10868 if (UNLIMITED_POLY (from_expr))
10869 vtab = NULL;
10870 else
10872 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10873 gcc_assert (vtab);
10876 gfc_free_expr (from_expr2);
10877 gfc_init_se (&from_se, NULL);
10878 from_se.want_pointer = 1;
10879 gfc_add_vptr_component (from_expr);
10880 gfc_conv_expr (&from_se, from_expr);
10881 gfc_add_modify_loc (input_location, &block, to_se.expr,
10882 fold_convert (TREE_TYPE (to_se.expr),
10883 from_se.expr));
10885 /* Reset _vptr component to declared type. */
10886 if (vtab == NULL)
10887 /* Unlimited polymorphic. */
10888 gfc_add_modify_loc (input_location, &block, from_se.expr,
10889 fold_convert (TREE_TYPE (from_se.expr),
10890 null_pointer_node));
10891 else
10893 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10894 gfc_add_modify_loc (input_location, &block, from_se.expr,
10895 fold_convert (TREE_TYPE (from_se.expr), tmp));
10898 else
10900 vtab = gfc_find_vtab (&from_expr->ts);
10901 gcc_assert (vtab);
10902 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10903 gfc_add_modify_loc (input_location, &block, to_se.expr,
10904 fold_convert (TREE_TYPE (to_se.expr), tmp));
10908 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
10910 gfc_add_modify_loc (input_location, &block, to_se.string_length,
10911 fold_convert (TREE_TYPE (to_se.string_length),
10912 from_se.string_length));
10913 if (from_expr->ts.deferred)
10914 gfc_add_modify_loc (input_location, &block, from_se.string_length,
10915 build_int_cst (TREE_TYPE (from_se.string_length), 0));
10918 return gfc_finish_block (&block);
10921 /* Update _vptr component. */
10922 if (to_expr->ts.type == BT_CLASS)
10924 gfc_symbol *vtab;
10926 to_se.want_pointer = 1;
10927 to_expr2 = gfc_copy_expr (to_expr);
10928 gfc_add_vptr_component (to_expr2);
10929 gfc_conv_expr (&to_se, to_expr2);
10931 if (from_expr->ts.type == BT_CLASS)
10933 if (UNLIMITED_POLY (from_expr))
10934 vtab = NULL;
10935 else
10937 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10938 gcc_assert (vtab);
10941 from_se.want_pointer = 1;
10942 from_expr2 = gfc_copy_expr (from_expr);
10943 gfc_add_vptr_component (from_expr2);
10944 gfc_conv_expr (&from_se, from_expr2);
10945 gfc_add_modify_loc (input_location, &block, to_se.expr,
10946 fold_convert (TREE_TYPE (to_se.expr),
10947 from_se.expr));
10949 /* Reset _vptr component to declared type. */
10950 if (vtab == NULL)
10951 /* Unlimited polymorphic. */
10952 gfc_add_modify_loc (input_location, &block, from_se.expr,
10953 fold_convert (TREE_TYPE (from_se.expr),
10954 null_pointer_node));
10955 else
10957 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10958 gfc_add_modify_loc (input_location, &block, from_se.expr,
10959 fold_convert (TREE_TYPE (from_se.expr), tmp));
10962 else
10964 vtab = gfc_find_vtab (&from_expr->ts);
10965 gcc_assert (vtab);
10966 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10967 gfc_add_modify_loc (input_location, &block, to_se.expr,
10968 fold_convert (TREE_TYPE (to_se.expr), tmp));
10971 gfc_free_expr (to_expr2);
10972 gfc_init_se (&to_se, NULL);
10974 if (from_expr->ts.type == BT_CLASS)
10976 gfc_free_expr (from_expr2);
10977 gfc_init_se (&from_se, NULL);
10982 /* Deallocate "to". */
10983 if (from_expr->rank == 0)
10985 to_se.want_coarray = 1;
10986 from_se.want_coarray = 1;
10988 gfc_conv_expr_descriptor (&to_se, to_expr);
10989 gfc_conv_expr_descriptor (&from_se, from_expr);
10991 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
10992 is an image control "statement", cf. IR F08/0040 in 12-006A. */
10993 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
10995 tree cond;
10997 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10998 NULL_TREE, NULL_TREE, true, to_expr,
10999 GFC_CAF_COARRAY_DEALLOCATE_ONLY);
11000 gfc_add_expr_to_block (&block, tmp);
11002 tmp = gfc_conv_descriptor_data_get (to_se.expr);
11003 cond = fold_build2_loc (input_location, EQ_EXPR,
11004 logical_type_node, tmp,
11005 fold_convert (TREE_TYPE (tmp),
11006 null_pointer_node));
11007 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
11008 3, null_pointer_node, null_pointer_node,
11009 build_int_cst (integer_type_node, 0));
11011 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
11012 tmp, build_empty_stmt (input_location));
11013 gfc_add_expr_to_block (&block, tmp);
11015 else
11017 if (to_expr->ts.type == BT_DERIVED
11018 && to_expr->ts.u.derived->attr.alloc_comp)
11020 tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
11021 to_se.expr, to_expr->rank);
11022 gfc_add_expr_to_block (&block, tmp);
11025 tmp = gfc_conv_descriptor_data_get (to_se.expr);
11026 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
11027 NULL_TREE, true, to_expr,
11028 GFC_CAF_COARRAY_NOCOARRAY);
11029 gfc_add_expr_to_block (&block, tmp);
11032 /* Move the pointer and update the array descriptor data. */
11033 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
11035 /* Set "from" to NULL. */
11036 tmp = gfc_conv_descriptor_data_get (from_se.expr);
11037 gfc_add_modify_loc (input_location, &block, tmp,
11038 fold_convert (TREE_TYPE (tmp), null_pointer_node));
11041 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
11043 gfc_add_modify_loc (input_location, &block, to_se.string_length,
11044 fold_convert (TREE_TYPE (to_se.string_length),
11045 from_se.string_length));
11046 if (from_expr->ts.deferred)
11047 gfc_add_modify_loc (input_location, &block, from_se.string_length,
11048 build_int_cst (TREE_TYPE (from_se.string_length), 0));
11051 return gfc_finish_block (&block);
11055 tree
11056 gfc_conv_intrinsic_subroutine (gfc_code *code)
11058 tree res;
11060 gcc_assert (code->resolved_isym);
11062 switch (code->resolved_isym->id)
11064 case GFC_ISYM_MOVE_ALLOC:
11065 res = conv_intrinsic_move_alloc (code);
11066 break;
11068 case GFC_ISYM_ATOMIC_CAS:
11069 res = conv_intrinsic_atomic_cas (code);
11070 break;
11072 case GFC_ISYM_ATOMIC_ADD:
11073 case GFC_ISYM_ATOMIC_AND:
11074 case GFC_ISYM_ATOMIC_DEF:
11075 case GFC_ISYM_ATOMIC_OR:
11076 case GFC_ISYM_ATOMIC_XOR:
11077 case GFC_ISYM_ATOMIC_FETCH_ADD:
11078 case GFC_ISYM_ATOMIC_FETCH_AND:
11079 case GFC_ISYM_ATOMIC_FETCH_OR:
11080 case GFC_ISYM_ATOMIC_FETCH_XOR:
11081 res = conv_intrinsic_atomic_op (code);
11082 break;
11084 case GFC_ISYM_ATOMIC_REF:
11085 res = conv_intrinsic_atomic_ref (code);
11086 break;
11088 case GFC_ISYM_EVENT_QUERY:
11089 res = conv_intrinsic_event_query (code);
11090 break;
11092 case GFC_ISYM_C_F_POINTER:
11093 case GFC_ISYM_C_F_PROCPOINTER:
11094 res = conv_isocbinding_subroutine (code);
11095 break;
11097 case GFC_ISYM_CAF_SEND:
11098 res = conv_caf_send (code);
11099 break;
11101 case GFC_ISYM_CO_BROADCAST:
11102 case GFC_ISYM_CO_MIN:
11103 case GFC_ISYM_CO_MAX:
11104 case GFC_ISYM_CO_REDUCE:
11105 case GFC_ISYM_CO_SUM:
11106 res = conv_co_collective (code);
11107 break;
11109 case GFC_ISYM_FREE:
11110 res = conv_intrinsic_free (code);
11111 break;
11113 case GFC_ISYM_RANDOM_INIT:
11114 res = conv_intrinsic_random_init (code);
11115 break;
11117 case GFC_ISYM_KILL:
11118 res = conv_intrinsic_kill_sub (code);
11119 break;
11121 case GFC_ISYM_SYSTEM_CLOCK:
11122 res = conv_intrinsic_system_clock (code);
11123 break;
11125 default:
11126 res = NULL_TREE;
11127 break;
11130 return res;
11133 #include "gt-fortran-trans-intrinsic.h"