2018-05-07 Edward Smith-Rowland <3dw4rd@verizon.net>
[official-gcc.git] / gcc / fortran / trans-intrinsic.c
blob87b3ca72c05a5498650c44c2eba590035b36ce6b
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 SYSTEM_CLOCK library functions, handling the type and kind
3639 conversions. */
3641 static tree
3642 conv_intrinsic_system_clock (gfc_code *code)
3644 stmtblock_t block;
3645 gfc_se count_se, count_rate_se, count_max_se;
3646 tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
3647 tree tmp;
3648 int least;
3650 gfc_expr *count = code->ext.actual->expr;
3651 gfc_expr *count_rate = code->ext.actual->next->expr;
3652 gfc_expr *count_max = code->ext.actual->next->next->expr;
3654 /* Evaluate our arguments. */
3655 if (count)
3657 gfc_init_se (&count_se, NULL);
3658 gfc_conv_expr (&count_se, count);
3661 if (count_rate)
3663 gfc_init_se (&count_rate_se, NULL);
3664 gfc_conv_expr (&count_rate_se, count_rate);
3667 if (count_max)
3669 gfc_init_se (&count_max_se, NULL);
3670 gfc_conv_expr (&count_max_se, count_max);
3673 /* Find the smallest kind found of the arguments. */
3674 least = 16;
3675 least = (count && count->ts.kind < least) ? count->ts.kind : least;
3676 least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
3677 : least;
3678 least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
3679 : least;
3681 /* Prepare temporary variables. */
3683 if (count)
3685 if (least >= 8)
3686 arg1 = gfc_create_var (gfc_get_int_type (8), "count");
3687 else if (least == 4)
3688 arg1 = gfc_create_var (gfc_get_int_type (4), "count");
3689 else if (count->ts.kind == 1)
3690 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
3691 count->ts.kind);
3692 else
3693 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
3694 count->ts.kind);
3697 if (count_rate)
3699 if (least >= 8)
3700 arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
3701 else if (least == 4)
3702 arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
3703 else
3704 arg2 = integer_zero_node;
3707 if (count_max)
3709 if (least >= 8)
3710 arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
3711 else if (least == 4)
3712 arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
3713 else
3714 arg3 = integer_zero_node;
3717 /* Make the function call. */
3718 gfc_init_block (&block);
3720 if (least <= 2)
3722 if (least == 1)
3724 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3725 : null_pointer_node;
3726 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3727 : null_pointer_node;
3728 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3729 : null_pointer_node;
3732 if (least == 2)
3734 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3735 : null_pointer_node;
3736 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3737 : null_pointer_node;
3738 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3739 : null_pointer_node;
3742 else
3744 if (least == 4)
3746 tmp = build_call_expr_loc (input_location,
3747 gfor_fndecl_system_clock4, 3,
3748 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3749 : null_pointer_node,
3750 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3751 : null_pointer_node,
3752 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3753 : null_pointer_node);
3754 gfc_add_expr_to_block (&block, tmp);
3756 /* Handle kind>=8, 10, or 16 arguments */
3757 if (least >= 8)
3759 tmp = build_call_expr_loc (input_location,
3760 gfor_fndecl_system_clock8, 3,
3761 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3762 : null_pointer_node,
3763 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3764 : null_pointer_node,
3765 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3766 : null_pointer_node);
3767 gfc_add_expr_to_block (&block, tmp);
3771 /* And store values back if needed. */
3772 if (arg1 && arg1 != count_se.expr)
3773 gfc_add_modify (&block, count_se.expr,
3774 fold_convert (TREE_TYPE (count_se.expr), arg1));
3775 if (arg2 && arg2 != count_rate_se.expr)
3776 gfc_add_modify (&block, count_rate_se.expr,
3777 fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
3778 if (arg3 && arg3 != count_max_se.expr)
3779 gfc_add_modify (&block, count_max_se.expr,
3780 fold_convert (TREE_TYPE (count_max_se.expr), arg3));
3782 return gfc_finish_block (&block);
3786 /* Return a character string containing the tty name. */
3788 static void
3789 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
3791 tree var;
3792 tree len;
3793 tree tmp;
3794 tree cond;
3795 tree fndecl;
3796 tree *args;
3797 unsigned int num_args;
3799 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3800 args = XALLOCAVEC (tree, num_args);
3802 var = gfc_create_var (pchar_type_node, "pstr");
3803 len = gfc_create_var (gfc_charlen_type_node, "len");
3805 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3806 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3807 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3809 fndecl = build_addr (gfor_fndecl_ttynam);
3810 tmp = build_call_array_loc (input_location,
3811 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
3812 fndecl, num_args, args);
3813 gfc_add_expr_to_block (&se->pre, tmp);
3815 /* Free the temporary afterwards, if necessary. */
3816 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3817 len, build_int_cst (TREE_TYPE (len), 0));
3818 tmp = gfc_call_free (var);
3819 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3820 gfc_add_expr_to_block (&se->post, tmp);
3822 se->expr = var;
3823 se->string_length = len;
3827 /* Get the minimum/maximum value of all the parameters.
3828 minmax (a1, a2, a3, ...)
3830 mvar = a1;
3831 if (a2 .op. mvar || isnan (mvar))
3832 mvar = a2;
3833 if (a3 .op. mvar || isnan (mvar))
3834 mvar = a3;
3836 return mvar
3840 /* TODO: Mismatching types can occur when specific names are used.
3841 These should be handled during resolution. */
3842 static void
3843 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
3845 tree tmp;
3846 tree mvar;
3847 tree val;
3848 tree thencase;
3849 tree *args;
3850 tree type;
3851 gfc_actual_arglist *argexpr;
3852 unsigned int i, nargs;
3854 nargs = gfc_intrinsic_argument_list_length (expr);
3855 args = XALLOCAVEC (tree, nargs);
3857 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
3858 type = gfc_typenode_for_spec (&expr->ts);
3860 argexpr = expr->value.function.actual;
3861 if (TREE_TYPE (args[0]) != type)
3862 args[0] = convert (type, args[0]);
3863 /* Only evaluate the argument once. */
3864 if (!VAR_P (args[0]) && !TREE_CONSTANT (args[0]))
3865 args[0] = gfc_evaluate_now (args[0], &se->pre);
3867 mvar = gfc_create_var (type, "M");
3868 gfc_add_modify (&se->pre, mvar, args[0]);
3869 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
3871 tree cond, isnan;
3873 val = args[i];
3875 /* Handle absent optional arguments by ignoring the comparison. */
3876 if (argexpr->expr->expr_type == EXPR_VARIABLE
3877 && argexpr->expr->symtree->n.sym->attr.optional
3878 && TREE_CODE (val) == INDIRECT_REF)
3879 cond = fold_build2_loc (input_location,
3880 NE_EXPR, logical_type_node,
3881 TREE_OPERAND (val, 0),
3882 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
3883 else
3885 cond = NULL_TREE;
3887 /* Only evaluate the argument once. */
3888 if (!VAR_P (val) && !TREE_CONSTANT (val))
3889 val = gfc_evaluate_now (val, &se->pre);
3892 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
3894 tmp = fold_build2_loc (input_location, op, logical_type_node,
3895 convert (type, val), mvar);
3897 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
3898 __builtin_isnan might be made dependent on that module being loaded,
3899 to help performance of programs that don't rely on IEEE semantics. */
3900 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
3902 isnan = build_call_expr_loc (input_location,
3903 builtin_decl_explicit (BUILT_IN_ISNAN),
3904 1, mvar);
3905 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3906 logical_type_node, tmp,
3907 fold_convert (logical_type_node, isnan));
3909 tmp = build3_v (COND_EXPR, tmp, thencase,
3910 build_empty_stmt (input_location));
3912 if (cond != NULL_TREE)
3913 tmp = build3_v (COND_EXPR, cond, tmp,
3914 build_empty_stmt (input_location));
3916 gfc_add_expr_to_block (&se->pre, tmp);
3917 argexpr = argexpr->next;
3919 se->expr = mvar;
3923 /* Generate library calls for MIN and MAX intrinsics for character
3924 variables. */
3925 static void
3926 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
3928 tree *args;
3929 tree var, len, fndecl, tmp, cond, function;
3930 unsigned int nargs;
3932 nargs = gfc_intrinsic_argument_list_length (expr);
3933 args = XALLOCAVEC (tree, nargs + 4);
3934 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
3936 /* Create the result variables. */
3937 len = gfc_create_var (gfc_charlen_type_node, "len");
3938 args[0] = gfc_build_addr_expr (NULL_TREE, len);
3939 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
3940 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
3941 args[2] = build_int_cst (integer_type_node, op);
3942 args[3] = build_int_cst (integer_type_node, nargs / 2);
3944 if (expr->ts.kind == 1)
3945 function = gfor_fndecl_string_minmax;
3946 else if (expr->ts.kind == 4)
3947 function = gfor_fndecl_string_minmax_char4;
3948 else
3949 gcc_unreachable ();
3951 /* Make the function call. */
3952 fndecl = build_addr (function);
3953 tmp = build_call_array_loc (input_location,
3954 TREE_TYPE (TREE_TYPE (function)), fndecl,
3955 nargs + 4, args);
3956 gfc_add_expr_to_block (&se->pre, tmp);
3958 /* Free the temporary afterwards, if necessary. */
3959 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3960 len, build_int_cst (TREE_TYPE (len), 0));
3961 tmp = gfc_call_free (var);
3962 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3963 gfc_add_expr_to_block (&se->post, tmp);
3965 se->expr = var;
3966 se->string_length = len;
3970 /* Create a symbol node for this intrinsic. The symbol from the frontend
3971 has the generic name. */
3973 static gfc_symbol *
3974 gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
3976 gfc_symbol *sym;
3978 /* TODO: Add symbols for intrinsic function to the global namespace. */
3979 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
3980 sym = gfc_new_symbol (expr->value.function.name, NULL);
3982 sym->ts = expr->ts;
3983 sym->attr.external = 1;
3984 sym->attr.function = 1;
3985 sym->attr.always_explicit = 1;
3986 sym->attr.proc = PROC_INTRINSIC;
3987 sym->attr.flavor = FL_PROCEDURE;
3988 sym->result = sym;
3989 if (expr->rank > 0)
3991 sym->attr.dimension = 1;
3992 sym->as = gfc_get_array_spec ();
3993 sym->as->type = AS_ASSUMED_SHAPE;
3994 sym->as->rank = expr->rank;
3997 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
3998 ignore_optional ? expr->value.function.actual
3999 : NULL);
4001 return sym;
4004 /* Generate a call to an external intrinsic function. */
4005 static void
4006 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
4008 gfc_symbol *sym;
4009 vec<tree, va_gc> *append_args;
4011 gcc_assert (!se->ss || se->ss->info->expr == expr);
4013 if (se->ss)
4014 gcc_assert (expr->rank > 0);
4015 else
4016 gcc_assert (expr->rank == 0);
4018 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
4020 /* Calls to libgfortran_matmul need to be appended special arguments,
4021 to be able to call the BLAS ?gemm functions if required and possible. */
4022 append_args = NULL;
4023 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
4024 && sym->ts.type != BT_LOGICAL)
4026 tree cint = gfc_get_int_type (gfc_c_int_kind);
4028 if (flag_external_blas
4029 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
4030 && (sym->ts.kind == 4 || sym->ts.kind == 8))
4032 tree gemm_fndecl;
4034 if (sym->ts.type == BT_REAL)
4036 if (sym->ts.kind == 4)
4037 gemm_fndecl = gfor_fndecl_sgemm;
4038 else
4039 gemm_fndecl = gfor_fndecl_dgemm;
4041 else
4043 if (sym->ts.kind == 4)
4044 gemm_fndecl = gfor_fndecl_cgemm;
4045 else
4046 gemm_fndecl = gfor_fndecl_zgemm;
4049 vec_alloc (append_args, 3);
4050 append_args->quick_push (build_int_cst (cint, 1));
4051 append_args->quick_push (build_int_cst (cint,
4052 flag_blas_matmul_limit));
4053 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
4054 gemm_fndecl));
4056 else
4058 vec_alloc (append_args, 3);
4059 append_args->quick_push (build_int_cst (cint, 0));
4060 append_args->quick_push (build_int_cst (cint, 0));
4061 append_args->quick_push (null_pointer_node);
4065 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4066 append_args);
4067 gfc_free_symbol (sym);
4070 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4071 Implemented as
4072 any(a)
4074 forall (i=...)
4075 if (a[i] != 0)
4076 return 1
4077 end forall
4078 return 0
4080 all(a)
4082 forall (i=...)
4083 if (a[i] == 0)
4084 return 0
4085 end forall
4086 return 1
4089 static void
4090 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
4092 tree resvar;
4093 stmtblock_t block;
4094 stmtblock_t body;
4095 tree type;
4096 tree tmp;
4097 tree found;
4098 gfc_loopinfo loop;
4099 gfc_actual_arglist *actual;
4100 gfc_ss *arrayss;
4101 gfc_se arrayse;
4102 tree exit_label;
4104 if (se->ss)
4106 gfc_conv_intrinsic_funcall (se, expr);
4107 return;
4110 actual = expr->value.function.actual;
4111 type = gfc_typenode_for_spec (&expr->ts);
4112 /* Initialize the result. */
4113 resvar = gfc_create_var (type, "test");
4114 if (op == EQ_EXPR)
4115 tmp = convert (type, boolean_true_node);
4116 else
4117 tmp = convert (type, boolean_false_node);
4118 gfc_add_modify (&se->pre, resvar, tmp);
4120 /* Walk the arguments. */
4121 arrayss = gfc_walk_expr (actual->expr);
4122 gcc_assert (arrayss != gfc_ss_terminator);
4124 /* Initialize the scalarizer. */
4125 gfc_init_loopinfo (&loop);
4126 exit_label = gfc_build_label_decl (NULL_TREE);
4127 TREE_USED (exit_label) = 1;
4128 gfc_add_ss_to_loop (&loop, arrayss);
4130 /* Initialize the loop. */
4131 gfc_conv_ss_startstride (&loop);
4132 gfc_conv_loop_setup (&loop, &expr->where);
4134 gfc_mark_ss_chain_used (arrayss, 1);
4135 /* Generate the loop body. */
4136 gfc_start_scalarized_body (&loop, &body);
4138 /* If the condition matches then set the return value. */
4139 gfc_start_block (&block);
4140 if (op == EQ_EXPR)
4141 tmp = convert (type, boolean_false_node);
4142 else
4143 tmp = convert (type, boolean_true_node);
4144 gfc_add_modify (&block, resvar, tmp);
4146 /* And break out of the loop. */
4147 tmp = build1_v (GOTO_EXPR, exit_label);
4148 gfc_add_expr_to_block (&block, tmp);
4150 found = gfc_finish_block (&block);
4152 /* Check this element. */
4153 gfc_init_se (&arrayse, NULL);
4154 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4155 arrayse.ss = arrayss;
4156 gfc_conv_expr_val (&arrayse, actual->expr);
4158 gfc_add_block_to_block (&body, &arrayse.pre);
4159 tmp = fold_build2_loc (input_location, op, logical_type_node, arrayse.expr,
4160 build_int_cst (TREE_TYPE (arrayse.expr), 0));
4161 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
4162 gfc_add_expr_to_block (&body, tmp);
4163 gfc_add_block_to_block (&body, &arrayse.post);
4165 gfc_trans_scalarizing_loops (&loop, &body);
4167 /* Add the exit label. */
4168 tmp = build1_v (LABEL_EXPR, exit_label);
4169 gfc_add_expr_to_block (&loop.pre, tmp);
4171 gfc_add_block_to_block (&se->pre, &loop.pre);
4172 gfc_add_block_to_block (&se->pre, &loop.post);
4173 gfc_cleanup_loop (&loop);
4175 se->expr = resvar;
4178 /* COUNT(A) = Number of true elements in A. */
4179 static void
4180 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
4182 tree resvar;
4183 tree type;
4184 stmtblock_t body;
4185 tree tmp;
4186 gfc_loopinfo loop;
4187 gfc_actual_arglist *actual;
4188 gfc_ss *arrayss;
4189 gfc_se arrayse;
4191 if (se->ss)
4193 gfc_conv_intrinsic_funcall (se, expr);
4194 return;
4197 actual = expr->value.function.actual;
4199 type = gfc_typenode_for_spec (&expr->ts);
4200 /* Initialize the result. */
4201 resvar = gfc_create_var (type, "count");
4202 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4204 /* Walk the arguments. */
4205 arrayss = gfc_walk_expr (actual->expr);
4206 gcc_assert (arrayss != gfc_ss_terminator);
4208 /* Initialize the scalarizer. */
4209 gfc_init_loopinfo (&loop);
4210 gfc_add_ss_to_loop (&loop, arrayss);
4212 /* Initialize the loop. */
4213 gfc_conv_ss_startstride (&loop);
4214 gfc_conv_loop_setup (&loop, &expr->where);
4216 gfc_mark_ss_chain_used (arrayss, 1);
4217 /* Generate the loop body. */
4218 gfc_start_scalarized_body (&loop, &body);
4220 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
4221 resvar, build_int_cst (TREE_TYPE (resvar), 1));
4222 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
4224 gfc_init_se (&arrayse, NULL);
4225 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4226 arrayse.ss = arrayss;
4227 gfc_conv_expr_val (&arrayse, actual->expr);
4228 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
4229 build_empty_stmt (input_location));
4231 gfc_add_block_to_block (&body, &arrayse.pre);
4232 gfc_add_expr_to_block (&body, tmp);
4233 gfc_add_block_to_block (&body, &arrayse.post);
4235 gfc_trans_scalarizing_loops (&loop, &body);
4237 gfc_add_block_to_block (&se->pre, &loop.pre);
4238 gfc_add_block_to_block (&se->pre, &loop.post);
4239 gfc_cleanup_loop (&loop);
4241 se->expr = resvar;
4245 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4246 struct and return the corresponding loopinfo. */
4248 static gfc_loopinfo *
4249 enter_nested_loop (gfc_se *se)
4251 se->ss = se->ss->nested_ss;
4252 gcc_assert (se->ss == se->ss->loop->ss);
4254 return se->ss->loop;
4258 /* Inline implementation of the sum and product intrinsics. */
4259 static void
4260 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
4261 bool norm2)
4263 tree resvar;
4264 tree scale = NULL_TREE;
4265 tree type;
4266 stmtblock_t body;
4267 stmtblock_t block;
4268 tree tmp;
4269 gfc_loopinfo loop, *ploop;
4270 gfc_actual_arglist *arg_array, *arg_mask;
4271 gfc_ss *arrayss = NULL;
4272 gfc_ss *maskss = NULL;
4273 gfc_se arrayse;
4274 gfc_se maskse;
4275 gfc_se *parent_se;
4276 gfc_expr *arrayexpr;
4277 gfc_expr *maskexpr;
4279 if (expr->rank > 0)
4281 gcc_assert (gfc_inline_intrinsic_function_p (expr));
4282 parent_se = se;
4284 else
4285 parent_se = NULL;
4287 type = gfc_typenode_for_spec (&expr->ts);
4288 /* Initialize the result. */
4289 resvar = gfc_create_var (type, "val");
4290 if (norm2)
4292 /* result = 0.0;
4293 scale = 1.0. */
4294 scale = gfc_create_var (type, "scale");
4295 gfc_add_modify (&se->pre, scale,
4296 gfc_build_const (type, integer_one_node));
4297 tmp = gfc_build_const (type, integer_zero_node);
4299 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4300 tmp = gfc_build_const (type, integer_zero_node);
4301 else if (op == NE_EXPR)
4302 /* PARITY. */
4303 tmp = convert (type, boolean_false_node);
4304 else if (op == BIT_AND_EXPR)
4305 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
4306 type, integer_one_node));
4307 else
4308 tmp = gfc_build_const (type, integer_one_node);
4310 gfc_add_modify (&se->pre, resvar, tmp);
4312 arg_array = expr->value.function.actual;
4314 arrayexpr = arg_array->expr;
4316 if (op == NE_EXPR || norm2)
4317 /* PARITY and NORM2. */
4318 maskexpr = NULL;
4319 else
4321 arg_mask = arg_array->next->next;
4322 gcc_assert (arg_mask != NULL);
4323 maskexpr = arg_mask->expr;
4326 if (expr->rank == 0)
4328 /* Walk the arguments. */
4329 arrayss = gfc_walk_expr (arrayexpr);
4330 gcc_assert (arrayss != gfc_ss_terminator);
4332 if (maskexpr && maskexpr->rank > 0)
4334 maskss = gfc_walk_expr (maskexpr);
4335 gcc_assert (maskss != gfc_ss_terminator);
4337 else
4338 maskss = NULL;
4340 /* Initialize the scalarizer. */
4341 gfc_init_loopinfo (&loop);
4342 gfc_add_ss_to_loop (&loop, arrayss);
4343 if (maskexpr && maskexpr->rank > 0)
4344 gfc_add_ss_to_loop (&loop, maskss);
4346 /* Initialize the loop. */
4347 gfc_conv_ss_startstride (&loop);
4348 gfc_conv_loop_setup (&loop, &expr->where);
4350 gfc_mark_ss_chain_used (arrayss, 1);
4351 if (maskexpr && maskexpr->rank > 0)
4352 gfc_mark_ss_chain_used (maskss, 1);
4354 ploop = &loop;
4356 else
4357 /* All the work has been done in the parent loops. */
4358 ploop = enter_nested_loop (se);
4360 gcc_assert (ploop);
4362 /* Generate the loop body. */
4363 gfc_start_scalarized_body (ploop, &body);
4365 /* If we have a mask, only add this element if the mask is set. */
4366 if (maskexpr && maskexpr->rank > 0)
4368 gfc_init_se (&maskse, parent_se);
4369 gfc_copy_loopinfo_to_se (&maskse, ploop);
4370 if (expr->rank == 0)
4371 maskse.ss = maskss;
4372 gfc_conv_expr_val (&maskse, maskexpr);
4373 gfc_add_block_to_block (&body, &maskse.pre);
4375 gfc_start_block (&block);
4377 else
4378 gfc_init_block (&block);
4380 /* Do the actual summation/product. */
4381 gfc_init_se (&arrayse, parent_se);
4382 gfc_copy_loopinfo_to_se (&arrayse, ploop);
4383 if (expr->rank == 0)
4384 arrayse.ss = arrayss;
4385 gfc_conv_expr_val (&arrayse, arrayexpr);
4386 gfc_add_block_to_block (&block, &arrayse.pre);
4388 if (norm2)
4390 /* if (x (i) != 0.0)
4392 absX = abs(x(i))
4393 if (absX > scale)
4395 val = scale/absX;
4396 result = 1.0 + result * val * val;
4397 scale = absX;
4399 else
4401 val = absX/scale;
4402 result += val * val;
4404 } */
4405 tree res1, res2, cond, absX, val;
4406 stmtblock_t ifblock1, ifblock2, ifblock3;
4408 gfc_init_block (&ifblock1);
4410 absX = gfc_create_var (type, "absX");
4411 gfc_add_modify (&ifblock1, absX,
4412 fold_build1_loc (input_location, ABS_EXPR, type,
4413 arrayse.expr));
4414 val = gfc_create_var (type, "val");
4415 gfc_add_expr_to_block (&ifblock1, val);
4417 gfc_init_block (&ifblock2);
4418 gfc_add_modify (&ifblock2, val,
4419 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
4420 absX));
4421 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4422 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
4423 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
4424 gfc_build_const (type, integer_one_node));
4425 gfc_add_modify (&ifblock2, resvar, res1);
4426 gfc_add_modify (&ifblock2, scale, absX);
4427 res1 = gfc_finish_block (&ifblock2);
4429 gfc_init_block (&ifblock3);
4430 gfc_add_modify (&ifblock3, val,
4431 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
4432 scale));
4433 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4434 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
4435 gfc_add_modify (&ifblock3, resvar, res2);
4436 res2 = gfc_finish_block (&ifblock3);
4438 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4439 absX, scale);
4440 tmp = build3_v (COND_EXPR, cond, res1, res2);
4441 gfc_add_expr_to_block (&ifblock1, tmp);
4442 tmp = gfc_finish_block (&ifblock1);
4444 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
4445 arrayse.expr,
4446 gfc_build_const (type, integer_zero_node));
4448 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4449 gfc_add_expr_to_block (&block, tmp);
4451 else
4453 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
4454 gfc_add_modify (&block, resvar, tmp);
4457 gfc_add_block_to_block (&block, &arrayse.post);
4459 if (maskexpr && maskexpr->rank > 0)
4461 /* We enclose the above in if (mask) {...} . */
4463 tmp = gfc_finish_block (&block);
4464 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4465 build_empty_stmt (input_location));
4467 else
4468 tmp = gfc_finish_block (&block);
4469 gfc_add_expr_to_block (&body, tmp);
4471 gfc_trans_scalarizing_loops (ploop, &body);
4473 /* For a scalar mask, enclose the loop in an if statement. */
4474 if (maskexpr && maskexpr->rank == 0)
4476 gfc_init_block (&block);
4477 gfc_add_block_to_block (&block, &ploop->pre);
4478 gfc_add_block_to_block (&block, &ploop->post);
4479 tmp = gfc_finish_block (&block);
4481 if (expr->rank > 0)
4483 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
4484 build_empty_stmt (input_location));
4485 gfc_advance_se_ss_chain (se);
4487 else
4489 gcc_assert (expr->rank == 0);
4490 gfc_init_se (&maskse, NULL);
4491 gfc_conv_expr_val (&maskse, maskexpr);
4492 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4493 build_empty_stmt (input_location));
4496 gfc_add_expr_to_block (&block, tmp);
4497 gfc_add_block_to_block (&se->pre, &block);
4498 gcc_assert (se->post.head == NULL);
4500 else
4502 gfc_add_block_to_block (&se->pre, &ploop->pre);
4503 gfc_add_block_to_block (&se->pre, &ploop->post);
4506 if (expr->rank == 0)
4507 gfc_cleanup_loop (ploop);
4509 if (norm2)
4511 /* result = scale * sqrt(result). */
4512 tree sqrt;
4513 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
4514 resvar = build_call_expr_loc (input_location,
4515 sqrt, 1, resvar);
4516 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
4519 se->expr = resvar;
4523 /* Inline implementation of the dot_product intrinsic. This function
4524 is based on gfc_conv_intrinsic_arith (the previous function). */
4525 static void
4526 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
4528 tree resvar;
4529 tree type;
4530 stmtblock_t body;
4531 stmtblock_t block;
4532 tree tmp;
4533 gfc_loopinfo loop;
4534 gfc_actual_arglist *actual;
4535 gfc_ss *arrayss1, *arrayss2;
4536 gfc_se arrayse1, arrayse2;
4537 gfc_expr *arrayexpr1, *arrayexpr2;
4539 type = gfc_typenode_for_spec (&expr->ts);
4541 /* Initialize the result. */
4542 resvar = gfc_create_var (type, "val");
4543 if (expr->ts.type == BT_LOGICAL)
4544 tmp = build_int_cst (type, 0);
4545 else
4546 tmp = gfc_build_const (type, integer_zero_node);
4548 gfc_add_modify (&se->pre, resvar, tmp);
4550 /* Walk argument #1. */
4551 actual = expr->value.function.actual;
4552 arrayexpr1 = actual->expr;
4553 arrayss1 = gfc_walk_expr (arrayexpr1);
4554 gcc_assert (arrayss1 != gfc_ss_terminator);
4556 /* Walk argument #2. */
4557 actual = actual->next;
4558 arrayexpr2 = actual->expr;
4559 arrayss2 = gfc_walk_expr (arrayexpr2);
4560 gcc_assert (arrayss2 != gfc_ss_terminator);
4562 /* Initialize the scalarizer. */
4563 gfc_init_loopinfo (&loop);
4564 gfc_add_ss_to_loop (&loop, arrayss1);
4565 gfc_add_ss_to_loop (&loop, arrayss2);
4567 /* Initialize the loop. */
4568 gfc_conv_ss_startstride (&loop);
4569 gfc_conv_loop_setup (&loop, &expr->where);
4571 gfc_mark_ss_chain_used (arrayss1, 1);
4572 gfc_mark_ss_chain_used (arrayss2, 1);
4574 /* Generate the loop body. */
4575 gfc_start_scalarized_body (&loop, &body);
4576 gfc_init_block (&block);
4578 /* Make the tree expression for [conjg(]array1[)]. */
4579 gfc_init_se (&arrayse1, NULL);
4580 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
4581 arrayse1.ss = arrayss1;
4582 gfc_conv_expr_val (&arrayse1, arrayexpr1);
4583 if (expr->ts.type == BT_COMPLEX)
4584 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
4585 arrayse1.expr);
4586 gfc_add_block_to_block (&block, &arrayse1.pre);
4588 /* Make the tree expression for array2. */
4589 gfc_init_se (&arrayse2, NULL);
4590 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
4591 arrayse2.ss = arrayss2;
4592 gfc_conv_expr_val (&arrayse2, arrayexpr2);
4593 gfc_add_block_to_block (&block, &arrayse2.pre);
4595 /* Do the actual product and sum. */
4596 if (expr->ts.type == BT_LOGICAL)
4598 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
4599 arrayse1.expr, arrayse2.expr);
4600 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
4602 else
4604 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
4605 arrayse2.expr);
4606 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
4608 gfc_add_modify (&block, resvar, tmp);
4610 /* Finish up the loop block and the loop. */
4611 tmp = gfc_finish_block (&block);
4612 gfc_add_expr_to_block (&body, tmp);
4614 gfc_trans_scalarizing_loops (&loop, &body);
4615 gfc_add_block_to_block (&se->pre, &loop.pre);
4616 gfc_add_block_to_block (&se->pre, &loop.post);
4617 gfc_cleanup_loop (&loop);
4619 se->expr = resvar;
4623 /* Emit code for minloc or maxloc intrinsic. There are many different cases
4624 we need to handle. For performance reasons we sometimes create two
4625 loops instead of one, where the second one is much simpler.
4626 Examples for minloc intrinsic:
4627 1) Result is an array, a call is generated
4628 2) Array mask is used and NaNs need to be supported:
4629 limit = Infinity;
4630 pos = 0;
4631 S = from;
4632 while (S <= to) {
4633 if (mask[S]) {
4634 if (pos == 0) pos = S + (1 - from);
4635 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4637 S++;
4639 goto lab2;
4640 lab1:;
4641 while (S <= to) {
4642 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4643 S++;
4645 lab2:;
4646 3) NaNs need to be supported, but it is known at compile time or cheaply
4647 at runtime whether array is nonempty or not:
4648 limit = Infinity;
4649 pos = 0;
4650 S = from;
4651 while (S <= to) {
4652 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4653 S++;
4655 if (from <= to) pos = 1;
4656 goto lab2;
4657 lab1:;
4658 while (S <= to) {
4659 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4660 S++;
4662 lab2:;
4663 4) NaNs aren't supported, array mask is used:
4664 limit = infinities_supported ? Infinity : huge (limit);
4665 pos = 0;
4666 S = from;
4667 while (S <= to) {
4668 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4669 S++;
4671 goto lab2;
4672 lab1:;
4673 while (S <= to) {
4674 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4675 S++;
4677 lab2:;
4678 5) Same without array mask:
4679 limit = infinities_supported ? Infinity : huge (limit);
4680 pos = (from <= to) ? 1 : 0;
4681 S = from;
4682 while (S <= to) {
4683 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4684 S++;
4686 For 3) and 5), if mask is scalar, this all goes into a conditional,
4687 setting pos = 0; in the else branch. */
4689 static void
4690 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
4692 stmtblock_t body;
4693 stmtblock_t block;
4694 stmtblock_t ifblock;
4695 stmtblock_t elseblock;
4696 tree limit;
4697 tree type;
4698 tree tmp;
4699 tree cond;
4700 tree elsetmp;
4701 tree ifbody;
4702 tree offset;
4703 tree nonempty;
4704 tree lab1, lab2;
4705 gfc_loopinfo loop;
4706 gfc_actual_arglist *actual;
4707 gfc_ss *arrayss;
4708 gfc_ss *maskss;
4709 gfc_se arrayse;
4710 gfc_se maskse;
4711 gfc_expr *arrayexpr;
4712 gfc_expr *maskexpr;
4713 tree pos;
4714 int n;
4716 actual = expr->value.function.actual;
4718 /* The last argument, BACK, is passed by value. Ensure that
4719 by setting its name to %VAL. */
4720 for (gfc_actual_arglist *a = actual; a; a = a->next)
4722 if (a->next == NULL)
4723 a->name = "%VAL";
4726 if (se->ss)
4728 gfc_conv_intrinsic_funcall (se, expr);
4729 return;
4732 arrayexpr = actual->expr;
4734 /* Special case for character maxloc. Remove unneeded actual
4735 arguments, then call a library function. */
4737 if (arrayexpr->ts.type == BT_CHARACTER)
4739 gfc_actual_arglist *a, *b;
4740 a = actual;
4741 while (a->next)
4743 b = a->next;
4744 if (b->expr == NULL || strcmp (b->name, "dim") == 0)
4746 a->next = b->next;
4747 b->next = NULL;
4748 gfc_free_actual_arglist (b);
4750 else
4751 a = b;
4753 gfc_conv_intrinsic_funcall (se, expr);
4754 return;
4757 /* Initialize the result. */
4758 pos = gfc_create_var (gfc_array_index_type, "pos");
4759 offset = gfc_create_var (gfc_array_index_type, "offset");
4760 type = gfc_typenode_for_spec (&expr->ts);
4762 /* Walk the arguments. */
4763 arrayss = gfc_walk_expr (arrayexpr);
4764 gcc_assert (arrayss != gfc_ss_terminator);
4766 actual = actual->next->next;
4767 gcc_assert (actual);
4768 maskexpr = actual->expr;
4769 nonempty = NULL;
4770 if (maskexpr && maskexpr->rank != 0)
4772 maskss = gfc_walk_expr (maskexpr);
4773 gcc_assert (maskss != gfc_ss_terminator);
4775 else
4777 mpz_t asize;
4778 if (gfc_array_size (arrayexpr, &asize))
4780 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
4781 mpz_clear (asize);
4782 nonempty = fold_build2_loc (input_location, GT_EXPR,
4783 logical_type_node, nonempty,
4784 gfc_index_zero_node);
4786 maskss = NULL;
4789 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
4790 switch (arrayexpr->ts.type)
4792 case BT_REAL:
4793 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
4794 break;
4796 case BT_INTEGER:
4797 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
4798 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
4799 arrayexpr->ts.kind);
4800 break;
4802 default:
4803 gcc_unreachable ();
4806 /* We start with the most negative possible value for MAXLOC, and the most
4807 positive possible value for MINLOC. The most negative possible value is
4808 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
4809 possible value is HUGE in both cases. */
4810 if (op == GT_EXPR)
4811 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
4812 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
4813 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
4814 build_int_cst (TREE_TYPE (tmp), 1));
4816 gfc_add_modify (&se->pre, limit, tmp);
4818 /* Initialize the scalarizer. */
4819 gfc_init_loopinfo (&loop);
4820 gfc_add_ss_to_loop (&loop, arrayss);
4821 if (maskss)
4822 gfc_add_ss_to_loop (&loop, maskss);
4824 /* Initialize the loop. */
4825 gfc_conv_ss_startstride (&loop);
4827 /* The code generated can have more than one loop in sequence (see the
4828 comment at the function header). This doesn't work well with the
4829 scalarizer, which changes arrays' offset when the scalarization loops
4830 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
4831 are currently inlined in the scalar case only (for which loop is of rank
4832 one). As there is no dependency to care about in that case, there is no
4833 temporary, so that we can use the scalarizer temporary code to handle
4834 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
4835 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
4836 to restore offset.
4837 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
4838 should eventually go away. We could either create two loops properly,
4839 or find another way to save/restore the array offsets between the two
4840 loops (without conflicting with temporary management), or use a single
4841 loop minmaxloc implementation. See PR 31067. */
4842 loop.temp_dim = loop.dimen;
4843 gfc_conv_loop_setup (&loop, &expr->where);
4845 gcc_assert (loop.dimen == 1);
4846 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
4847 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
4848 loop.from[0], loop.to[0]);
4850 lab1 = NULL;
4851 lab2 = NULL;
4852 /* Initialize the position to zero, following Fortran 2003. We are free
4853 to do this because Fortran 95 allows the result of an entirely false
4854 mask to be processor dependent. If we know at compile time the array
4855 is non-empty and no MASK is used, we can initialize to 1 to simplify
4856 the inner loop. */
4857 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
4858 gfc_add_modify (&loop.pre, pos,
4859 fold_build3_loc (input_location, COND_EXPR,
4860 gfc_array_index_type,
4861 nonempty, gfc_index_one_node,
4862 gfc_index_zero_node));
4863 else
4865 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
4866 lab1 = gfc_build_label_decl (NULL_TREE);
4867 TREE_USED (lab1) = 1;
4868 lab2 = gfc_build_label_decl (NULL_TREE);
4869 TREE_USED (lab2) = 1;
4872 /* An offset must be added to the loop
4873 counter to obtain the required position. */
4874 gcc_assert (loop.from[0]);
4876 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4877 gfc_index_one_node, loop.from[0]);
4878 gfc_add_modify (&loop.pre, offset, tmp);
4880 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
4881 if (maskss)
4882 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
4883 /* Generate the loop body. */
4884 gfc_start_scalarized_body (&loop, &body);
4886 /* If we have a mask, only check this element if the mask is set. */
4887 if (maskss)
4889 gfc_init_se (&maskse, NULL);
4890 gfc_copy_loopinfo_to_se (&maskse, &loop);
4891 maskse.ss = maskss;
4892 gfc_conv_expr_val (&maskse, maskexpr);
4893 gfc_add_block_to_block (&body, &maskse.pre);
4895 gfc_start_block (&block);
4897 else
4898 gfc_init_block (&block);
4900 /* Compare with the current limit. */
4901 gfc_init_se (&arrayse, NULL);
4902 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4903 arrayse.ss = arrayss;
4904 gfc_conv_expr_val (&arrayse, arrayexpr);
4905 gfc_add_block_to_block (&block, &arrayse.pre);
4907 /* We do the following if this is a more extreme value. */
4908 gfc_start_block (&ifblock);
4910 /* Assign the value to the limit... */
4911 gfc_add_modify (&ifblock, limit, arrayse.expr);
4913 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
4915 stmtblock_t ifblock2;
4916 tree ifbody2;
4918 gfc_start_block (&ifblock2);
4919 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4920 loop.loopvar[0], offset);
4921 gfc_add_modify (&ifblock2, pos, tmp);
4922 ifbody2 = gfc_finish_block (&ifblock2);
4923 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pos,
4924 gfc_index_zero_node);
4925 tmp = build3_v (COND_EXPR, cond, ifbody2,
4926 build_empty_stmt (input_location));
4927 gfc_add_expr_to_block (&block, tmp);
4930 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4931 loop.loopvar[0], offset);
4932 gfc_add_modify (&ifblock, pos, tmp);
4934 if (lab1)
4935 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
4937 ifbody = gfc_finish_block (&ifblock);
4939 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
4941 if (lab1)
4942 cond = fold_build2_loc (input_location,
4943 op == GT_EXPR ? GE_EXPR : LE_EXPR,
4944 logical_type_node, arrayse.expr, limit);
4945 else
4946 cond = fold_build2_loc (input_location, op, logical_type_node,
4947 arrayse.expr, limit);
4949 ifbody = build3_v (COND_EXPR, cond, ifbody,
4950 build_empty_stmt (input_location));
4952 gfc_add_expr_to_block (&block, ifbody);
4954 if (maskss)
4956 /* We enclose the above in if (mask) {...}. */
4957 tmp = gfc_finish_block (&block);
4959 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4960 build_empty_stmt (input_location));
4962 else
4963 tmp = gfc_finish_block (&block);
4964 gfc_add_expr_to_block (&body, tmp);
4966 if (lab1)
4968 gfc_trans_scalarized_loop_boundary (&loop, &body);
4970 if (HONOR_NANS (DECL_MODE (limit)))
4972 if (nonempty != NULL)
4974 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
4975 tmp = build3_v (COND_EXPR, nonempty, ifbody,
4976 build_empty_stmt (input_location));
4977 gfc_add_expr_to_block (&loop.code[0], tmp);
4981 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
4982 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
4984 /* If we have a mask, only check this element if the mask is set. */
4985 if (maskss)
4987 gfc_init_se (&maskse, NULL);
4988 gfc_copy_loopinfo_to_se (&maskse, &loop);
4989 maskse.ss = maskss;
4990 gfc_conv_expr_val (&maskse, maskexpr);
4991 gfc_add_block_to_block (&body, &maskse.pre);
4993 gfc_start_block (&block);
4995 else
4996 gfc_init_block (&block);
4998 /* Compare with the current limit. */
4999 gfc_init_se (&arrayse, NULL);
5000 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5001 arrayse.ss = arrayss;
5002 gfc_conv_expr_val (&arrayse, arrayexpr);
5003 gfc_add_block_to_block (&block, &arrayse.pre);
5005 /* We do the following if this is a more extreme value. */
5006 gfc_start_block (&ifblock);
5008 /* Assign the value to the limit... */
5009 gfc_add_modify (&ifblock, limit, arrayse.expr);
5011 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
5012 loop.loopvar[0], offset);
5013 gfc_add_modify (&ifblock, pos, tmp);
5015 ifbody = gfc_finish_block (&ifblock);
5017 cond = fold_build2_loc (input_location, op, logical_type_node,
5018 arrayse.expr, limit);
5020 tmp = build3_v (COND_EXPR, cond, ifbody,
5021 build_empty_stmt (input_location));
5022 gfc_add_expr_to_block (&block, tmp);
5024 if (maskss)
5026 /* We enclose the above in if (mask) {...}. */
5027 tmp = gfc_finish_block (&block);
5029 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5030 build_empty_stmt (input_location));
5032 else
5033 tmp = gfc_finish_block (&block);
5034 gfc_add_expr_to_block (&body, tmp);
5035 /* Avoid initializing loopvar[0] again, it should be left where
5036 it finished by the first loop. */
5037 loop.from[0] = loop.loopvar[0];
5040 gfc_trans_scalarizing_loops (&loop, &body);
5042 if (lab2)
5043 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
5045 /* For a scalar mask, enclose the loop in an if statement. */
5046 if (maskexpr && maskss == NULL)
5048 gfc_init_se (&maskse, NULL);
5049 gfc_conv_expr_val (&maskse, maskexpr);
5050 gfc_init_block (&block);
5051 gfc_add_block_to_block (&block, &loop.pre);
5052 gfc_add_block_to_block (&block, &loop.post);
5053 tmp = gfc_finish_block (&block);
5055 /* For the else part of the scalar mask, just initialize
5056 the pos variable the same way as above. */
5058 gfc_init_block (&elseblock);
5059 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
5060 elsetmp = gfc_finish_block (&elseblock);
5062 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
5063 gfc_add_expr_to_block (&block, tmp);
5064 gfc_add_block_to_block (&se->pre, &block);
5066 else
5068 gfc_add_block_to_block (&se->pre, &loop.pre);
5069 gfc_add_block_to_block (&se->pre, &loop.post);
5071 gfc_cleanup_loop (&loop);
5073 se->expr = convert (type, pos);
5076 /* Emit code for minval or maxval intrinsic. There are many different cases
5077 we need to handle. For performance reasons we sometimes create two
5078 loops instead of one, where the second one is much simpler.
5079 Examples for minval intrinsic:
5080 1) Result is an array, a call is generated
5081 2) Array mask is used and NaNs need to be supported, rank 1:
5082 limit = Infinity;
5083 nonempty = false;
5084 S = from;
5085 while (S <= to) {
5086 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
5087 S++;
5089 limit = nonempty ? NaN : huge (limit);
5090 lab:
5091 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
5092 3) NaNs need to be supported, but it is known at compile time or cheaply
5093 at runtime whether array is nonempty or not, rank 1:
5094 limit = Infinity;
5095 S = from;
5096 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
5097 limit = (from <= to) ? NaN : huge (limit);
5098 lab:
5099 while (S <= to) { limit = min (a[S], limit); S++; }
5100 4) Array mask is used and NaNs need to be supported, rank > 1:
5101 limit = Infinity;
5102 nonempty = false;
5103 fast = false;
5104 S1 = from1;
5105 while (S1 <= to1) {
5106 S2 = from2;
5107 while (S2 <= to2) {
5108 if (mask[S1][S2]) {
5109 if (fast) limit = min (a[S1][S2], limit);
5110 else {
5111 nonempty = true;
5112 if (a[S1][S2] <= limit) {
5113 limit = a[S1][S2];
5114 fast = true;
5118 S2++;
5120 S1++;
5122 if (!fast)
5123 limit = nonempty ? NaN : huge (limit);
5124 5) NaNs need to be supported, but it is known at compile time or cheaply
5125 at runtime whether array is nonempty or not, rank > 1:
5126 limit = Infinity;
5127 fast = false;
5128 S1 = from1;
5129 while (S1 <= to1) {
5130 S2 = from2;
5131 while (S2 <= to2) {
5132 if (fast) limit = min (a[S1][S2], limit);
5133 else {
5134 if (a[S1][S2] <= limit) {
5135 limit = a[S1][S2];
5136 fast = true;
5139 S2++;
5141 S1++;
5143 if (!fast)
5144 limit = (nonempty_array) ? NaN : huge (limit);
5145 6) NaNs aren't supported, but infinities are. Array mask is used:
5146 limit = Infinity;
5147 nonempty = false;
5148 S = from;
5149 while (S <= to) {
5150 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
5151 S++;
5153 limit = nonempty ? limit : huge (limit);
5154 7) Same without array mask:
5155 limit = Infinity;
5156 S = from;
5157 while (S <= to) { limit = min (a[S], limit); S++; }
5158 limit = (from <= to) ? limit : huge (limit);
5159 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
5160 limit = huge (limit);
5161 S = from;
5162 while (S <= to) { limit = min (a[S], limit); S++); }
5164 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
5165 with array mask instead).
5166 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
5167 setting limit = huge (limit); in the else branch. */
5169 static void
5170 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
5172 tree limit;
5173 tree type;
5174 tree tmp;
5175 tree ifbody;
5176 tree nonempty;
5177 tree nonempty_var;
5178 tree lab;
5179 tree fast;
5180 tree huge_cst = NULL, nan_cst = NULL;
5181 stmtblock_t body;
5182 stmtblock_t block, block2;
5183 gfc_loopinfo loop;
5184 gfc_actual_arglist *actual;
5185 gfc_ss *arrayss;
5186 gfc_ss *maskss;
5187 gfc_se arrayse;
5188 gfc_se maskse;
5189 gfc_expr *arrayexpr;
5190 gfc_expr *maskexpr;
5191 int n;
5193 if (se->ss)
5195 gfc_conv_intrinsic_funcall (se, expr);
5196 return;
5199 actual = expr->value.function.actual;
5200 arrayexpr = actual->expr;
5202 if (arrayexpr->ts.type == BT_CHARACTER)
5204 gfc_actual_arglist *a2, *a3;
5205 a2 = actual->next; /* dim */
5206 a3 = a2->next; /* mask */
5207 if (a2->expr == NULL || expr->rank == 0)
5209 if (a3->expr == NULL)
5210 actual->next = NULL;
5211 else
5213 actual->next = a3;
5214 a2->next = NULL;
5216 gfc_free_actual_arglist (a2);
5218 else
5219 if (a3->expr == NULL)
5221 a2->next = NULL;
5222 gfc_free_actual_arglist (a3);
5224 gfc_conv_intrinsic_funcall (se, expr);
5225 return;
5227 type = gfc_typenode_for_spec (&expr->ts);
5228 /* Initialize the result. */
5229 limit = gfc_create_var (type, "limit");
5230 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
5231 switch (expr->ts.type)
5233 case BT_REAL:
5234 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
5235 expr->ts.kind, 0);
5236 if (HONOR_INFINITIES (DECL_MODE (limit)))
5238 REAL_VALUE_TYPE real;
5239 real_inf (&real);
5240 tmp = build_real (type, real);
5242 else
5243 tmp = huge_cst;
5244 if (HONOR_NANS (DECL_MODE (limit)))
5245 nan_cst = gfc_build_nan (type, "");
5246 break;
5248 case BT_INTEGER:
5249 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
5250 break;
5252 default:
5253 gcc_unreachable ();
5256 /* We start with the most negative possible value for MAXVAL, and the most
5257 positive possible value for MINVAL. The most negative possible value is
5258 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5259 possible value is HUGE in both cases. */
5260 if (op == GT_EXPR)
5262 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
5263 if (huge_cst)
5264 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
5265 TREE_TYPE (huge_cst), huge_cst);
5268 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
5269 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
5270 tmp, build_int_cst (type, 1));
5272 gfc_add_modify (&se->pre, limit, tmp);
5274 /* Walk the arguments. */
5275 arrayss = gfc_walk_expr (arrayexpr);
5276 gcc_assert (arrayss != gfc_ss_terminator);
5278 actual = actual->next->next;
5279 gcc_assert (actual);
5280 maskexpr = actual->expr;
5281 nonempty = NULL;
5282 if (maskexpr && maskexpr->rank != 0)
5284 maskss = gfc_walk_expr (maskexpr);
5285 gcc_assert (maskss != gfc_ss_terminator);
5287 else
5289 mpz_t asize;
5290 if (gfc_array_size (arrayexpr, &asize))
5292 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
5293 mpz_clear (asize);
5294 nonempty = fold_build2_loc (input_location, GT_EXPR,
5295 logical_type_node, nonempty,
5296 gfc_index_zero_node);
5298 maskss = NULL;
5301 /* Initialize the scalarizer. */
5302 gfc_init_loopinfo (&loop);
5303 gfc_add_ss_to_loop (&loop, arrayss);
5304 if (maskss)
5305 gfc_add_ss_to_loop (&loop, maskss);
5307 /* Initialize the loop. */
5308 gfc_conv_ss_startstride (&loop);
5310 /* The code generated can have more than one loop in sequence (see the
5311 comment at the function header). This doesn't work well with the
5312 scalarizer, which changes arrays' offset when the scalarization loops
5313 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
5314 are currently inlined in the scalar case only. As there is no dependency
5315 to care about in that case, there is no temporary, so that we can use the
5316 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
5317 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
5318 gfc_trans_scalarized_loop_boundary even later to restore offset.
5319 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
5320 should eventually go away. We could either create two loops properly,
5321 or find another way to save/restore the array offsets between the two
5322 loops (without conflicting with temporary management), or use a single
5323 loop minmaxval implementation. See PR 31067. */
5324 loop.temp_dim = loop.dimen;
5325 gfc_conv_loop_setup (&loop, &expr->where);
5327 if (nonempty == NULL && maskss == NULL
5328 && loop.dimen == 1 && loop.from[0] && loop.to[0])
5329 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
5330 loop.from[0], loop.to[0]);
5331 nonempty_var = NULL;
5332 if (nonempty == NULL
5333 && (HONOR_INFINITIES (DECL_MODE (limit))
5334 || HONOR_NANS (DECL_MODE (limit))))
5336 nonempty_var = gfc_create_var (logical_type_node, "nonempty");
5337 gfc_add_modify (&se->pre, nonempty_var, logical_false_node);
5338 nonempty = nonempty_var;
5340 lab = NULL;
5341 fast = NULL;
5342 if (HONOR_NANS (DECL_MODE (limit)))
5344 if (loop.dimen == 1)
5346 lab = gfc_build_label_decl (NULL_TREE);
5347 TREE_USED (lab) = 1;
5349 else
5351 fast = gfc_create_var (logical_type_node, "fast");
5352 gfc_add_modify (&se->pre, fast, logical_false_node);
5356 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
5357 if (maskss)
5358 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
5359 /* Generate the loop body. */
5360 gfc_start_scalarized_body (&loop, &body);
5362 /* If we have a mask, only add this element if the mask is set. */
5363 if (maskss)
5365 gfc_init_se (&maskse, NULL);
5366 gfc_copy_loopinfo_to_se (&maskse, &loop);
5367 maskse.ss = maskss;
5368 gfc_conv_expr_val (&maskse, maskexpr);
5369 gfc_add_block_to_block (&body, &maskse.pre);
5371 gfc_start_block (&block);
5373 else
5374 gfc_init_block (&block);
5376 /* Compare with the current limit. */
5377 gfc_init_se (&arrayse, NULL);
5378 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5379 arrayse.ss = arrayss;
5380 gfc_conv_expr_val (&arrayse, arrayexpr);
5381 gfc_add_block_to_block (&block, &arrayse.pre);
5383 gfc_init_block (&block2);
5385 if (nonempty_var)
5386 gfc_add_modify (&block2, nonempty_var, logical_true_node);
5388 if (HONOR_NANS (DECL_MODE (limit)))
5390 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5391 logical_type_node, arrayse.expr, limit);
5392 if (lab)
5393 ifbody = build1_v (GOTO_EXPR, lab);
5394 else
5396 stmtblock_t ifblock;
5398 gfc_init_block (&ifblock);
5399 gfc_add_modify (&ifblock, limit, arrayse.expr);
5400 gfc_add_modify (&ifblock, fast, logical_true_node);
5401 ifbody = gfc_finish_block (&ifblock);
5403 tmp = build3_v (COND_EXPR, tmp, ifbody,
5404 build_empty_stmt (input_location));
5405 gfc_add_expr_to_block (&block2, tmp);
5407 else
5409 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5410 signed zeros. */
5411 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5413 tmp = fold_build2_loc (input_location, op, logical_type_node,
5414 arrayse.expr, limit);
5415 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5416 tmp = build3_v (COND_EXPR, tmp, ifbody,
5417 build_empty_stmt (input_location));
5418 gfc_add_expr_to_block (&block2, tmp);
5420 else
5422 tmp = fold_build2_loc (input_location,
5423 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5424 type, arrayse.expr, limit);
5425 gfc_add_modify (&block2, limit, tmp);
5429 if (fast)
5431 tree elsebody = gfc_finish_block (&block2);
5433 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5434 signed zeros. */
5435 if (HONOR_NANS (DECL_MODE (limit))
5436 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5438 tmp = fold_build2_loc (input_location, op, logical_type_node,
5439 arrayse.expr, limit);
5440 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5441 ifbody = build3_v (COND_EXPR, tmp, ifbody,
5442 build_empty_stmt (input_location));
5444 else
5446 tmp = fold_build2_loc (input_location,
5447 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5448 type, arrayse.expr, limit);
5449 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5451 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
5452 gfc_add_expr_to_block (&block, tmp);
5454 else
5455 gfc_add_block_to_block (&block, &block2);
5457 gfc_add_block_to_block (&block, &arrayse.post);
5459 tmp = gfc_finish_block (&block);
5460 if (maskss)
5461 /* We enclose the above in if (mask) {...}. */
5462 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5463 build_empty_stmt (input_location));
5464 gfc_add_expr_to_block (&body, tmp);
5466 if (lab)
5468 gfc_trans_scalarized_loop_boundary (&loop, &body);
5470 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5471 nan_cst, huge_cst);
5472 gfc_add_modify (&loop.code[0], limit, tmp);
5473 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
5475 /* If we have a mask, only add this element if the mask is set. */
5476 if (maskss)
5478 gfc_init_se (&maskse, NULL);
5479 gfc_copy_loopinfo_to_se (&maskse, &loop);
5480 maskse.ss = maskss;
5481 gfc_conv_expr_val (&maskse, maskexpr);
5482 gfc_add_block_to_block (&body, &maskse.pre);
5484 gfc_start_block (&block);
5486 else
5487 gfc_init_block (&block);
5489 /* Compare with the current limit. */
5490 gfc_init_se (&arrayse, NULL);
5491 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5492 arrayse.ss = arrayss;
5493 gfc_conv_expr_val (&arrayse, arrayexpr);
5494 gfc_add_block_to_block (&block, &arrayse.pre);
5496 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5497 signed zeros. */
5498 if (HONOR_NANS (DECL_MODE (limit))
5499 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5501 tmp = fold_build2_loc (input_location, op, logical_type_node,
5502 arrayse.expr, limit);
5503 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5504 tmp = build3_v (COND_EXPR, tmp, ifbody,
5505 build_empty_stmt (input_location));
5506 gfc_add_expr_to_block (&block, tmp);
5508 else
5510 tmp = fold_build2_loc (input_location,
5511 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5512 type, arrayse.expr, limit);
5513 gfc_add_modify (&block, limit, tmp);
5516 gfc_add_block_to_block (&block, &arrayse.post);
5518 tmp = gfc_finish_block (&block);
5519 if (maskss)
5520 /* We enclose the above in if (mask) {...}. */
5521 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5522 build_empty_stmt (input_location));
5523 gfc_add_expr_to_block (&body, tmp);
5524 /* Avoid initializing loopvar[0] again, it should be left where
5525 it finished by the first loop. */
5526 loop.from[0] = loop.loopvar[0];
5528 gfc_trans_scalarizing_loops (&loop, &body);
5530 if (fast)
5532 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5533 nan_cst, huge_cst);
5534 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5535 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
5536 ifbody);
5537 gfc_add_expr_to_block (&loop.pre, tmp);
5539 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
5541 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
5542 huge_cst);
5543 gfc_add_modify (&loop.pre, limit, tmp);
5546 /* For a scalar mask, enclose the loop in an if statement. */
5547 if (maskexpr && maskss == NULL)
5549 tree else_stmt;
5551 gfc_init_se (&maskse, NULL);
5552 gfc_conv_expr_val (&maskse, maskexpr);
5553 gfc_init_block (&block);
5554 gfc_add_block_to_block (&block, &loop.pre);
5555 gfc_add_block_to_block (&block, &loop.post);
5556 tmp = gfc_finish_block (&block);
5558 if (HONOR_INFINITIES (DECL_MODE (limit)))
5559 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
5560 else
5561 else_stmt = build_empty_stmt (input_location);
5562 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
5563 gfc_add_expr_to_block (&block, tmp);
5564 gfc_add_block_to_block (&se->pre, &block);
5566 else
5568 gfc_add_block_to_block (&se->pre, &loop.pre);
5569 gfc_add_block_to_block (&se->pre, &loop.post);
5572 gfc_cleanup_loop (&loop);
5574 se->expr = limit;
5577 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
5578 static void
5579 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
5581 tree args[2];
5582 tree type;
5583 tree tmp;
5585 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5586 type = TREE_TYPE (args[0]);
5588 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5589 build_int_cst (type, 1), args[1]);
5590 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
5591 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
5592 build_int_cst (type, 0));
5593 type = gfc_typenode_for_spec (&expr->ts);
5594 se->expr = convert (type, tmp);
5598 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
5599 static void
5600 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
5602 tree args[2];
5604 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5606 /* Convert both arguments to the unsigned type of the same size. */
5607 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
5608 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
5610 /* If they have unequal type size, convert to the larger one. */
5611 if (TYPE_PRECISION (TREE_TYPE (args[0]))
5612 > TYPE_PRECISION (TREE_TYPE (args[1])))
5613 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
5614 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
5615 > TYPE_PRECISION (TREE_TYPE (args[0])))
5616 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
5618 /* Now, we compare them. */
5619 se->expr = fold_build2_loc (input_location, op, logical_type_node,
5620 args[0], args[1]);
5624 /* Generate code to perform the specified operation. */
5625 static void
5626 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
5628 tree args[2];
5630 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5631 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
5632 args[0], args[1]);
5635 /* Bitwise not. */
5636 static void
5637 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
5639 tree arg;
5641 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5642 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
5643 TREE_TYPE (arg), arg);
5646 /* Set or clear a single bit. */
5647 static void
5648 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
5650 tree args[2];
5651 tree type;
5652 tree tmp;
5653 enum tree_code op;
5655 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5656 type = TREE_TYPE (args[0]);
5658 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5659 build_int_cst (type, 1), args[1]);
5660 if (set)
5661 op = BIT_IOR_EXPR;
5662 else
5664 op = BIT_AND_EXPR;
5665 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
5667 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
5670 /* Extract a sequence of bits.
5671 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
5672 static void
5673 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
5675 tree args[3];
5676 tree type;
5677 tree tmp;
5678 tree mask;
5680 gfc_conv_intrinsic_function_args (se, expr, args, 3);
5681 type = TREE_TYPE (args[0]);
5683 mask = build_int_cst (type, -1);
5684 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
5685 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
5687 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
5689 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
5692 static void
5693 gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
5695 gfc_actual_arglist *s, *k;
5696 gfc_expr *e;
5698 /* Remove the KIND argument, if present. */
5699 s = expr->value.function.actual;
5700 k = s->next;
5701 e = k->expr;
5702 gfc_free_expr (e);
5703 k->expr = NULL;
5705 gfc_conv_intrinsic_funcall (se, expr);
5708 static void
5709 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
5710 bool arithmetic)
5712 tree args[2], type, num_bits, cond;
5714 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5716 args[0] = gfc_evaluate_now (args[0], &se->pre);
5717 args[1] = gfc_evaluate_now (args[1], &se->pre);
5718 type = TREE_TYPE (args[0]);
5720 if (!arithmetic)
5721 args[0] = fold_convert (unsigned_type_for (type), args[0]);
5722 else
5723 gcc_assert (right_shift);
5725 se->expr = fold_build2_loc (input_location,
5726 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
5727 TREE_TYPE (args[0]), args[0], args[1]);
5729 if (!arithmetic)
5730 se->expr = fold_convert (type, se->expr);
5732 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5733 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5734 special case. */
5735 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
5736 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
5737 args[1], num_bits);
5739 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5740 build_int_cst (type, 0), se->expr);
5743 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
5745 : ((shift >= 0) ? i << shift : i >> -shift)
5746 where all shifts are logical shifts. */
5747 static void
5748 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
5750 tree args[2];
5751 tree type;
5752 tree utype;
5753 tree tmp;
5754 tree width;
5755 tree num_bits;
5756 tree cond;
5757 tree lshift;
5758 tree rshift;
5760 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5762 args[0] = gfc_evaluate_now (args[0], &se->pre);
5763 args[1] = gfc_evaluate_now (args[1], &se->pre);
5765 type = TREE_TYPE (args[0]);
5766 utype = unsigned_type_for (type);
5768 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
5769 args[1]);
5771 /* Left shift if positive. */
5772 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
5774 /* Right shift if negative.
5775 We convert to an unsigned type because we want a logical shift.
5776 The standard doesn't define the case of shifting negative
5777 numbers, and we try to be compatible with other compilers, most
5778 notably g77, here. */
5779 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
5780 utype, convert (utype, args[0]), width));
5782 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[1],
5783 build_int_cst (TREE_TYPE (args[1]), 0));
5784 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
5786 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5787 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5788 special case. */
5789 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
5790 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, width,
5791 num_bits);
5792 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5793 build_int_cst (type, 0), tmp);
5797 /* Circular shift. AKA rotate or barrel shift. */
5799 static void
5800 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
5802 tree *args;
5803 tree type;
5804 tree tmp;
5805 tree lrot;
5806 tree rrot;
5807 tree zero;
5808 unsigned int num_args;
5810 num_args = gfc_intrinsic_argument_list_length (expr);
5811 args = XALLOCAVEC (tree, num_args);
5813 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
5815 if (num_args == 3)
5817 /* Use a library function for the 3 parameter version. */
5818 tree int4type = gfc_get_int_type (4);
5820 type = TREE_TYPE (args[0]);
5821 /* We convert the first argument to at least 4 bytes, and
5822 convert back afterwards. This removes the need for library
5823 functions for all argument sizes, and function will be
5824 aligned to at least 32 bits, so there's no loss. */
5825 if (expr->ts.kind < 4)
5826 args[0] = convert (int4type, args[0]);
5828 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
5829 need loads of library functions. They cannot have values >
5830 BIT_SIZE (I) so the conversion is safe. */
5831 args[1] = convert (int4type, args[1]);
5832 args[2] = convert (int4type, args[2]);
5834 switch (expr->ts.kind)
5836 case 1:
5837 case 2:
5838 case 4:
5839 tmp = gfor_fndecl_math_ishftc4;
5840 break;
5841 case 8:
5842 tmp = gfor_fndecl_math_ishftc8;
5843 break;
5844 case 16:
5845 tmp = gfor_fndecl_math_ishftc16;
5846 break;
5847 default:
5848 gcc_unreachable ();
5850 se->expr = build_call_expr_loc (input_location,
5851 tmp, 3, args[0], args[1], args[2]);
5852 /* Convert the result back to the original type, if we extended
5853 the first argument's width above. */
5854 if (expr->ts.kind < 4)
5855 se->expr = convert (type, se->expr);
5857 return;
5859 type = TREE_TYPE (args[0]);
5861 /* Evaluate arguments only once. */
5862 args[0] = gfc_evaluate_now (args[0], &se->pre);
5863 args[1] = gfc_evaluate_now (args[1], &se->pre);
5865 /* Rotate left if positive. */
5866 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
5868 /* Rotate right if negative. */
5869 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
5870 args[1]);
5871 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
5873 zero = build_int_cst (TREE_TYPE (args[1]), 0);
5874 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, args[1],
5875 zero);
5876 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
5878 /* Do nothing if shift == 0. */
5879 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, args[1],
5880 zero);
5881 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
5882 rrot);
5886 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
5887 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
5889 The conditional expression is necessary because the result of LEADZ(0)
5890 is defined, but the result of __builtin_clz(0) is undefined for most
5891 targets.
5893 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
5894 difference in bit size between the argument of LEADZ and the C int. */
5896 static void
5897 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
5899 tree arg;
5900 tree arg_type;
5901 tree cond;
5902 tree result_type;
5903 tree leadz;
5904 tree bit_size;
5905 tree tmp;
5906 tree func;
5907 int s, argsize;
5909 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5910 argsize = TYPE_PRECISION (TREE_TYPE (arg));
5912 /* Which variant of __builtin_clz* should we call? */
5913 if (argsize <= INT_TYPE_SIZE)
5915 arg_type = unsigned_type_node;
5916 func = builtin_decl_explicit (BUILT_IN_CLZ);
5918 else if (argsize <= LONG_TYPE_SIZE)
5920 arg_type = long_unsigned_type_node;
5921 func = builtin_decl_explicit (BUILT_IN_CLZL);
5923 else if (argsize <= LONG_LONG_TYPE_SIZE)
5925 arg_type = long_long_unsigned_type_node;
5926 func = builtin_decl_explicit (BUILT_IN_CLZLL);
5928 else
5930 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
5931 arg_type = gfc_build_uint_type (argsize);
5932 func = NULL_TREE;
5935 /* Convert the actual argument twice: first, to the unsigned type of the
5936 same size; then, to the proper argument type for the built-in
5937 function. But the return type is of the default INTEGER kind. */
5938 arg = fold_convert (gfc_build_uint_type (argsize), arg);
5939 arg = fold_convert (arg_type, arg);
5940 arg = gfc_evaluate_now (arg, &se->pre);
5941 result_type = gfc_get_int_type (gfc_default_integer_kind);
5943 /* Compute LEADZ for the case i .ne. 0. */
5944 if (func)
5946 s = TYPE_PRECISION (arg_type) - argsize;
5947 tmp = fold_convert (result_type,
5948 build_call_expr_loc (input_location, func,
5949 1, arg));
5950 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
5951 tmp, build_int_cst (result_type, s));
5953 else
5955 /* We end up here if the argument type is larger than 'long long'.
5956 We generate this code:
5958 if (x & (ULL_MAX << ULL_SIZE) != 0)
5959 return clzll ((unsigned long long) (x >> ULLSIZE));
5960 else
5961 return ULL_SIZE + clzll ((unsigned long long) x);
5962 where ULL_MAX is the largest value that a ULL_MAX can hold
5963 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
5964 is the bit-size of the long long type (64 in this example). */
5965 tree ullsize, ullmax, tmp1, tmp2, btmp;
5967 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
5968 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
5969 long_long_unsigned_type_node,
5970 build_int_cst (long_long_unsigned_type_node,
5971 0));
5973 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
5974 fold_convert (arg_type, ullmax), ullsize);
5975 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
5976 arg, cond);
5977 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
5978 cond, build_int_cst (arg_type, 0));
5980 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
5981 arg, ullsize);
5982 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
5983 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
5984 tmp1 = fold_convert (result_type,
5985 build_call_expr_loc (input_location, btmp, 1, tmp1));
5987 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
5988 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
5989 tmp2 = fold_convert (result_type,
5990 build_call_expr_loc (input_location, btmp, 1, tmp2));
5991 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
5992 tmp2, ullsize);
5994 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
5995 cond, tmp1, tmp2);
5998 /* Build BIT_SIZE. */
5999 bit_size = build_int_cst (result_type, argsize);
6001 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6002 arg, build_int_cst (arg_type, 0));
6003 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
6004 bit_size, leadz);
6008 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
6010 The conditional expression is necessary because the result of TRAILZ(0)
6011 is defined, but the result of __builtin_ctz(0) is undefined for most
6012 targets. */
6014 static void
6015 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
6017 tree arg;
6018 tree arg_type;
6019 tree cond;
6020 tree result_type;
6021 tree trailz;
6022 tree bit_size;
6023 tree func;
6024 int argsize;
6026 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6027 argsize = TYPE_PRECISION (TREE_TYPE (arg));
6029 /* Which variant of __builtin_ctz* should we call? */
6030 if (argsize <= INT_TYPE_SIZE)
6032 arg_type = unsigned_type_node;
6033 func = builtin_decl_explicit (BUILT_IN_CTZ);
6035 else if (argsize <= LONG_TYPE_SIZE)
6037 arg_type = long_unsigned_type_node;
6038 func = builtin_decl_explicit (BUILT_IN_CTZL);
6040 else if (argsize <= LONG_LONG_TYPE_SIZE)
6042 arg_type = long_long_unsigned_type_node;
6043 func = builtin_decl_explicit (BUILT_IN_CTZLL);
6045 else
6047 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6048 arg_type = gfc_build_uint_type (argsize);
6049 func = NULL_TREE;
6052 /* Convert the actual argument twice: first, to the unsigned type of the
6053 same size; then, to the proper argument type for the built-in
6054 function. But the return type is of the default INTEGER kind. */
6055 arg = fold_convert (gfc_build_uint_type (argsize), arg);
6056 arg = fold_convert (arg_type, arg);
6057 arg = gfc_evaluate_now (arg, &se->pre);
6058 result_type = gfc_get_int_type (gfc_default_integer_kind);
6060 /* Compute TRAILZ for the case i .ne. 0. */
6061 if (func)
6062 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
6063 func, 1, arg));
6064 else
6066 /* We end up here if the argument type is larger than 'long long'.
6067 We generate this code:
6069 if ((x & ULL_MAX) == 0)
6070 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
6071 else
6072 return ctzll ((unsigned long long) x);
6074 where ULL_MAX is the largest value that a ULL_MAX can hold
6075 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
6076 is the bit-size of the long long type (64 in this example). */
6077 tree ullsize, ullmax, tmp1, tmp2, btmp;
6079 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
6080 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
6081 long_long_unsigned_type_node,
6082 build_int_cst (long_long_unsigned_type_node, 0));
6084 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
6085 fold_convert (arg_type, ullmax));
6086 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, cond,
6087 build_int_cst (arg_type, 0));
6089 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
6090 arg, ullsize);
6091 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
6092 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
6093 tmp1 = fold_convert (result_type,
6094 build_call_expr_loc (input_location, btmp, 1, tmp1));
6095 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6096 tmp1, ullsize);
6098 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
6099 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
6100 tmp2 = fold_convert (result_type,
6101 build_call_expr_loc (input_location, btmp, 1, tmp2));
6103 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
6104 cond, tmp1, tmp2);
6107 /* Build BIT_SIZE. */
6108 bit_size = build_int_cst (result_type, argsize);
6110 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6111 arg, build_int_cst (arg_type, 0));
6112 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
6113 bit_size, trailz);
6116 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
6117 for types larger than "long long", we call the long long built-in for
6118 the lower and higher bits and combine the result. */
6120 static void
6121 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
6123 tree arg;
6124 tree arg_type;
6125 tree result_type;
6126 tree func;
6127 int argsize;
6129 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6130 argsize = TYPE_PRECISION (TREE_TYPE (arg));
6131 result_type = gfc_get_int_type (gfc_default_integer_kind);
6133 /* Which variant of the builtin should we call? */
6134 if (argsize <= INT_TYPE_SIZE)
6136 arg_type = unsigned_type_node;
6137 func = builtin_decl_explicit (parity
6138 ? BUILT_IN_PARITY
6139 : BUILT_IN_POPCOUNT);
6141 else if (argsize <= LONG_TYPE_SIZE)
6143 arg_type = long_unsigned_type_node;
6144 func = builtin_decl_explicit (parity
6145 ? BUILT_IN_PARITYL
6146 : BUILT_IN_POPCOUNTL);
6148 else if (argsize <= LONG_LONG_TYPE_SIZE)
6150 arg_type = long_long_unsigned_type_node;
6151 func = builtin_decl_explicit (parity
6152 ? BUILT_IN_PARITYLL
6153 : BUILT_IN_POPCOUNTLL);
6155 else
6157 /* Our argument type is larger than 'long long', which mean none
6158 of the POPCOUNT builtins covers it. We thus call the 'long long'
6159 variant multiple times, and add the results. */
6160 tree utype, arg2, call1, call2;
6162 /* For now, we only cover the case where argsize is twice as large
6163 as 'long long'. */
6164 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
6166 func = builtin_decl_explicit (parity
6167 ? BUILT_IN_PARITYLL
6168 : BUILT_IN_POPCOUNTLL);
6170 /* Convert it to an integer, and store into a variable. */
6171 utype = gfc_build_uint_type (argsize);
6172 arg = fold_convert (utype, arg);
6173 arg = gfc_evaluate_now (arg, &se->pre);
6175 /* Call the builtin twice. */
6176 call1 = build_call_expr_loc (input_location, func, 1,
6177 fold_convert (long_long_unsigned_type_node,
6178 arg));
6180 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
6181 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
6182 call2 = build_call_expr_loc (input_location, func, 1,
6183 fold_convert (long_long_unsigned_type_node,
6184 arg2));
6186 /* Combine the results. */
6187 if (parity)
6188 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
6189 call1, call2);
6190 else
6191 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
6192 call1, call2);
6194 return;
6197 /* Convert the actual argument twice: first, to the unsigned type of the
6198 same size; then, to the proper argument type for the built-in
6199 function. */
6200 arg = fold_convert (gfc_build_uint_type (argsize), arg);
6201 arg = fold_convert (arg_type, arg);
6203 se->expr = fold_convert (result_type,
6204 build_call_expr_loc (input_location, func, 1, arg));
6208 /* Process an intrinsic with unspecified argument-types that has an optional
6209 argument (which could be of type character), e.g. EOSHIFT. For those, we
6210 need to append the string length of the optional argument if it is not
6211 present and the type is really character.
6212 primary specifies the position (starting at 1) of the non-optional argument
6213 specifying the type and optional gives the position of the optional
6214 argument in the arglist. */
6216 static void
6217 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
6218 unsigned primary, unsigned optional)
6220 gfc_actual_arglist* prim_arg;
6221 gfc_actual_arglist* opt_arg;
6222 unsigned cur_pos;
6223 gfc_actual_arglist* arg;
6224 gfc_symbol* sym;
6225 vec<tree, va_gc> *append_args;
6227 /* Find the two arguments given as position. */
6228 cur_pos = 0;
6229 prim_arg = NULL;
6230 opt_arg = NULL;
6231 for (arg = expr->value.function.actual; arg; arg = arg->next)
6233 ++cur_pos;
6235 if (cur_pos == primary)
6236 prim_arg = arg;
6237 if (cur_pos == optional)
6238 opt_arg = arg;
6240 if (cur_pos >= primary && cur_pos >= optional)
6241 break;
6243 gcc_assert (prim_arg);
6244 gcc_assert (prim_arg->expr);
6245 gcc_assert (opt_arg);
6247 /* If we do have type CHARACTER and the optional argument is really absent,
6248 append a dummy 0 as string length. */
6249 append_args = NULL;
6250 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
6252 tree dummy;
6254 dummy = build_int_cst (gfc_charlen_type_node, 0);
6255 vec_alloc (append_args, 1);
6256 append_args->quick_push (dummy);
6259 /* Build the call itself. */
6260 gcc_assert (!se->ignore_optional);
6261 sym = gfc_get_symbol_for_expr (expr, false);
6262 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
6263 append_args);
6264 gfc_free_symbol (sym);
6267 /* The length of a character string. */
6268 static void
6269 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
6271 tree len;
6272 tree type;
6273 tree decl;
6274 gfc_symbol *sym;
6275 gfc_se argse;
6276 gfc_expr *arg;
6278 gcc_assert (!se->ss);
6280 arg = expr->value.function.actual->expr;
6282 type = gfc_typenode_for_spec (&expr->ts);
6283 switch (arg->expr_type)
6285 case EXPR_CONSTANT:
6286 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
6287 break;
6289 case EXPR_ARRAY:
6290 /* Obtain the string length from the function used by
6291 trans-array.c(gfc_trans_array_constructor). */
6292 len = NULL_TREE;
6293 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
6294 break;
6296 case EXPR_VARIABLE:
6297 if (arg->ref == NULL
6298 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
6300 /* This doesn't catch all cases.
6301 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
6302 and the surrounding thread. */
6303 sym = arg->symtree->n.sym;
6304 decl = gfc_get_symbol_decl (sym);
6305 if (decl == current_function_decl && sym->attr.function
6306 && (sym->result == sym))
6307 decl = gfc_get_fake_result_decl (sym, 0);
6309 len = sym->ts.u.cl->backend_decl;
6310 gcc_assert (len);
6311 break;
6314 /* Fall through. */
6316 default:
6317 /* Anybody stupid enough to do this deserves inefficient code. */
6318 gfc_init_se (&argse, se);
6319 if (arg->rank == 0)
6320 gfc_conv_expr (&argse, arg);
6321 else
6322 gfc_conv_expr_descriptor (&argse, arg);
6323 gfc_add_block_to_block (&se->pre, &argse.pre);
6324 gfc_add_block_to_block (&se->post, &argse.post);
6325 len = argse.string_length;
6326 break;
6328 se->expr = convert (type, len);
6331 /* The length of a character string not including trailing blanks. */
6332 static void
6333 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
6335 int kind = expr->value.function.actual->expr->ts.kind;
6336 tree args[2], type, fndecl;
6338 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6339 type = gfc_typenode_for_spec (&expr->ts);
6341 if (kind == 1)
6342 fndecl = gfor_fndecl_string_len_trim;
6343 else if (kind == 4)
6344 fndecl = gfor_fndecl_string_len_trim_char4;
6345 else
6346 gcc_unreachable ();
6348 se->expr = build_call_expr_loc (input_location,
6349 fndecl, 2, args[0], args[1]);
6350 se->expr = convert (type, se->expr);
6354 /* Returns the starting position of a substring within a string. */
6356 static void
6357 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
6358 tree function)
6360 tree logical4_type_node = gfc_get_logical_type (4);
6361 tree type;
6362 tree fndecl;
6363 tree *args;
6364 unsigned int num_args;
6366 args = XALLOCAVEC (tree, 5);
6368 /* Get number of arguments; characters count double due to the
6369 string length argument. Kind= is not passed to the library
6370 and thus ignored. */
6371 if (expr->value.function.actual->next->next->expr == NULL)
6372 num_args = 4;
6373 else
6374 num_args = 5;
6376 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6377 type = gfc_typenode_for_spec (&expr->ts);
6379 if (num_args == 4)
6380 args[4] = build_int_cst (logical4_type_node, 0);
6381 else
6382 args[4] = convert (logical4_type_node, args[4]);
6384 fndecl = build_addr (function);
6385 se->expr = build_call_array_loc (input_location,
6386 TREE_TYPE (TREE_TYPE (function)), fndecl,
6387 5, args);
6388 se->expr = convert (type, se->expr);
6392 /* The ascii value for a single character. */
6393 static void
6394 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
6396 tree args[3], type, pchartype;
6397 int nargs;
6399 nargs = gfc_intrinsic_argument_list_length (expr);
6400 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6401 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
6402 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
6403 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
6404 type = gfc_typenode_for_spec (&expr->ts);
6406 se->expr = build_fold_indirect_ref_loc (input_location,
6407 args[1]);
6408 se->expr = convert (type, se->expr);
6412 /* Intrinsic ISNAN calls __builtin_isnan. */
6414 static void
6415 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
6417 tree arg;
6419 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6420 se->expr = build_call_expr_loc (input_location,
6421 builtin_decl_explicit (BUILT_IN_ISNAN),
6422 1, arg);
6423 STRIP_TYPE_NOPS (se->expr);
6424 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6428 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
6429 their argument against a constant integer value. */
6431 static void
6432 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
6434 tree arg;
6436 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6437 se->expr = fold_build2_loc (input_location, EQ_EXPR,
6438 gfc_typenode_for_spec (&expr->ts),
6439 arg, build_int_cst (TREE_TYPE (arg), value));
6444 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
6446 static void
6447 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
6449 tree tsource;
6450 tree fsource;
6451 tree mask;
6452 tree type;
6453 tree len, len2;
6454 tree *args;
6455 unsigned int num_args;
6457 num_args = gfc_intrinsic_argument_list_length (expr);
6458 args = XALLOCAVEC (tree, num_args);
6460 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6461 if (expr->ts.type != BT_CHARACTER)
6463 tsource = args[0];
6464 fsource = args[1];
6465 mask = args[2];
6467 else
6469 /* We do the same as in the non-character case, but the argument
6470 list is different because of the string length arguments. We
6471 also have to set the string length for the result. */
6472 len = args[0];
6473 tsource = args[1];
6474 len2 = args[2];
6475 fsource = args[3];
6476 mask = args[4];
6478 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
6479 &se->pre);
6480 se->string_length = len;
6482 type = TREE_TYPE (tsource);
6483 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
6484 fold_convert (type, fsource));
6488 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
6490 static void
6491 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
6493 tree args[3], mask, type;
6495 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6496 mask = gfc_evaluate_now (args[2], &se->pre);
6498 type = TREE_TYPE (args[0]);
6499 gcc_assert (TREE_TYPE (args[1]) == type);
6500 gcc_assert (TREE_TYPE (mask) == type);
6502 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
6503 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
6504 fold_build1_loc (input_location, BIT_NOT_EXPR,
6505 type, mask));
6506 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
6507 args[0], args[1]);
6511 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
6512 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
6514 static void
6515 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
6517 tree arg, allones, type, utype, res, cond, bitsize;
6518 int i;
6520 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6521 arg = gfc_evaluate_now (arg, &se->pre);
6523 type = gfc_get_int_type (expr->ts.kind);
6524 utype = unsigned_type_for (type);
6526 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
6527 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
6529 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
6530 build_int_cst (utype, 0));
6532 if (left)
6534 /* Left-justified mask. */
6535 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
6536 bitsize, arg);
6537 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6538 fold_convert (utype, res));
6540 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
6541 smaller than type width. */
6542 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
6543 build_int_cst (TREE_TYPE (arg), 0));
6544 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
6545 build_int_cst (utype, 0), res);
6547 else
6549 /* Right-justified mask. */
6550 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6551 fold_convert (utype, arg));
6552 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
6554 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
6555 strictly smaller than type width. */
6556 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6557 arg, bitsize);
6558 res = fold_build3_loc (input_location, COND_EXPR, utype,
6559 cond, allones, res);
6562 se->expr = fold_convert (type, res);
6566 /* FRACTION (s) is translated into:
6567 isfinite (s) ? frexp (s, &dummy_int) : NaN */
6568 static void
6569 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
6571 tree arg, type, tmp, res, frexp, cond;
6573 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6575 type = gfc_typenode_for_spec (&expr->ts);
6576 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6577 arg = gfc_evaluate_now (arg, &se->pre);
6579 cond = build_call_expr_loc (input_location,
6580 builtin_decl_explicit (BUILT_IN_ISFINITE),
6581 1, arg);
6583 tmp = gfc_create_var (integer_type_node, NULL);
6584 res = build_call_expr_loc (input_location, frexp, 2,
6585 fold_convert (type, arg),
6586 gfc_build_addr_expr (NULL_TREE, tmp));
6587 res = fold_convert (type, res);
6589 se->expr = fold_build3_loc (input_location, COND_EXPR, type,
6590 cond, res, gfc_build_nan (type, ""));
6594 /* NEAREST (s, dir) is translated into
6595 tmp = copysign (HUGE_VAL, dir);
6596 return nextafter (s, tmp);
6598 static void
6599 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
6601 tree args[2], type, tmp, nextafter, copysign, huge_val;
6603 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
6604 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
6606 type = gfc_typenode_for_spec (&expr->ts);
6607 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6609 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
6610 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
6611 fold_convert (type, args[1]));
6612 se->expr = build_call_expr_loc (input_location, nextafter, 2,
6613 fold_convert (type, args[0]), tmp);
6614 se->expr = fold_convert (type, se->expr);
6618 /* SPACING (s) is translated into
6619 int e;
6620 if (!isfinite (s))
6621 res = NaN;
6622 else if (s == 0)
6623 res = tiny;
6624 else
6626 frexp (s, &e);
6627 e = e - prec;
6628 e = MAX_EXPR (e, emin);
6629 res = scalbn (1., e);
6631 return res;
6633 where prec is the precision of s, gfc_real_kinds[k].digits,
6634 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
6635 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
6637 static void
6638 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
6640 tree arg, type, prec, emin, tiny, res, e;
6641 tree cond, nan, tmp, frexp, scalbn;
6642 int k;
6643 stmtblock_t block;
6645 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
6646 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
6647 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
6648 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
6650 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6651 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6653 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6654 arg = gfc_evaluate_now (arg, &se->pre);
6656 type = gfc_typenode_for_spec (&expr->ts);
6657 e = gfc_create_var (integer_type_node, NULL);
6658 res = gfc_create_var (type, NULL);
6661 /* Build the block for s /= 0. */
6662 gfc_start_block (&block);
6663 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
6664 gfc_build_addr_expr (NULL_TREE, e));
6665 gfc_add_expr_to_block (&block, tmp);
6667 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
6668 prec);
6669 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
6670 integer_type_node, tmp, emin));
6672 tmp = build_call_expr_loc (input_location, scalbn, 2,
6673 build_real_from_int_cst (type, integer_one_node), e);
6674 gfc_add_modify (&block, res, tmp);
6676 /* Finish by building the IF statement for value zero. */
6677 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
6678 build_real_from_int_cst (type, integer_zero_node));
6679 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
6680 gfc_finish_block (&block));
6682 /* And deal with infinities and NaNs. */
6683 cond = build_call_expr_loc (input_location,
6684 builtin_decl_explicit (BUILT_IN_ISFINITE),
6685 1, arg);
6686 nan = gfc_build_nan (type, "");
6687 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
6689 gfc_add_expr_to_block (&se->pre, tmp);
6690 se->expr = res;
6694 /* RRSPACING (s) is translated into
6695 int e;
6696 real x;
6697 x = fabs (s);
6698 if (isfinite (x))
6700 if (x != 0)
6702 frexp (s, &e);
6703 x = scalbn (x, precision - e);
6706 else
6707 x = NaN;
6708 return x;
6710 where precision is gfc_real_kinds[k].digits. */
6712 static void
6713 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
6715 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
6716 int prec, k;
6717 stmtblock_t block;
6719 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
6720 prec = gfc_real_kinds[k].digits;
6722 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6723 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6724 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
6726 type = gfc_typenode_for_spec (&expr->ts);
6727 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6728 arg = gfc_evaluate_now (arg, &se->pre);
6730 e = gfc_create_var (integer_type_node, NULL);
6731 x = gfc_create_var (type, NULL);
6732 gfc_add_modify (&se->pre, x,
6733 build_call_expr_loc (input_location, fabs, 1, arg));
6736 gfc_start_block (&block);
6737 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
6738 gfc_build_addr_expr (NULL_TREE, e));
6739 gfc_add_expr_to_block (&block, tmp);
6741 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
6742 build_int_cst (integer_type_node, prec), e);
6743 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
6744 gfc_add_modify (&block, x, tmp);
6745 stmt = gfc_finish_block (&block);
6747 /* if (x != 0) */
6748 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, x,
6749 build_real_from_int_cst (type, integer_zero_node));
6750 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
6752 /* And deal with infinities and NaNs. */
6753 cond = build_call_expr_loc (input_location,
6754 builtin_decl_explicit (BUILT_IN_ISFINITE),
6755 1, x);
6756 nan = gfc_build_nan (type, "");
6757 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
6759 gfc_add_expr_to_block (&se->pre, tmp);
6760 se->expr = fold_convert (type, x);
6764 /* SCALE (s, i) is translated into scalbn (s, i). */
6765 static void
6766 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
6768 tree args[2], type, scalbn;
6770 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6772 type = gfc_typenode_for_spec (&expr->ts);
6773 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6774 se->expr = build_call_expr_loc (input_location, scalbn, 2,
6775 fold_convert (type, args[0]),
6776 fold_convert (integer_type_node, args[1]));
6777 se->expr = fold_convert (type, se->expr);
6781 /* SET_EXPONENT (s, i) is translated into
6782 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
6783 static void
6784 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
6786 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
6788 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6789 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6791 type = gfc_typenode_for_spec (&expr->ts);
6792 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6793 args[0] = gfc_evaluate_now (args[0], &se->pre);
6795 tmp = gfc_create_var (integer_type_node, NULL);
6796 tmp = build_call_expr_loc (input_location, frexp, 2,
6797 fold_convert (type, args[0]),
6798 gfc_build_addr_expr (NULL_TREE, tmp));
6799 res = build_call_expr_loc (input_location, scalbn, 2, tmp,
6800 fold_convert (integer_type_node, args[1]));
6801 res = fold_convert (type, res);
6803 /* Call to isfinite */
6804 cond = build_call_expr_loc (input_location,
6805 builtin_decl_explicit (BUILT_IN_ISFINITE),
6806 1, args[0]);
6807 nan = gfc_build_nan (type, "");
6809 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
6810 res, nan);
6814 static void
6815 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
6817 gfc_actual_arglist *actual;
6818 tree arg1;
6819 tree type;
6820 tree fncall0;
6821 tree fncall1;
6822 gfc_se argse;
6824 gfc_init_se (&argse, NULL);
6825 actual = expr->value.function.actual;
6827 if (actual->expr->ts.type == BT_CLASS)
6828 gfc_add_class_array_ref (actual->expr);
6830 argse.data_not_needed = 1;
6831 if (gfc_is_class_array_function (actual->expr))
6833 /* For functions that return a class array conv_expr_descriptor is not
6834 able to get the descriptor right. Therefore this special case. */
6835 gfc_conv_expr_reference (&argse, actual->expr);
6836 argse.expr = gfc_build_addr_expr (NULL_TREE,
6837 gfc_class_data_get (argse.expr));
6839 else
6841 argse.want_pointer = 1;
6842 gfc_conv_expr_descriptor (&argse, actual->expr);
6844 gfc_add_block_to_block (&se->pre, &argse.pre);
6845 gfc_add_block_to_block (&se->post, &argse.post);
6846 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
6848 /* Build the call to size0. */
6849 fncall0 = build_call_expr_loc (input_location,
6850 gfor_fndecl_size0, 1, arg1);
6852 actual = actual->next;
6854 if (actual->expr)
6856 gfc_init_se (&argse, NULL);
6857 gfc_conv_expr_type (&argse, actual->expr,
6858 gfc_array_index_type);
6859 gfc_add_block_to_block (&se->pre, &argse.pre);
6861 /* Unusually, for an intrinsic, size does not exclude
6862 an optional arg2, so we must test for it. */
6863 if (actual->expr->expr_type == EXPR_VARIABLE
6864 && actual->expr->symtree->n.sym->attr.dummy
6865 && actual->expr->symtree->n.sym->attr.optional)
6867 tree tmp;
6868 /* Build the call to size1. */
6869 fncall1 = build_call_expr_loc (input_location,
6870 gfor_fndecl_size1, 2,
6871 arg1, argse.expr);
6873 gfc_init_se (&argse, NULL);
6874 argse.want_pointer = 1;
6875 argse.data_not_needed = 1;
6876 gfc_conv_expr (&argse, actual->expr);
6877 gfc_add_block_to_block (&se->pre, &argse.pre);
6878 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6879 argse.expr, null_pointer_node);
6880 tmp = gfc_evaluate_now (tmp, &se->pre);
6881 se->expr = fold_build3_loc (input_location, COND_EXPR,
6882 pvoid_type_node, tmp, fncall1, fncall0);
6884 else
6886 se->expr = NULL_TREE;
6887 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
6888 gfc_array_index_type,
6889 argse.expr, gfc_index_one_node);
6892 else if (expr->value.function.actual->expr->rank == 1)
6894 argse.expr = gfc_index_zero_node;
6895 se->expr = NULL_TREE;
6897 else
6898 se->expr = fncall0;
6900 if (se->expr == NULL_TREE)
6902 tree ubound, lbound;
6904 arg1 = build_fold_indirect_ref_loc (input_location,
6905 arg1);
6906 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
6907 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
6908 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
6909 gfc_array_index_type, ubound, lbound);
6910 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
6911 gfc_array_index_type,
6912 se->expr, gfc_index_one_node);
6913 se->expr = fold_build2_loc (input_location, MAX_EXPR,
6914 gfc_array_index_type, se->expr,
6915 gfc_index_zero_node);
6918 type = gfc_typenode_for_spec (&expr->ts);
6919 se->expr = convert (type, se->expr);
6923 /* Helper function to compute the size of a character variable,
6924 excluding the terminating null characters. The result has
6925 gfc_array_index_type type. */
6927 tree
6928 size_of_string_in_bytes (int kind, tree string_length)
6930 tree bytesize;
6931 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
6933 bytesize = build_int_cst (gfc_array_index_type,
6934 gfc_character_kinds[i].bit_size / 8);
6936 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6937 bytesize,
6938 fold_convert (gfc_array_index_type, string_length));
6942 static void
6943 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
6945 gfc_expr *arg;
6946 gfc_se argse;
6947 tree source_bytes;
6948 tree tmp;
6949 tree lower;
6950 tree upper;
6951 tree byte_size;
6952 tree field;
6953 int n;
6955 gfc_init_se (&argse, NULL);
6956 arg = expr->value.function.actual->expr;
6958 if (arg->rank || arg->ts.type == BT_ASSUMED)
6959 gfc_conv_expr_descriptor (&argse, arg);
6960 else
6961 gfc_conv_expr_reference (&argse, arg);
6963 if (arg->ts.type == BT_ASSUMED)
6965 /* This only works if an array descriptor has been passed; thus, extract
6966 the size from the descriptor. */
6967 gcc_assert (TYPE_PRECISION (gfc_array_index_type)
6968 == TYPE_PRECISION (size_type_node));
6969 tmp = arg->symtree->n.sym->backend_decl;
6970 tmp = DECL_LANG_SPECIFIC (tmp)
6971 && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
6972 ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
6973 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
6974 tmp = build_fold_indirect_ref_loc (input_location, tmp);
6976 tmp = gfc_conv_descriptor_dtype (tmp);
6977 field = gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
6978 GFC_DTYPE_ELEM_LEN);
6979 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
6980 tmp, field, NULL_TREE);
6982 byte_size = fold_convert (gfc_array_index_type, tmp);
6984 else if (arg->ts.type == BT_CLASS)
6986 /* Conv_expr_descriptor returns a component_ref to _data component of the
6987 class object. The class object may be a non-pointer object, e.g.
6988 located on the stack, or a memory location pointed to, e.g. a
6989 parameter, i.e., an indirect_ref. */
6990 if (arg->rank < 0
6991 || (arg->rank > 0 && !VAR_P (argse.expr)
6992 && ((INDIRECT_REF_P (TREE_OPERAND (argse.expr, 0))
6993 && GFC_DECL_CLASS (TREE_OPERAND (
6994 TREE_OPERAND (argse.expr, 0), 0)))
6995 || GFC_DECL_CLASS (TREE_OPERAND (argse.expr, 0)))))
6996 byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
6997 else if (arg->rank > 0
6998 || (arg->rank == 0
6999 && arg->ref && arg->ref->type == REF_COMPONENT))
7000 /* The scalarizer added an additional temp. To get the class' vptr
7001 one has to look at the original backend_decl. */
7002 byte_size = gfc_class_vtab_size_get (
7003 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
7004 else
7005 byte_size = gfc_class_vtab_size_get (argse.expr);
7007 else
7009 if (arg->ts.type == BT_CHARACTER)
7010 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
7011 else
7013 if (arg->rank == 0)
7014 byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7015 argse.expr));
7016 else
7017 byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
7018 byte_size = fold_convert (gfc_array_index_type,
7019 size_in_bytes (byte_size));
7023 if (arg->rank == 0)
7024 se->expr = byte_size;
7025 else
7027 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
7028 gfc_add_modify (&argse.pre, source_bytes, byte_size);
7030 if (arg->rank == -1)
7032 tree cond, loop_var, exit_label;
7033 stmtblock_t body;
7035 tmp = fold_convert (gfc_array_index_type,
7036 gfc_conv_descriptor_rank (argse.expr));
7037 loop_var = gfc_create_var (gfc_array_index_type, "i");
7038 gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
7039 exit_label = gfc_build_label_decl (NULL_TREE);
7041 /* Create loop:
7042 for (;;)
7044 if (i >= rank)
7045 goto exit;
7046 source_bytes = source_bytes * array.dim[i].extent;
7047 i = i + 1;
7049 exit: */
7050 gfc_start_block (&body);
7051 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
7052 loop_var, tmp);
7053 tmp = build1_v (GOTO_EXPR, exit_label);
7054 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
7055 cond, tmp, build_empty_stmt (input_location));
7056 gfc_add_expr_to_block (&body, tmp);
7058 lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
7059 upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
7060 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
7061 tmp = fold_build2_loc (input_location, MULT_EXPR,
7062 gfc_array_index_type, tmp, source_bytes);
7063 gfc_add_modify (&body, source_bytes, tmp);
7065 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7066 gfc_array_index_type, loop_var,
7067 gfc_index_one_node);
7068 gfc_add_modify_loc (input_location, &body, loop_var, tmp);
7070 tmp = gfc_finish_block (&body);
7072 tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
7073 tmp);
7074 gfc_add_expr_to_block (&argse.pre, tmp);
7076 tmp = build1_v (LABEL_EXPR, exit_label);
7077 gfc_add_expr_to_block (&argse.pre, tmp);
7079 else
7081 /* Obtain the size of the array in bytes. */
7082 for (n = 0; n < arg->rank; n++)
7084 tree idx;
7085 idx = gfc_rank_cst[n];
7086 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
7087 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
7088 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
7089 tmp = fold_build2_loc (input_location, MULT_EXPR,
7090 gfc_array_index_type, tmp, source_bytes);
7091 gfc_add_modify (&argse.pre, source_bytes, tmp);
7094 se->expr = source_bytes;
7097 gfc_add_block_to_block (&se->pre, &argse.pre);
7101 static void
7102 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
7104 gfc_expr *arg;
7105 gfc_se argse;
7106 tree type, result_type, tmp;
7108 arg = expr->value.function.actual->expr;
7110 gfc_init_se (&argse, NULL);
7111 result_type = gfc_get_int_type (expr->ts.kind);
7113 if (arg->rank == 0)
7115 if (arg->ts.type == BT_CLASS)
7117 gfc_add_vptr_component (arg);
7118 gfc_add_size_component (arg);
7119 gfc_conv_expr (&argse, arg);
7120 tmp = fold_convert (result_type, argse.expr);
7121 goto done;
7124 gfc_conv_expr_reference (&argse, arg);
7125 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7126 argse.expr));
7128 else
7130 argse.want_pointer = 0;
7131 gfc_conv_expr_descriptor (&argse, arg);
7132 if (arg->ts.type == BT_CLASS)
7134 if (arg->rank > 0)
7135 tmp = gfc_class_vtab_size_get (
7136 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
7137 else
7138 tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
7139 tmp = fold_convert (result_type, tmp);
7140 goto done;
7142 type = gfc_get_element_type (TREE_TYPE (argse.expr));
7145 /* Obtain the argument's word length. */
7146 if (arg->ts.type == BT_CHARACTER)
7147 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
7148 else
7149 tmp = size_in_bytes (type);
7150 tmp = fold_convert (result_type, tmp);
7152 done:
7153 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
7154 build_int_cst (result_type, BITS_PER_UNIT));
7155 gfc_add_block_to_block (&se->pre, &argse.pre);
7159 /* Intrinsic string comparison functions. */
7161 static void
7162 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
7164 tree args[4];
7166 gfc_conv_intrinsic_function_args (se, expr, args, 4);
7168 se->expr
7169 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
7170 expr->value.function.actual->expr->ts.kind,
7171 op);
7172 se->expr = fold_build2_loc (input_location, op,
7173 gfc_typenode_for_spec (&expr->ts), se->expr,
7174 build_int_cst (TREE_TYPE (se->expr), 0));
7177 /* Generate a call to the adjustl/adjustr library function. */
7178 static void
7179 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
7181 tree args[3];
7182 tree len;
7183 tree type;
7184 tree var;
7185 tree tmp;
7187 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
7188 len = args[1];
7190 type = TREE_TYPE (args[2]);
7191 var = gfc_conv_string_tmp (se, type, len);
7192 args[0] = var;
7194 tmp = build_call_expr_loc (input_location,
7195 fndecl, 3, args[0], args[1], args[2]);
7196 gfc_add_expr_to_block (&se->pre, tmp);
7197 se->expr = var;
7198 se->string_length = len;
7202 /* Generate code for the TRANSFER intrinsic:
7203 For scalar results:
7204 DEST = TRANSFER (SOURCE, MOLD)
7205 where:
7206 typeof<DEST> = typeof<MOLD>
7207 and:
7208 MOLD is scalar.
7210 For array results:
7211 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
7212 where:
7213 typeof<DEST> = typeof<MOLD>
7214 and:
7215 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
7216 sizeof (DEST(0) * SIZE). */
7217 static void
7218 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
7220 tree tmp;
7221 tree tmpdecl;
7222 tree ptr;
7223 tree extent;
7224 tree source;
7225 tree source_type;
7226 tree source_bytes;
7227 tree mold_type;
7228 tree dest_word_len;
7229 tree size_words;
7230 tree size_bytes;
7231 tree upper;
7232 tree lower;
7233 tree stmt;
7234 gfc_actual_arglist *arg;
7235 gfc_se argse;
7236 gfc_array_info *info;
7237 stmtblock_t block;
7238 int n;
7239 bool scalar_mold;
7240 gfc_expr *source_expr, *mold_expr;
7242 info = NULL;
7243 if (se->loop)
7244 info = &se->ss->info->data.array;
7246 /* Convert SOURCE. The output from this stage is:-
7247 source_bytes = length of the source in bytes
7248 source = pointer to the source data. */
7249 arg = expr->value.function.actual;
7250 source_expr = arg->expr;
7252 /* Ensure double transfer through LOGICAL preserves all
7253 the needed bits. */
7254 if (arg->expr->expr_type == EXPR_FUNCTION
7255 && arg->expr->value.function.esym == NULL
7256 && arg->expr->value.function.isym != NULL
7257 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
7258 && arg->expr->ts.type == BT_LOGICAL
7259 && expr->ts.type != arg->expr->ts.type)
7260 arg->expr->value.function.name = "__transfer_in_transfer";
7262 gfc_init_se (&argse, NULL);
7264 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
7266 /* Obtain the pointer to source and the length of source in bytes. */
7267 if (arg->expr->rank == 0)
7269 gfc_conv_expr_reference (&argse, arg->expr);
7270 if (arg->expr->ts.type == BT_CLASS)
7271 source = gfc_class_data_get (argse.expr);
7272 else
7273 source = argse.expr;
7275 /* Obtain the source word length. */
7276 switch (arg->expr->ts.type)
7278 case BT_CHARACTER:
7279 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7280 argse.string_length);
7281 break;
7282 case BT_CLASS:
7283 tmp = gfc_class_vtab_size_get (argse.expr);
7284 break;
7285 default:
7286 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7287 source));
7288 tmp = fold_convert (gfc_array_index_type,
7289 size_in_bytes (source_type));
7290 break;
7293 else
7295 argse.want_pointer = 0;
7296 gfc_conv_expr_descriptor (&argse, arg->expr);
7297 source = gfc_conv_descriptor_data_get (argse.expr);
7298 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7300 /* Repack the source if not simply contiguous. */
7301 if (!gfc_is_simply_contiguous (arg->expr, false, true))
7303 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
7305 if (warn_array_temporaries)
7306 gfc_warning (OPT_Warray_temporaries,
7307 "Creating array temporary at %L", &expr->where);
7309 source = build_call_expr_loc (input_location,
7310 gfor_fndecl_in_pack, 1, tmp);
7311 source = gfc_evaluate_now (source, &argse.pre);
7313 /* Free the temporary. */
7314 gfc_start_block (&block);
7315 tmp = gfc_call_free (source);
7316 gfc_add_expr_to_block (&block, tmp);
7317 stmt = gfc_finish_block (&block);
7319 /* Clean up if it was repacked. */
7320 gfc_init_block (&block);
7321 tmp = gfc_conv_array_data (argse.expr);
7322 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7323 source, tmp);
7324 tmp = build3_v (COND_EXPR, tmp, stmt,
7325 build_empty_stmt (input_location));
7326 gfc_add_expr_to_block (&block, tmp);
7327 gfc_add_block_to_block (&block, &se->post);
7328 gfc_init_block (&se->post);
7329 gfc_add_block_to_block (&se->post, &block);
7332 /* Obtain the source word length. */
7333 if (arg->expr->ts.type == BT_CHARACTER)
7334 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7335 argse.string_length);
7336 else
7337 tmp = fold_convert (gfc_array_index_type,
7338 size_in_bytes (source_type));
7340 /* Obtain the size of the array in bytes. */
7341 extent = gfc_create_var (gfc_array_index_type, NULL);
7342 for (n = 0; n < arg->expr->rank; n++)
7344 tree idx;
7345 idx = gfc_rank_cst[n];
7346 gfc_add_modify (&argse.pre, source_bytes, tmp);
7347 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
7348 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
7349 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7350 gfc_array_index_type, upper, lower);
7351 gfc_add_modify (&argse.pre, extent, tmp);
7352 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7353 gfc_array_index_type, extent,
7354 gfc_index_one_node);
7355 tmp = fold_build2_loc (input_location, MULT_EXPR,
7356 gfc_array_index_type, tmp, source_bytes);
7360 gfc_add_modify (&argse.pre, source_bytes, tmp);
7361 gfc_add_block_to_block (&se->pre, &argse.pre);
7362 gfc_add_block_to_block (&se->post, &argse.post);
7364 /* Now convert MOLD. The outputs are:
7365 mold_type = the TREE type of MOLD
7366 dest_word_len = destination word length in bytes. */
7367 arg = arg->next;
7368 mold_expr = arg->expr;
7370 gfc_init_se (&argse, NULL);
7372 scalar_mold = arg->expr->rank == 0;
7374 if (arg->expr->rank == 0)
7376 gfc_conv_expr_reference (&argse, arg->expr);
7377 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7378 argse.expr));
7380 else
7382 gfc_init_se (&argse, NULL);
7383 argse.want_pointer = 0;
7384 gfc_conv_expr_descriptor (&argse, arg->expr);
7385 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7388 gfc_add_block_to_block (&se->pre, &argse.pre);
7389 gfc_add_block_to_block (&se->post, &argse.post);
7391 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
7393 /* If this TRANSFER is nested in another TRANSFER, use a type
7394 that preserves all bits. */
7395 if (arg->expr->ts.type == BT_LOGICAL)
7396 mold_type = gfc_get_int_type (arg->expr->ts.kind);
7399 /* Obtain the destination word length. */
7400 switch (arg->expr->ts.type)
7402 case BT_CHARACTER:
7403 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
7404 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
7405 break;
7406 case BT_CLASS:
7407 tmp = gfc_class_vtab_size_get (argse.expr);
7408 break;
7409 default:
7410 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
7411 break;
7413 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
7414 gfc_add_modify (&se->pre, dest_word_len, tmp);
7416 /* Finally convert SIZE, if it is present. */
7417 arg = arg->next;
7418 size_words = gfc_create_var (gfc_array_index_type, NULL);
7420 if (arg->expr)
7422 gfc_init_se (&argse, NULL);
7423 gfc_conv_expr_reference (&argse, arg->expr);
7424 tmp = convert (gfc_array_index_type,
7425 build_fold_indirect_ref_loc (input_location,
7426 argse.expr));
7427 gfc_add_block_to_block (&se->pre, &argse.pre);
7428 gfc_add_block_to_block (&se->post, &argse.post);
7430 else
7431 tmp = NULL_TREE;
7433 /* Separate array and scalar results. */
7434 if (scalar_mold && tmp == NULL_TREE)
7435 goto scalar_transfer;
7437 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
7438 if (tmp != NULL_TREE)
7439 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7440 tmp, dest_word_len);
7441 else
7442 tmp = source_bytes;
7444 gfc_add_modify (&se->pre, size_bytes, tmp);
7445 gfc_add_modify (&se->pre, size_words,
7446 fold_build2_loc (input_location, CEIL_DIV_EXPR,
7447 gfc_array_index_type,
7448 size_bytes, dest_word_len));
7450 /* Evaluate the bounds of the result. If the loop range exists, we have
7451 to check if it is too large. If so, we modify loop->to be consistent
7452 with min(size, size(source)). Otherwise, size is made consistent with
7453 the loop range, so that the right number of bytes is transferred.*/
7454 n = se->loop->order[0];
7455 if (se->loop->to[n] != NULL_TREE)
7457 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7458 se->loop->to[n], se->loop->from[n]);
7459 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7460 tmp, gfc_index_one_node);
7461 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7462 tmp, size_words);
7463 gfc_add_modify (&se->pre, size_words, tmp);
7464 gfc_add_modify (&se->pre, size_bytes,
7465 fold_build2_loc (input_location, MULT_EXPR,
7466 gfc_array_index_type,
7467 size_words, dest_word_len));
7468 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7469 size_words, se->loop->from[n]);
7470 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7471 upper, gfc_index_one_node);
7473 else
7475 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7476 size_words, gfc_index_one_node);
7477 se->loop->from[n] = gfc_index_zero_node;
7480 se->loop->to[n] = upper;
7482 /* Build a destination descriptor, using the pointer, source, as the
7483 data field. */
7484 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
7485 NULL_TREE, false, true, false, &expr->where);
7487 /* Cast the pointer to the result. */
7488 tmp = gfc_conv_descriptor_data_get (info->descriptor);
7489 tmp = fold_convert (pvoid_type_node, tmp);
7491 /* Use memcpy to do the transfer. */
7493 = build_call_expr_loc (input_location,
7494 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
7495 fold_convert (pvoid_type_node, source),
7496 fold_convert (size_type_node,
7497 fold_build2_loc (input_location,
7498 MIN_EXPR,
7499 gfc_array_index_type,
7500 size_bytes,
7501 source_bytes)));
7502 gfc_add_expr_to_block (&se->pre, tmp);
7504 se->expr = info->descriptor;
7505 if (expr->ts.type == BT_CHARACTER)
7506 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7508 return;
7510 /* Deal with scalar results. */
7511 scalar_transfer:
7512 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7513 dest_word_len, source_bytes);
7514 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
7515 extent, gfc_index_zero_node);
7517 if (expr->ts.type == BT_CHARACTER)
7519 tree direct, indirect, free;
7521 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
7522 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
7523 "transfer");
7525 /* If source is longer than the destination, use a pointer to
7526 the source directly. */
7527 gfc_init_block (&block);
7528 gfc_add_modify (&block, tmpdecl, ptr);
7529 direct = gfc_finish_block (&block);
7531 /* Otherwise, allocate a string with the length of the destination
7532 and copy the source into it. */
7533 gfc_init_block (&block);
7534 tmp = gfc_get_pchar_type (expr->ts.kind);
7535 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
7536 gfc_add_modify (&block, tmpdecl,
7537 fold_convert (TREE_TYPE (ptr), tmp));
7538 tmp = build_call_expr_loc (input_location,
7539 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7540 fold_convert (pvoid_type_node, tmpdecl),
7541 fold_convert (pvoid_type_node, ptr),
7542 fold_convert (size_type_node, extent));
7543 gfc_add_expr_to_block (&block, tmp);
7544 indirect = gfc_finish_block (&block);
7546 /* Wrap it up with the condition. */
7547 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
7548 dest_word_len, source_bytes);
7549 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
7550 gfc_add_expr_to_block (&se->pre, tmp);
7552 /* Free the temporary string, if necessary. */
7553 free = gfc_call_free (tmpdecl);
7554 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
7555 dest_word_len, source_bytes);
7556 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
7557 gfc_add_expr_to_block (&se->post, tmp);
7559 se->expr = tmpdecl;
7560 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7562 else
7564 tmpdecl = gfc_create_var (mold_type, "transfer");
7566 ptr = convert (build_pointer_type (mold_type), source);
7568 /* For CLASS results, allocate the needed memory first. */
7569 if (mold_expr->ts.type == BT_CLASS)
7571 tree cdata;
7572 cdata = gfc_class_data_get (tmpdecl);
7573 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
7574 gfc_add_modify (&se->pre, cdata, tmp);
7577 /* Use memcpy to do the transfer. */
7578 if (mold_expr->ts.type == BT_CLASS)
7579 tmp = gfc_class_data_get (tmpdecl);
7580 else
7581 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
7583 tmp = build_call_expr_loc (input_location,
7584 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7585 fold_convert (pvoid_type_node, tmp),
7586 fold_convert (pvoid_type_node, ptr),
7587 fold_convert (size_type_node, extent));
7588 gfc_add_expr_to_block (&se->pre, tmp);
7590 /* For CLASS results, set the _vptr. */
7591 if (mold_expr->ts.type == BT_CLASS)
7593 tree vptr;
7594 gfc_symbol *vtab;
7595 vptr = gfc_class_vptr_get (tmpdecl);
7596 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
7597 gcc_assert (vtab);
7598 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7599 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
7602 se->expr = tmpdecl;
7607 /* Generate a call to caf_is_present. */
7609 static tree
7610 trans_caf_is_present (gfc_se *se, gfc_expr *expr)
7612 tree caf_reference, caf_decl, token, image_index;
7614 /* Compile the reference chain. */
7615 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
7616 gcc_assert (caf_reference != NULL_TREE);
7618 caf_decl = gfc_get_tree_for_caf_expr (expr);
7619 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
7620 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
7621 image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
7622 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
7623 expr);
7625 return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
7626 3, token, image_index, caf_reference);
7630 /* Test whether this ref-chain refs this image only. */
7632 static bool
7633 caf_this_image_ref (gfc_ref *ref)
7635 for ( ; ref; ref = ref->next)
7636 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
7637 return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
7639 return false;
7643 /* Generate code for the ALLOCATED intrinsic.
7644 Generate inline code that directly check the address of the argument. */
7646 static void
7647 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
7649 gfc_actual_arglist *arg1;
7650 gfc_se arg1se;
7651 tree tmp;
7652 symbol_attribute caf_attr;
7654 gfc_init_se (&arg1se, NULL);
7655 arg1 = expr->value.function.actual;
7657 if (arg1->expr->ts.type == BT_CLASS)
7659 /* Make sure that class array expressions have both a _data
7660 component reference and an array reference.... */
7661 if (CLASS_DATA (arg1->expr)->attr.dimension)
7662 gfc_add_class_array_ref (arg1->expr);
7663 /* .... whilst scalars only need the _data component. */
7664 else
7665 gfc_add_data_component (arg1->expr);
7668 /* When arg1 references an allocatable component in a coarray, then call
7669 the caf-library function caf_is_present (). */
7670 if (flag_coarray == GFC_FCOARRAY_LIB && arg1->expr->expr_type == EXPR_FUNCTION
7671 && arg1->expr->value.function.isym
7672 && arg1->expr->value.function.isym->id == GFC_ISYM_CAF_GET)
7673 caf_attr = gfc_caf_attr (arg1->expr->value.function.actual->expr);
7674 else
7675 gfc_clear_attr (&caf_attr);
7676 if (flag_coarray == GFC_FCOARRAY_LIB && caf_attr.codimension
7677 && !caf_this_image_ref (arg1->expr->value.function.actual->expr->ref))
7678 tmp = trans_caf_is_present (se, arg1->expr->value.function.actual->expr);
7679 else
7681 if (arg1->expr->rank == 0)
7683 /* Allocatable scalar. */
7684 arg1se.want_pointer = 1;
7685 gfc_conv_expr (&arg1se, arg1->expr);
7686 tmp = arg1se.expr;
7688 else
7690 /* Allocatable array. */
7691 arg1se.descriptor_only = 1;
7692 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7693 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
7696 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
7697 fold_convert (TREE_TYPE (tmp), null_pointer_node));
7700 /* Components of pointer array references sometimes come back with a pre block. */
7701 if (arg1se.pre.head)
7702 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7704 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
7708 /* Generate code for the ASSOCIATED intrinsic.
7709 If both POINTER and TARGET are arrays, generate a call to library function
7710 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
7711 In other cases, generate inline code that directly compare the address of
7712 POINTER with the address of TARGET. */
7714 static void
7715 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
7717 gfc_actual_arglist *arg1;
7718 gfc_actual_arglist *arg2;
7719 gfc_se arg1se;
7720 gfc_se arg2se;
7721 tree tmp2;
7722 tree tmp;
7723 tree nonzero_charlen;
7724 tree nonzero_arraylen;
7725 gfc_ss *ss;
7726 bool scalar;
7728 gfc_init_se (&arg1se, NULL);
7729 gfc_init_se (&arg2se, NULL);
7730 arg1 = expr->value.function.actual;
7731 arg2 = arg1->next;
7733 /* Check whether the expression is a scalar or not; we cannot use
7734 arg1->expr->rank as it can be nonzero for proc pointers. */
7735 ss = gfc_walk_expr (arg1->expr);
7736 scalar = ss == gfc_ss_terminator;
7737 if (!scalar)
7738 gfc_free_ss_chain (ss);
7740 if (!arg2->expr)
7742 /* No optional target. */
7743 if (scalar)
7745 /* A pointer to a scalar. */
7746 arg1se.want_pointer = 1;
7747 gfc_conv_expr (&arg1se, arg1->expr);
7748 if (arg1->expr->symtree->n.sym->attr.proc_pointer
7749 && arg1->expr->symtree->n.sym->attr.dummy)
7750 arg1se.expr = build_fold_indirect_ref_loc (input_location,
7751 arg1se.expr);
7752 if (arg1->expr->ts.type == BT_CLASS)
7754 tmp2 = gfc_class_data_get (arg1se.expr);
7755 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
7756 tmp2 = gfc_conv_descriptor_data_get (tmp2);
7758 else
7759 tmp2 = arg1se.expr;
7761 else
7763 /* A pointer to an array. */
7764 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7765 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
7767 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7768 gfc_add_block_to_block (&se->post, &arg1se.post);
7769 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp2,
7770 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
7771 se->expr = tmp;
7773 else
7775 /* An optional target. */
7776 if (arg2->expr->ts.type == BT_CLASS)
7777 gfc_add_data_component (arg2->expr);
7779 nonzero_charlen = NULL_TREE;
7780 if (arg1->expr->ts.type == BT_CHARACTER)
7781 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
7782 logical_type_node,
7783 arg1->expr->ts.u.cl->backend_decl,
7784 build_zero_cst
7785 (TREE_TYPE (arg1->expr->ts.u.cl->backend_decl)));
7786 if (scalar)
7788 /* A pointer to a scalar. */
7789 arg1se.want_pointer = 1;
7790 gfc_conv_expr (&arg1se, arg1->expr);
7791 if (arg1->expr->symtree->n.sym->attr.proc_pointer
7792 && arg1->expr->symtree->n.sym->attr.dummy)
7793 arg1se.expr = build_fold_indirect_ref_loc (input_location,
7794 arg1se.expr);
7795 if (arg1->expr->ts.type == BT_CLASS)
7796 arg1se.expr = gfc_class_data_get (arg1se.expr);
7798 arg2se.want_pointer = 1;
7799 gfc_conv_expr (&arg2se, arg2->expr);
7800 if (arg2->expr->symtree->n.sym->attr.proc_pointer
7801 && arg2->expr->symtree->n.sym->attr.dummy)
7802 arg2se.expr = build_fold_indirect_ref_loc (input_location,
7803 arg2se.expr);
7804 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7805 gfc_add_block_to_block (&se->post, &arg1se.post);
7806 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7807 gfc_add_block_to_block (&se->post, &arg2se.post);
7808 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7809 arg1se.expr, arg2se.expr);
7810 tmp2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7811 arg1se.expr, null_pointer_node);
7812 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7813 logical_type_node, tmp, tmp2);
7815 else
7817 /* An array pointer of zero length is not associated if target is
7818 present. */
7819 arg1se.descriptor_only = 1;
7820 gfc_conv_expr_lhs (&arg1se, arg1->expr);
7821 if (arg1->expr->rank == -1)
7823 tmp = gfc_conv_descriptor_rank (arg1se.expr);
7824 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7825 TREE_TYPE (tmp), tmp, gfc_index_one_node);
7827 else
7828 tmp = gfc_rank_cst[arg1->expr->rank - 1];
7829 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
7830 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
7831 logical_type_node, tmp,
7832 build_int_cst (TREE_TYPE (tmp), 0));
7834 /* A pointer to an array, call library function _gfor_associated. */
7835 arg1se.want_pointer = 1;
7836 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7838 arg2se.want_pointer = 1;
7839 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
7840 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7841 gfc_add_block_to_block (&se->post, &arg2se.post);
7842 se->expr = build_call_expr_loc (input_location,
7843 gfor_fndecl_associated, 2,
7844 arg1se.expr, arg2se.expr);
7845 se->expr = convert (logical_type_node, se->expr);
7846 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7847 logical_type_node, se->expr,
7848 nonzero_arraylen);
7851 /* If target is present zero character length pointers cannot
7852 be associated. */
7853 if (nonzero_charlen != NULL_TREE)
7854 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7855 logical_type_node,
7856 se->expr, nonzero_charlen);
7859 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7863 /* Generate code for the SAME_TYPE_AS intrinsic.
7864 Generate inline code that directly checks the vindices. */
7866 static void
7867 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
7869 gfc_expr *a, *b;
7870 gfc_se se1, se2;
7871 tree tmp;
7872 tree conda = NULL_TREE, condb = NULL_TREE;
7874 gfc_init_se (&se1, NULL);
7875 gfc_init_se (&se2, NULL);
7877 a = expr->value.function.actual->expr;
7878 b = expr->value.function.actual->next->expr;
7880 if (UNLIMITED_POLY (a))
7882 tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
7883 conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7884 tmp, build_int_cst (TREE_TYPE (tmp), 0));
7887 if (UNLIMITED_POLY (b))
7889 tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
7890 condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7891 tmp, build_int_cst (TREE_TYPE (tmp), 0));
7894 if (a->ts.type == BT_CLASS)
7896 gfc_add_vptr_component (a);
7897 gfc_add_hash_component (a);
7899 else if (a->ts.type == BT_DERIVED)
7900 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
7901 a->ts.u.derived->hash_value);
7903 if (b->ts.type == BT_CLASS)
7905 gfc_add_vptr_component (b);
7906 gfc_add_hash_component (b);
7908 else if (b->ts.type == BT_DERIVED)
7909 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
7910 b->ts.u.derived->hash_value);
7912 gfc_conv_expr (&se1, a);
7913 gfc_conv_expr (&se2, b);
7915 tmp = fold_build2_loc (input_location, EQ_EXPR,
7916 logical_type_node, se1.expr,
7917 fold_convert (TREE_TYPE (se1.expr), se2.expr));
7919 if (conda)
7920 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
7921 logical_type_node, conda, tmp);
7923 if (condb)
7924 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
7925 logical_type_node, condb, tmp);
7927 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
7931 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
7933 static void
7934 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
7936 tree args[2];
7938 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7939 se->expr = build_call_expr_loc (input_location,
7940 gfor_fndecl_sc_kind, 2, args[0], args[1]);
7941 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7945 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
7947 static void
7948 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
7950 tree arg, type;
7952 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7954 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
7955 type = gfc_get_int_type (4);
7956 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
7958 /* Convert it to the required type. */
7959 type = gfc_typenode_for_spec (&expr->ts);
7960 se->expr = build_call_expr_loc (input_location,
7961 gfor_fndecl_si_kind, 1, arg);
7962 se->expr = fold_convert (type, se->expr);
7966 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
7968 static void
7969 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
7971 gfc_actual_arglist *actual;
7972 tree type;
7973 gfc_se argse;
7974 vec<tree, va_gc> *args = NULL;
7976 for (actual = expr->value.function.actual; actual; actual = actual->next)
7978 gfc_init_se (&argse, se);
7980 /* Pass a NULL pointer for an absent arg. */
7981 if (actual->expr == NULL)
7982 argse.expr = null_pointer_node;
7983 else
7985 gfc_typespec ts;
7986 gfc_clear_ts (&ts);
7988 if (actual->expr->ts.kind != gfc_c_int_kind)
7990 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
7991 ts.type = BT_INTEGER;
7992 ts.kind = gfc_c_int_kind;
7993 gfc_convert_type (actual->expr, &ts, 2);
7995 gfc_conv_expr_reference (&argse, actual->expr);
7998 gfc_add_block_to_block (&se->pre, &argse.pre);
7999 gfc_add_block_to_block (&se->post, &argse.post);
8000 vec_safe_push (args, argse.expr);
8003 /* Convert it to the required type. */
8004 type = gfc_typenode_for_spec (&expr->ts);
8005 se->expr = build_call_expr_loc_vec (input_location,
8006 gfor_fndecl_sr_kind, args);
8007 se->expr = fold_convert (type, se->expr);
8011 /* Generate code for TRIM (A) intrinsic function. */
8013 static void
8014 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
8016 tree var;
8017 tree len;
8018 tree addr;
8019 tree tmp;
8020 tree cond;
8021 tree fndecl;
8022 tree function;
8023 tree *args;
8024 unsigned int num_args;
8026 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
8027 args = XALLOCAVEC (tree, num_args);
8029 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
8030 addr = gfc_build_addr_expr (ppvoid_type_node, var);
8031 len = gfc_create_var (gfc_charlen_type_node, "len");
8033 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
8034 args[0] = gfc_build_addr_expr (NULL_TREE, len);
8035 args[1] = addr;
8037 if (expr->ts.kind == 1)
8038 function = gfor_fndecl_string_trim;
8039 else if (expr->ts.kind == 4)
8040 function = gfor_fndecl_string_trim_char4;
8041 else
8042 gcc_unreachable ();
8044 fndecl = build_addr (function);
8045 tmp = build_call_array_loc (input_location,
8046 TREE_TYPE (TREE_TYPE (function)), fndecl,
8047 num_args, args);
8048 gfc_add_expr_to_block (&se->pre, tmp);
8050 /* Free the temporary afterwards, if necessary. */
8051 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
8052 len, build_int_cst (TREE_TYPE (len), 0));
8053 tmp = gfc_call_free (var);
8054 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
8055 gfc_add_expr_to_block (&se->post, tmp);
8057 se->expr = var;
8058 se->string_length = len;
8062 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
8064 static void
8065 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
8067 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
8068 tree type, cond, tmp, count, exit_label, n, max, largest;
8069 tree size;
8070 stmtblock_t block, body;
8071 int i;
8073 /* We store in charsize the size of a character. */
8074 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
8075 size = build_int_cst (sizetype, gfc_character_kinds[i].bit_size / 8);
8077 /* Get the arguments. */
8078 gfc_conv_intrinsic_function_args (se, expr, args, 3);
8079 slen = fold_convert (sizetype, gfc_evaluate_now (args[0], &se->pre));
8080 src = args[1];
8081 ncopies = gfc_evaluate_now (args[2], &se->pre);
8082 ncopies_type = TREE_TYPE (ncopies);
8084 /* Check that NCOPIES is not negative. */
8085 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, ncopies,
8086 build_int_cst (ncopies_type, 0));
8087 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
8088 "Argument NCOPIES of REPEAT intrinsic is negative "
8089 "(its value is %ld)",
8090 fold_convert (long_integer_type_node, ncopies));
8092 /* If the source length is zero, any non negative value of NCOPIES
8093 is valid, and nothing happens. */
8094 n = gfc_create_var (ncopies_type, "ncopies");
8095 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
8096 size_zero_node);
8097 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
8098 build_int_cst (ncopies_type, 0), ncopies);
8099 gfc_add_modify (&se->pre, n, tmp);
8100 ncopies = n;
8102 /* Check that ncopies is not too large: ncopies should be less than
8103 (or equal to) MAX / slen, where MAX is the maximal integer of
8104 the gfc_charlen_type_node type. If slen == 0, we need a special
8105 case to avoid the division by zero. */
8106 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, sizetype,
8107 fold_convert (sizetype,
8108 TYPE_MAX_VALUE (gfc_charlen_type_node)),
8109 slen);
8110 largest = TYPE_PRECISION (sizetype) > TYPE_PRECISION (ncopies_type)
8111 ? sizetype : ncopies_type;
8112 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
8113 fold_convert (largest, ncopies),
8114 fold_convert (largest, max));
8115 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
8116 size_zero_node);
8117 cond = fold_build3_loc (input_location, COND_EXPR, logical_type_node, tmp,
8118 logical_false_node, cond);
8119 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
8120 "Argument NCOPIES of REPEAT intrinsic is too large");
8122 /* Compute the destination length. */
8123 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
8124 fold_convert (gfc_charlen_type_node, slen),
8125 fold_convert (gfc_charlen_type_node, ncopies));
8126 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
8127 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
8129 /* Generate the code to do the repeat operation:
8130 for (i = 0; i < ncopies; i++)
8131 memmove (dest + (i * slen * size), src, slen*size); */
8132 gfc_start_block (&block);
8133 count = gfc_create_var (sizetype, "count");
8134 gfc_add_modify (&block, count, size_zero_node);
8135 exit_label = gfc_build_label_decl (NULL_TREE);
8137 /* Start the loop body. */
8138 gfc_start_block (&body);
8140 /* Exit the loop if count >= ncopies. */
8141 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, count,
8142 fold_convert (sizetype, ncopies));
8143 tmp = build1_v (GOTO_EXPR, exit_label);
8144 TREE_USED (exit_label) = 1;
8145 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
8146 build_empty_stmt (input_location));
8147 gfc_add_expr_to_block (&body, tmp);
8149 /* Call memmove (dest + (i*slen*size), src, slen*size). */
8150 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, slen,
8151 count);
8152 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, tmp,
8153 size);
8154 tmp = fold_build_pointer_plus_loc (input_location,
8155 fold_convert (pvoid_type_node, dest), tmp);
8156 tmp = build_call_expr_loc (input_location,
8157 builtin_decl_explicit (BUILT_IN_MEMMOVE),
8158 3, tmp, src,
8159 fold_build2_loc (input_location, MULT_EXPR,
8160 size_type_node, slen, size));
8161 gfc_add_expr_to_block (&body, tmp);
8163 /* Increment count. */
8164 tmp = fold_build2_loc (input_location, PLUS_EXPR, sizetype,
8165 count, size_one_node);
8166 gfc_add_modify (&body, count, tmp);
8168 /* Build the loop. */
8169 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
8170 gfc_add_expr_to_block (&block, tmp);
8172 /* Add the exit label. */
8173 tmp = build1_v (LABEL_EXPR, exit_label);
8174 gfc_add_expr_to_block (&block, tmp);
8176 /* Finish the block. */
8177 tmp = gfc_finish_block (&block);
8178 gfc_add_expr_to_block (&se->pre, tmp);
8180 /* Set the result value. */
8181 se->expr = dest;
8182 se->string_length = dlen;
8186 /* Generate code for the IARGC intrinsic. */
8188 static void
8189 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
8191 tree tmp;
8192 tree fndecl;
8193 tree type;
8195 /* Call the library function. This always returns an INTEGER(4). */
8196 fndecl = gfor_fndecl_iargc;
8197 tmp = build_call_expr_loc (input_location,
8198 fndecl, 0);
8200 /* Convert it to the required type. */
8201 type = gfc_typenode_for_spec (&expr->ts);
8202 tmp = fold_convert (type, tmp);
8204 se->expr = tmp;
8208 /* Generate code for the KILL intrinsic. */
8210 static void
8211 conv_intrinsic_kill (gfc_se *se, gfc_expr *expr)
8213 tree *args;
8214 tree int4_type_node = gfc_get_int_type (4);
8215 tree pid;
8216 tree sig;
8217 tree tmp;
8218 unsigned int num_args;
8220 num_args = gfc_intrinsic_argument_list_length (expr);
8221 args = XALLOCAVEC (tree, num_args);
8222 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
8224 /* Convert PID to a INTEGER(4) entity. */
8225 pid = convert (int4_type_node, args[0]);
8227 /* Convert SIG to a INTEGER(4) entity. */
8228 sig = convert (int4_type_node, args[1]);
8230 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill, 2, pid, sig);
8232 se->expr = fold_convert (TREE_TYPE (args[0]), tmp);
8236 static tree
8237 conv_intrinsic_kill_sub (gfc_code *code)
8239 stmtblock_t block;
8240 gfc_se se, se_stat;
8241 tree int4_type_node = gfc_get_int_type (4);
8242 tree pid;
8243 tree sig;
8244 tree statp;
8245 tree tmp;
8247 /* Make the function call. */
8248 gfc_init_block (&block);
8249 gfc_init_se (&se, NULL);
8251 /* Convert PID to a INTEGER(4) entity. */
8252 gfc_conv_expr (&se, code->ext.actual->expr);
8253 gfc_add_block_to_block (&block, &se.pre);
8254 pid = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
8255 gfc_add_block_to_block (&block, &se.post);
8257 /* Convert SIG to a INTEGER(4) entity. */
8258 gfc_conv_expr (&se, code->ext.actual->next->expr);
8259 gfc_add_block_to_block (&block, &se.pre);
8260 sig = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
8261 gfc_add_block_to_block (&block, &se.post);
8263 /* Deal with an optional STATUS. */
8264 if (code->ext.actual->next->next->expr)
8266 gfc_init_se (&se_stat, NULL);
8267 gfc_conv_expr (&se_stat, code->ext.actual->next->next->expr);
8268 statp = gfc_create_var (gfc_get_int_type (4), "_statp");
8270 else
8271 statp = NULL_TREE;
8273 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill_sub, 3, pid, sig,
8274 statp ? gfc_build_addr_expr (NULL_TREE, statp) : null_pointer_node);
8276 gfc_add_expr_to_block (&block, tmp);
8278 if (statp && statp != se_stat.expr)
8279 gfc_add_modify (&block, se_stat.expr,
8280 fold_convert (TREE_TYPE (se_stat.expr), statp));
8282 return gfc_finish_block (&block);
8287 /* The loc intrinsic returns the address of its argument as
8288 gfc_index_integer_kind integer. */
8290 static void
8291 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
8293 tree temp_var;
8294 gfc_expr *arg_expr;
8296 gcc_assert (!se->ss);
8298 arg_expr = expr->value.function.actual->expr;
8299 if (arg_expr->rank == 0)
8301 if (arg_expr->ts.type == BT_CLASS)
8302 gfc_add_data_component (arg_expr);
8303 gfc_conv_expr_reference (se, arg_expr);
8305 else
8306 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
8307 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
8309 /* Create a temporary variable for loc return value. Without this,
8310 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
8311 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
8312 gfc_add_modify (&se->pre, temp_var, se->expr);
8313 se->expr = temp_var;
8317 /* The following routine generates code for the intrinsic
8318 functions from the ISO_C_BINDING module:
8319 * C_LOC
8320 * C_FUNLOC
8321 * C_ASSOCIATED */
8323 static void
8324 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
8326 gfc_actual_arglist *arg = expr->value.function.actual;
8328 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
8330 if (arg->expr->rank == 0)
8331 gfc_conv_expr_reference (se, arg->expr);
8332 else if (gfc_is_simply_contiguous (arg->expr, false, false))
8333 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
8334 else
8336 gfc_conv_expr_descriptor (se, arg->expr);
8337 se->expr = gfc_conv_descriptor_data_get (se->expr);
8340 /* TODO -- the following two lines shouldn't be necessary, but if
8341 they're removed, a bug is exposed later in the code path.
8342 This workaround was thus introduced, but will have to be
8343 removed; please see PR 35150 for details about the issue. */
8344 se->expr = convert (pvoid_type_node, se->expr);
8345 se->expr = gfc_evaluate_now (se->expr, &se->pre);
8347 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
8348 gfc_conv_expr_reference (se, arg->expr);
8349 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
8351 gfc_se arg1se;
8352 gfc_se arg2se;
8354 /* Build the addr_expr for the first argument. The argument is
8355 already an *address* so we don't need to set want_pointer in
8356 the gfc_se. */
8357 gfc_init_se (&arg1se, NULL);
8358 gfc_conv_expr (&arg1se, arg->expr);
8359 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8360 gfc_add_block_to_block (&se->post, &arg1se.post);
8362 /* See if we were given two arguments. */
8363 if (arg->next->expr == NULL)
8364 /* Only given one arg so generate a null and do a
8365 not-equal comparison against the first arg. */
8366 se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8367 arg1se.expr,
8368 fold_convert (TREE_TYPE (arg1se.expr),
8369 null_pointer_node));
8370 else
8372 tree eq_expr;
8373 tree not_null_expr;
8375 /* Given two arguments so build the arg2se from second arg. */
8376 gfc_init_se (&arg2se, NULL);
8377 gfc_conv_expr (&arg2se, arg->next->expr);
8378 gfc_add_block_to_block (&se->pre, &arg2se.pre);
8379 gfc_add_block_to_block (&se->post, &arg2se.post);
8381 /* Generate test to compare that the two args are equal. */
8382 eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
8383 arg1se.expr, arg2se.expr);
8384 /* Generate test to ensure that the first arg is not null. */
8385 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
8386 logical_type_node,
8387 arg1se.expr, null_pointer_node);
8389 /* Finally, the generated test must check that both arg1 is not
8390 NULL and that it is equal to the second arg. */
8391 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8392 logical_type_node,
8393 not_null_expr, eq_expr);
8396 else
8397 gcc_unreachable ();
8401 /* The following routine generates code for the intrinsic
8402 subroutines from the ISO_C_BINDING module:
8403 * C_F_POINTER
8404 * C_F_PROCPOINTER. */
8406 static tree
8407 conv_isocbinding_subroutine (gfc_code *code)
8409 gfc_se se;
8410 gfc_se cptrse;
8411 gfc_se fptrse;
8412 gfc_se shapese;
8413 gfc_ss *shape_ss;
8414 tree desc, dim, tmp, stride, offset;
8415 stmtblock_t body, block;
8416 gfc_loopinfo loop;
8417 gfc_actual_arglist *arg = code->ext.actual;
8419 gfc_init_se (&se, NULL);
8420 gfc_init_se (&cptrse, NULL);
8421 gfc_conv_expr (&cptrse, arg->expr);
8422 gfc_add_block_to_block (&se.pre, &cptrse.pre);
8423 gfc_add_block_to_block (&se.post, &cptrse.post);
8425 gfc_init_se (&fptrse, NULL);
8426 if (arg->next->expr->rank == 0)
8428 fptrse.want_pointer = 1;
8429 gfc_conv_expr (&fptrse, arg->next->expr);
8430 gfc_add_block_to_block (&se.pre, &fptrse.pre);
8431 gfc_add_block_to_block (&se.post, &fptrse.post);
8432 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
8433 && arg->next->expr->symtree->n.sym->attr.dummy)
8434 fptrse.expr = build_fold_indirect_ref_loc (input_location,
8435 fptrse.expr);
8436 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
8437 TREE_TYPE (fptrse.expr),
8438 fptrse.expr,
8439 fold_convert (TREE_TYPE (fptrse.expr),
8440 cptrse.expr));
8441 gfc_add_expr_to_block (&se.pre, se.expr);
8442 gfc_add_block_to_block (&se.pre, &se.post);
8443 return gfc_finish_block (&se.pre);
8446 gfc_start_block (&block);
8448 /* Get the descriptor of the Fortran pointer. */
8449 fptrse.descriptor_only = 1;
8450 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
8451 gfc_add_block_to_block (&block, &fptrse.pre);
8452 desc = fptrse.expr;
8454 /* Set the span field. */
8455 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
8456 tmp = fold_convert (gfc_array_index_type, tmp);
8457 gfc_conv_descriptor_span_set (&block, desc, tmp);
8459 /* Set data value, dtype, and offset. */
8460 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
8461 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
8462 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
8463 gfc_get_dtype (TREE_TYPE (desc)));
8465 /* Start scalarization of the bounds, using the shape argument. */
8467 shape_ss = gfc_walk_expr (arg->next->next->expr);
8468 gcc_assert (shape_ss != gfc_ss_terminator);
8469 gfc_init_se (&shapese, NULL);
8471 gfc_init_loopinfo (&loop);
8472 gfc_add_ss_to_loop (&loop, shape_ss);
8473 gfc_conv_ss_startstride (&loop);
8474 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
8475 gfc_mark_ss_chain_used (shape_ss, 1);
8477 gfc_copy_loopinfo_to_se (&shapese, &loop);
8478 shapese.ss = shape_ss;
8480 stride = gfc_create_var (gfc_array_index_type, "stride");
8481 offset = gfc_create_var (gfc_array_index_type, "offset");
8482 gfc_add_modify (&block, stride, gfc_index_one_node);
8483 gfc_add_modify (&block, offset, gfc_index_zero_node);
8485 /* Loop body. */
8486 gfc_start_scalarized_body (&loop, &body);
8488 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8489 loop.loopvar[0], loop.from[0]);
8491 /* Set bounds and stride. */
8492 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
8493 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
8495 gfc_conv_expr (&shapese, arg->next->next->expr);
8496 gfc_add_block_to_block (&body, &shapese.pre);
8497 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
8498 gfc_add_block_to_block (&body, &shapese.post);
8500 /* Calculate offset. */
8501 gfc_add_modify (&body, offset,
8502 fold_build2_loc (input_location, PLUS_EXPR,
8503 gfc_array_index_type, offset, stride));
8504 /* Update stride. */
8505 gfc_add_modify (&body, stride,
8506 fold_build2_loc (input_location, MULT_EXPR,
8507 gfc_array_index_type, stride,
8508 fold_convert (gfc_array_index_type,
8509 shapese.expr)));
8510 /* Finish scalarization loop. */
8511 gfc_trans_scalarizing_loops (&loop, &body);
8512 gfc_add_block_to_block (&block, &loop.pre);
8513 gfc_add_block_to_block (&block, &loop.post);
8514 gfc_add_block_to_block (&block, &fptrse.post);
8515 gfc_cleanup_loop (&loop);
8517 gfc_add_modify (&block, offset,
8518 fold_build1_loc (input_location, NEGATE_EXPR,
8519 gfc_array_index_type, offset));
8520 gfc_conv_descriptor_offset_set (&block, desc, offset);
8522 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
8523 gfc_add_block_to_block (&se.pre, &se.post);
8524 return gfc_finish_block (&se.pre);
8528 /* Save and restore floating-point state. */
8530 tree
8531 gfc_save_fp_state (stmtblock_t *block)
8533 tree type, fpstate, tmp;
8535 type = build_array_type (char_type_node,
8536 build_range_type (size_type_node, size_zero_node,
8537 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
8538 fpstate = gfc_create_var (type, "fpstate");
8539 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
8541 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
8542 1, fpstate);
8543 gfc_add_expr_to_block (block, tmp);
8545 return fpstate;
8549 void
8550 gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
8552 tree tmp;
8554 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
8555 1, fpstate);
8556 gfc_add_expr_to_block (block, tmp);
8560 /* Generate code for arguments of IEEE functions. */
8562 static void
8563 conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
8564 int nargs)
8566 gfc_actual_arglist *actual;
8567 gfc_expr *e;
8568 gfc_se argse;
8569 int arg;
8571 actual = expr->value.function.actual;
8572 for (arg = 0; arg < nargs; arg++, actual = actual->next)
8574 gcc_assert (actual);
8575 e = actual->expr;
8577 gfc_init_se (&argse, se);
8578 gfc_conv_expr_val (&argse, e);
8580 gfc_add_block_to_block (&se->pre, &argse.pre);
8581 gfc_add_block_to_block (&se->post, &argse.post);
8582 argarray[arg] = argse.expr;
8587 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
8588 and IEEE_UNORDERED, which translate directly to GCC type-generic
8589 built-ins. */
8591 static void
8592 conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
8593 enum built_in_function code, int nargs)
8595 tree args[2];
8596 gcc_assert ((unsigned) nargs <= sizeof(args)/sizeof(args[0]));
8598 conv_ieee_function_args (se, expr, args, nargs);
8599 se->expr = build_call_expr_loc_array (input_location,
8600 builtin_decl_explicit (code),
8601 nargs, args);
8602 STRIP_TYPE_NOPS (se->expr);
8603 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8607 /* Generate code for IEEE_IS_NORMAL intrinsic:
8608 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
8610 static void
8611 conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
8613 tree arg, isnormal, iszero;
8615 /* Convert arg, evaluate it only once. */
8616 conv_ieee_function_args (se, expr, &arg, 1);
8617 arg = gfc_evaluate_now (arg, &se->pre);
8619 isnormal = build_call_expr_loc (input_location,
8620 builtin_decl_explicit (BUILT_IN_ISNORMAL),
8621 1, arg);
8622 iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
8623 build_real_from_int_cst (TREE_TYPE (arg),
8624 integer_zero_node));
8625 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
8626 logical_type_node, isnormal, iszero);
8627 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8631 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
8632 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
8634 static void
8635 conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
8637 tree arg, signbit, isnan;
8639 /* Convert arg, evaluate it only once. */
8640 conv_ieee_function_args (se, expr, &arg, 1);
8641 arg = gfc_evaluate_now (arg, &se->pre);
8643 isnan = build_call_expr_loc (input_location,
8644 builtin_decl_explicit (BUILT_IN_ISNAN),
8645 1, arg);
8646 STRIP_TYPE_NOPS (isnan);
8648 signbit = build_call_expr_loc (input_location,
8649 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8650 1, arg);
8651 signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8652 signbit, integer_zero_node);
8654 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8655 logical_type_node, signbit,
8656 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
8657 TREE_TYPE(isnan), isnan));
8659 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8663 /* Generate code for IEEE_LOGB and IEEE_RINT. */
8665 static void
8666 conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
8667 enum built_in_function code)
8669 tree arg, decl, call, fpstate;
8670 int argprec;
8672 conv_ieee_function_args (se, expr, &arg, 1);
8673 argprec = TYPE_PRECISION (TREE_TYPE (arg));
8674 decl = builtin_decl_for_precision (code, argprec);
8676 /* Save floating-point state. */
8677 fpstate = gfc_save_fp_state (&se->pre);
8679 /* Make the function call. */
8680 call = build_call_expr_loc (input_location, decl, 1, arg);
8681 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
8683 /* Restore floating-point state. */
8684 gfc_restore_fp_state (&se->post, fpstate);
8688 /* Generate code for IEEE_REM. */
8690 static void
8691 conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
8693 tree args[2], decl, call, fpstate;
8694 int argprec;
8696 conv_ieee_function_args (se, expr, args, 2);
8698 /* If arguments have unequal size, convert them to the larger. */
8699 if (TYPE_PRECISION (TREE_TYPE (args[0]))
8700 > TYPE_PRECISION (TREE_TYPE (args[1])))
8701 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8702 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
8703 > TYPE_PRECISION (TREE_TYPE (args[0])))
8704 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
8706 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8707 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
8709 /* Save floating-point state. */
8710 fpstate = gfc_save_fp_state (&se->pre);
8712 /* Make the function call. */
8713 call = build_call_expr_loc_array (input_location, decl, 2, args);
8714 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8716 /* Restore floating-point state. */
8717 gfc_restore_fp_state (&se->post, fpstate);
8721 /* Generate code for IEEE_NEXT_AFTER. */
8723 static void
8724 conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
8726 tree args[2], decl, call, fpstate;
8727 int argprec;
8729 conv_ieee_function_args (se, expr, args, 2);
8731 /* Result has the characteristics of first argument. */
8732 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8733 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8734 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
8736 /* Save floating-point state. */
8737 fpstate = gfc_save_fp_state (&se->pre);
8739 /* Make the function call. */
8740 call = build_call_expr_loc_array (input_location, decl, 2, args);
8741 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8743 /* Restore floating-point state. */
8744 gfc_restore_fp_state (&se->post, fpstate);
8748 /* Generate code for IEEE_SCALB. */
8750 static void
8751 conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
8753 tree args[2], decl, call, huge, type;
8754 int argprec, n;
8756 conv_ieee_function_args (se, expr, args, 2);
8758 /* Result has the characteristics of first argument. */
8759 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8760 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
8762 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
8764 /* We need to fold the integer into the range of a C int. */
8765 args[1] = gfc_evaluate_now (args[1], &se->pre);
8766 type = TREE_TYPE (args[1]);
8768 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
8769 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
8770 gfc_c_int_kind);
8771 huge = fold_convert (type, huge);
8772 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
8773 huge);
8774 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
8775 fold_build1_loc (input_location, NEGATE_EXPR,
8776 type, huge));
8779 args[1] = fold_convert (integer_type_node, args[1]);
8781 /* Make the function call. */
8782 call = build_call_expr_loc_array (input_location, decl, 2, args);
8783 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8787 /* Generate code for IEEE_COPY_SIGN. */
8789 static void
8790 conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
8792 tree args[2], decl, sign;
8793 int argprec;
8795 conv_ieee_function_args (se, expr, args, 2);
8797 /* Get the sign of the second argument. */
8798 sign = build_call_expr_loc (input_location,
8799 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8800 1, args[1]);
8801 sign = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8802 sign, integer_zero_node);
8804 /* Create a value of one, with the right sign. */
8805 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
8806 sign,
8807 fold_build1_loc (input_location, NEGATE_EXPR,
8808 integer_type_node,
8809 integer_one_node),
8810 integer_one_node);
8811 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
8813 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8814 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
8816 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
8820 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
8821 module. */
8823 bool
8824 gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
8826 const char *name = expr->value.function.name;
8828 #define STARTS_WITH(A,B) (strncmp((A), (B), strlen(B)) == 0)
8830 if (STARTS_WITH (name, "_gfortran_ieee_is_nan"))
8831 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
8832 else if (STARTS_WITH (name, "_gfortran_ieee_is_finite"))
8833 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
8834 else if (STARTS_WITH (name, "_gfortran_ieee_unordered"))
8835 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
8836 else if (STARTS_WITH (name, "_gfortran_ieee_is_normal"))
8837 conv_intrinsic_ieee_is_normal (se, expr);
8838 else if (STARTS_WITH (name, "_gfortran_ieee_is_negative"))
8839 conv_intrinsic_ieee_is_negative (se, expr);
8840 else if (STARTS_WITH (name, "_gfortran_ieee_copy_sign"))
8841 conv_intrinsic_ieee_copy_sign (se, expr);
8842 else if (STARTS_WITH (name, "_gfortran_ieee_scalb"))
8843 conv_intrinsic_ieee_scalb (se, expr);
8844 else if (STARTS_WITH (name, "_gfortran_ieee_next_after"))
8845 conv_intrinsic_ieee_next_after (se, expr);
8846 else if (STARTS_WITH (name, "_gfortran_ieee_rem"))
8847 conv_intrinsic_ieee_rem (se, expr);
8848 else if (STARTS_WITH (name, "_gfortran_ieee_logb"))
8849 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
8850 else if (STARTS_WITH (name, "_gfortran_ieee_rint"))
8851 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
8852 else
8853 /* It is not among the functions we translate directly. We return
8854 false, so a library function call is emitted. */
8855 return false;
8857 #undef STARTS_WITH
8859 return true;
8863 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
8865 static void
8866 gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
8868 tree arg, res, restype;
8870 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8871 arg = fold_convert (size_type_node, arg);
8872 res = build_call_expr_loc (input_location,
8873 builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
8874 restype = gfc_typenode_for_spec (&expr->ts);
8875 se->expr = fold_convert (restype, res);
8879 /* Generate code for an intrinsic function. Some map directly to library
8880 calls, others get special handling. In some cases the name of the function
8881 used depends on the type specifiers. */
8883 void
8884 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
8886 const char *name;
8887 int lib, kind;
8888 tree fndecl;
8890 name = &expr->value.function.name[2];
8892 if (expr->rank > 0)
8894 lib = gfc_is_intrinsic_libcall (expr);
8895 if (lib != 0)
8897 if (lib == 1)
8898 se->ignore_optional = 1;
8900 switch (expr->value.function.isym->id)
8902 case GFC_ISYM_EOSHIFT:
8903 case GFC_ISYM_PACK:
8904 case GFC_ISYM_RESHAPE:
8905 /* For all of those the first argument specifies the type and the
8906 third is optional. */
8907 conv_generic_with_optional_char_arg (se, expr, 1, 3);
8908 break;
8910 case GFC_ISYM_MINLOC:
8911 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
8912 break;
8914 case GFC_ISYM_MAXLOC:
8915 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
8916 break;
8918 case GFC_ISYM_SHAPE:
8919 gfc_conv_intrinsic_shape (se, expr);
8920 break;
8922 default:
8923 gfc_conv_intrinsic_funcall (se, expr);
8924 break;
8927 return;
8931 switch (expr->value.function.isym->id)
8933 case GFC_ISYM_NONE:
8934 gcc_unreachable ();
8936 case GFC_ISYM_REPEAT:
8937 gfc_conv_intrinsic_repeat (se, expr);
8938 break;
8940 case GFC_ISYM_TRIM:
8941 gfc_conv_intrinsic_trim (se, expr);
8942 break;
8944 case GFC_ISYM_SC_KIND:
8945 gfc_conv_intrinsic_sc_kind (se, expr);
8946 break;
8948 case GFC_ISYM_SI_KIND:
8949 gfc_conv_intrinsic_si_kind (se, expr);
8950 break;
8952 case GFC_ISYM_SR_KIND:
8953 gfc_conv_intrinsic_sr_kind (se, expr);
8954 break;
8956 case GFC_ISYM_EXPONENT:
8957 gfc_conv_intrinsic_exponent (se, expr);
8958 break;
8960 case GFC_ISYM_SCAN:
8961 kind = expr->value.function.actual->expr->ts.kind;
8962 if (kind == 1)
8963 fndecl = gfor_fndecl_string_scan;
8964 else if (kind == 4)
8965 fndecl = gfor_fndecl_string_scan_char4;
8966 else
8967 gcc_unreachable ();
8969 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
8970 break;
8972 case GFC_ISYM_VERIFY:
8973 kind = expr->value.function.actual->expr->ts.kind;
8974 if (kind == 1)
8975 fndecl = gfor_fndecl_string_verify;
8976 else if (kind == 4)
8977 fndecl = gfor_fndecl_string_verify_char4;
8978 else
8979 gcc_unreachable ();
8981 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
8982 break;
8984 case GFC_ISYM_ALLOCATED:
8985 gfc_conv_allocated (se, expr);
8986 break;
8988 case GFC_ISYM_ASSOCIATED:
8989 gfc_conv_associated(se, expr);
8990 break;
8992 case GFC_ISYM_SAME_TYPE_AS:
8993 gfc_conv_same_type_as (se, expr);
8994 break;
8996 case GFC_ISYM_ABS:
8997 gfc_conv_intrinsic_abs (se, expr);
8998 break;
9000 case GFC_ISYM_ADJUSTL:
9001 if (expr->ts.kind == 1)
9002 fndecl = gfor_fndecl_adjustl;
9003 else if (expr->ts.kind == 4)
9004 fndecl = gfor_fndecl_adjustl_char4;
9005 else
9006 gcc_unreachable ();
9008 gfc_conv_intrinsic_adjust (se, expr, fndecl);
9009 break;
9011 case GFC_ISYM_ADJUSTR:
9012 if (expr->ts.kind == 1)
9013 fndecl = gfor_fndecl_adjustr;
9014 else if (expr->ts.kind == 4)
9015 fndecl = gfor_fndecl_adjustr_char4;
9016 else
9017 gcc_unreachable ();
9019 gfc_conv_intrinsic_adjust (se, expr, fndecl);
9020 break;
9022 case GFC_ISYM_AIMAG:
9023 gfc_conv_intrinsic_imagpart (se, expr);
9024 break;
9026 case GFC_ISYM_AINT:
9027 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
9028 break;
9030 case GFC_ISYM_ALL:
9031 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
9032 break;
9034 case GFC_ISYM_ANINT:
9035 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
9036 break;
9038 case GFC_ISYM_AND:
9039 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
9040 break;
9042 case GFC_ISYM_ANY:
9043 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
9044 break;
9046 case GFC_ISYM_BTEST:
9047 gfc_conv_intrinsic_btest (se, expr);
9048 break;
9050 case GFC_ISYM_BGE:
9051 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
9052 break;
9054 case GFC_ISYM_BGT:
9055 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
9056 break;
9058 case GFC_ISYM_BLE:
9059 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
9060 break;
9062 case GFC_ISYM_BLT:
9063 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
9064 break;
9066 case GFC_ISYM_C_ASSOCIATED:
9067 case GFC_ISYM_C_FUNLOC:
9068 case GFC_ISYM_C_LOC:
9069 conv_isocbinding_function (se, expr);
9070 break;
9072 case GFC_ISYM_ACHAR:
9073 case GFC_ISYM_CHAR:
9074 gfc_conv_intrinsic_char (se, expr);
9075 break;
9077 case GFC_ISYM_CONVERSION:
9078 case GFC_ISYM_REAL:
9079 case GFC_ISYM_LOGICAL:
9080 case GFC_ISYM_DBLE:
9081 gfc_conv_intrinsic_conversion (se, expr);
9082 break;
9084 /* Integer conversions are handled separately to make sure we get the
9085 correct rounding mode. */
9086 case GFC_ISYM_INT:
9087 case GFC_ISYM_INT2:
9088 case GFC_ISYM_INT8:
9089 case GFC_ISYM_LONG:
9090 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
9091 break;
9093 case GFC_ISYM_NINT:
9094 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
9095 break;
9097 case GFC_ISYM_CEILING:
9098 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
9099 break;
9101 case GFC_ISYM_FLOOR:
9102 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
9103 break;
9105 case GFC_ISYM_MOD:
9106 gfc_conv_intrinsic_mod (se, expr, 0);
9107 break;
9109 case GFC_ISYM_MODULO:
9110 gfc_conv_intrinsic_mod (se, expr, 1);
9111 break;
9113 case GFC_ISYM_CAF_GET:
9114 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
9115 false, NULL);
9116 break;
9118 case GFC_ISYM_CMPLX:
9119 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
9120 break;
9122 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
9123 gfc_conv_intrinsic_iargc (se, expr);
9124 break;
9126 case GFC_ISYM_COMPLEX:
9127 gfc_conv_intrinsic_cmplx (se, expr, 1);
9128 break;
9130 case GFC_ISYM_CONJG:
9131 gfc_conv_intrinsic_conjg (se, expr);
9132 break;
9134 case GFC_ISYM_COUNT:
9135 gfc_conv_intrinsic_count (se, expr);
9136 break;
9138 case GFC_ISYM_CTIME:
9139 gfc_conv_intrinsic_ctime (se, expr);
9140 break;
9142 case GFC_ISYM_DIM:
9143 gfc_conv_intrinsic_dim (se, expr);
9144 break;
9146 case GFC_ISYM_DOT_PRODUCT:
9147 gfc_conv_intrinsic_dot_product (se, expr);
9148 break;
9150 case GFC_ISYM_DPROD:
9151 gfc_conv_intrinsic_dprod (se, expr);
9152 break;
9154 case GFC_ISYM_DSHIFTL:
9155 gfc_conv_intrinsic_dshift (se, expr, true);
9156 break;
9158 case GFC_ISYM_DSHIFTR:
9159 gfc_conv_intrinsic_dshift (se, expr, false);
9160 break;
9162 case GFC_ISYM_FDATE:
9163 gfc_conv_intrinsic_fdate (se, expr);
9164 break;
9166 case GFC_ISYM_FRACTION:
9167 gfc_conv_intrinsic_fraction (se, expr);
9168 break;
9170 case GFC_ISYM_IALL:
9171 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
9172 break;
9174 case GFC_ISYM_IAND:
9175 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
9176 break;
9178 case GFC_ISYM_IANY:
9179 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
9180 break;
9182 case GFC_ISYM_IBCLR:
9183 gfc_conv_intrinsic_singlebitop (se, expr, 0);
9184 break;
9186 case GFC_ISYM_IBITS:
9187 gfc_conv_intrinsic_ibits (se, expr);
9188 break;
9190 case GFC_ISYM_IBSET:
9191 gfc_conv_intrinsic_singlebitop (se, expr, 1);
9192 break;
9194 case GFC_ISYM_IACHAR:
9195 case GFC_ISYM_ICHAR:
9196 /* We assume ASCII character sequence. */
9197 gfc_conv_intrinsic_ichar (se, expr);
9198 break;
9200 case GFC_ISYM_IARGC:
9201 gfc_conv_intrinsic_iargc (se, expr);
9202 break;
9204 case GFC_ISYM_IEOR:
9205 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9206 break;
9208 case GFC_ISYM_INDEX:
9209 kind = expr->value.function.actual->expr->ts.kind;
9210 if (kind == 1)
9211 fndecl = gfor_fndecl_string_index;
9212 else if (kind == 4)
9213 fndecl = gfor_fndecl_string_index_char4;
9214 else
9215 gcc_unreachable ();
9217 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
9218 break;
9220 case GFC_ISYM_IOR:
9221 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9222 break;
9224 case GFC_ISYM_IPARITY:
9225 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
9226 break;
9228 case GFC_ISYM_IS_IOSTAT_END:
9229 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
9230 break;
9232 case GFC_ISYM_IS_IOSTAT_EOR:
9233 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
9234 break;
9236 case GFC_ISYM_ISNAN:
9237 gfc_conv_intrinsic_isnan (se, expr);
9238 break;
9240 case GFC_ISYM_KILL:
9241 conv_intrinsic_kill (se, expr);
9242 break;
9244 case GFC_ISYM_LSHIFT:
9245 gfc_conv_intrinsic_shift (se, expr, false, false);
9246 break;
9248 case GFC_ISYM_RSHIFT:
9249 gfc_conv_intrinsic_shift (se, expr, true, true);
9250 break;
9252 case GFC_ISYM_SHIFTA:
9253 gfc_conv_intrinsic_shift (se, expr, true, true);
9254 break;
9256 case GFC_ISYM_SHIFTL:
9257 gfc_conv_intrinsic_shift (se, expr, false, false);
9258 break;
9260 case GFC_ISYM_SHIFTR:
9261 gfc_conv_intrinsic_shift (se, expr, true, false);
9262 break;
9264 case GFC_ISYM_ISHFT:
9265 gfc_conv_intrinsic_ishft (se, expr);
9266 break;
9268 case GFC_ISYM_ISHFTC:
9269 gfc_conv_intrinsic_ishftc (se, expr);
9270 break;
9272 case GFC_ISYM_LEADZ:
9273 gfc_conv_intrinsic_leadz (se, expr);
9274 break;
9276 case GFC_ISYM_TRAILZ:
9277 gfc_conv_intrinsic_trailz (se, expr);
9278 break;
9280 case GFC_ISYM_POPCNT:
9281 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
9282 break;
9284 case GFC_ISYM_POPPAR:
9285 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
9286 break;
9288 case GFC_ISYM_LBOUND:
9289 gfc_conv_intrinsic_bound (se, expr, 0);
9290 break;
9292 case GFC_ISYM_LCOBOUND:
9293 conv_intrinsic_cobound (se, expr);
9294 break;
9296 case GFC_ISYM_TRANSPOSE:
9297 /* The scalarizer has already been set up for reversed dimension access
9298 order ; now we just get the argument value normally. */
9299 gfc_conv_expr (se, expr->value.function.actual->expr);
9300 break;
9302 case GFC_ISYM_LEN:
9303 gfc_conv_intrinsic_len (se, expr);
9304 break;
9306 case GFC_ISYM_LEN_TRIM:
9307 gfc_conv_intrinsic_len_trim (se, expr);
9308 break;
9310 case GFC_ISYM_LGE:
9311 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
9312 break;
9314 case GFC_ISYM_LGT:
9315 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
9316 break;
9318 case GFC_ISYM_LLE:
9319 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
9320 break;
9322 case GFC_ISYM_LLT:
9323 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
9324 break;
9326 case GFC_ISYM_MALLOC:
9327 gfc_conv_intrinsic_malloc (se, expr);
9328 break;
9330 case GFC_ISYM_MASKL:
9331 gfc_conv_intrinsic_mask (se, expr, 1);
9332 break;
9334 case GFC_ISYM_MASKR:
9335 gfc_conv_intrinsic_mask (se, expr, 0);
9336 break;
9338 case GFC_ISYM_MAX:
9339 if (expr->ts.type == BT_CHARACTER)
9340 gfc_conv_intrinsic_minmax_char (se, expr, 1);
9341 else
9342 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
9343 break;
9345 case GFC_ISYM_MAXLOC:
9346 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
9347 break;
9349 case GFC_ISYM_MAXVAL:
9350 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
9351 break;
9353 case GFC_ISYM_MERGE:
9354 gfc_conv_intrinsic_merge (se, expr);
9355 break;
9357 case GFC_ISYM_MERGE_BITS:
9358 gfc_conv_intrinsic_merge_bits (se, expr);
9359 break;
9361 case GFC_ISYM_MIN:
9362 if (expr->ts.type == BT_CHARACTER)
9363 gfc_conv_intrinsic_minmax_char (se, expr, -1);
9364 else
9365 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
9366 break;
9368 case GFC_ISYM_MINLOC:
9369 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
9370 break;
9372 case GFC_ISYM_MINVAL:
9373 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
9374 break;
9376 case GFC_ISYM_NEAREST:
9377 gfc_conv_intrinsic_nearest (se, expr);
9378 break;
9380 case GFC_ISYM_NORM2:
9381 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
9382 break;
9384 case GFC_ISYM_NOT:
9385 gfc_conv_intrinsic_not (se, expr);
9386 break;
9388 case GFC_ISYM_OR:
9389 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9390 break;
9392 case GFC_ISYM_PARITY:
9393 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
9394 break;
9396 case GFC_ISYM_PRESENT:
9397 gfc_conv_intrinsic_present (se, expr);
9398 break;
9400 case GFC_ISYM_PRODUCT:
9401 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
9402 break;
9404 case GFC_ISYM_RANK:
9405 gfc_conv_intrinsic_rank (se, expr);
9406 break;
9408 case GFC_ISYM_RRSPACING:
9409 gfc_conv_intrinsic_rrspacing (se, expr);
9410 break;
9412 case GFC_ISYM_SET_EXPONENT:
9413 gfc_conv_intrinsic_set_exponent (se, expr);
9414 break;
9416 case GFC_ISYM_SCALE:
9417 gfc_conv_intrinsic_scale (se, expr);
9418 break;
9420 case GFC_ISYM_SIGN:
9421 gfc_conv_intrinsic_sign (se, expr);
9422 break;
9424 case GFC_ISYM_SIZE:
9425 gfc_conv_intrinsic_size (se, expr);
9426 break;
9428 case GFC_ISYM_SIZEOF:
9429 case GFC_ISYM_C_SIZEOF:
9430 gfc_conv_intrinsic_sizeof (se, expr);
9431 break;
9433 case GFC_ISYM_STORAGE_SIZE:
9434 gfc_conv_intrinsic_storage_size (se, expr);
9435 break;
9437 case GFC_ISYM_SPACING:
9438 gfc_conv_intrinsic_spacing (se, expr);
9439 break;
9441 case GFC_ISYM_STRIDE:
9442 conv_intrinsic_stride (se, expr);
9443 break;
9445 case GFC_ISYM_SUM:
9446 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
9447 break;
9449 case GFC_ISYM_TEAM_NUMBER:
9450 conv_intrinsic_team_number (se, expr);
9451 break;
9453 case GFC_ISYM_TRANSFER:
9454 if (se->ss && se->ss->info->useflags)
9455 /* Access the previously obtained result. */
9456 gfc_conv_tmp_array_ref (se);
9457 else
9458 gfc_conv_intrinsic_transfer (se, expr);
9459 break;
9461 case GFC_ISYM_TTYNAM:
9462 gfc_conv_intrinsic_ttynam (se, expr);
9463 break;
9465 case GFC_ISYM_UBOUND:
9466 gfc_conv_intrinsic_bound (se, expr, 1);
9467 break;
9469 case GFC_ISYM_UCOBOUND:
9470 conv_intrinsic_cobound (se, expr);
9471 break;
9473 case GFC_ISYM_XOR:
9474 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9475 break;
9477 case GFC_ISYM_LOC:
9478 gfc_conv_intrinsic_loc (se, expr);
9479 break;
9481 case GFC_ISYM_THIS_IMAGE:
9482 /* For num_images() == 1, handle as LCOBOUND. */
9483 if (expr->value.function.actual->expr
9484 && flag_coarray == GFC_FCOARRAY_SINGLE)
9485 conv_intrinsic_cobound (se, expr);
9486 else
9487 trans_this_image (se, expr);
9488 break;
9490 case GFC_ISYM_IMAGE_INDEX:
9491 trans_image_index (se, expr);
9492 break;
9494 case GFC_ISYM_IMAGE_STATUS:
9495 conv_intrinsic_image_status (se, expr);
9496 break;
9498 case GFC_ISYM_NUM_IMAGES:
9499 trans_num_images (se, expr);
9500 break;
9502 case GFC_ISYM_ACCESS:
9503 case GFC_ISYM_CHDIR:
9504 case GFC_ISYM_CHMOD:
9505 case GFC_ISYM_DTIME:
9506 case GFC_ISYM_ETIME:
9507 case GFC_ISYM_EXTENDS_TYPE_OF:
9508 case GFC_ISYM_FGET:
9509 case GFC_ISYM_FGETC:
9510 case GFC_ISYM_FNUM:
9511 case GFC_ISYM_FPUT:
9512 case GFC_ISYM_FPUTC:
9513 case GFC_ISYM_FSTAT:
9514 case GFC_ISYM_FTELL:
9515 case GFC_ISYM_GETCWD:
9516 case GFC_ISYM_GETGID:
9517 case GFC_ISYM_GETPID:
9518 case GFC_ISYM_GETUID:
9519 case GFC_ISYM_HOSTNM:
9520 case GFC_ISYM_IERRNO:
9521 case GFC_ISYM_IRAND:
9522 case GFC_ISYM_ISATTY:
9523 case GFC_ISYM_JN2:
9524 case GFC_ISYM_LINK:
9525 case GFC_ISYM_LSTAT:
9526 case GFC_ISYM_MATMUL:
9527 case GFC_ISYM_MCLOCK:
9528 case GFC_ISYM_MCLOCK8:
9529 case GFC_ISYM_RAND:
9530 case GFC_ISYM_RENAME:
9531 case GFC_ISYM_SECOND:
9532 case GFC_ISYM_SECNDS:
9533 case GFC_ISYM_SIGNAL:
9534 case GFC_ISYM_STAT:
9535 case GFC_ISYM_SYMLNK:
9536 case GFC_ISYM_SYSTEM:
9537 case GFC_ISYM_TIME:
9538 case GFC_ISYM_TIME8:
9539 case GFC_ISYM_UMASK:
9540 case GFC_ISYM_UNLINK:
9541 case GFC_ISYM_YN2:
9542 gfc_conv_intrinsic_funcall (se, expr);
9543 break;
9545 case GFC_ISYM_EOSHIFT:
9546 case GFC_ISYM_PACK:
9547 case GFC_ISYM_RESHAPE:
9548 /* For those, expr->rank should always be >0 and thus the if above the
9549 switch should have matched. */
9550 gcc_unreachable ();
9551 break;
9553 default:
9554 gfc_conv_intrinsic_lib_function (se, expr);
9555 break;
9560 static gfc_ss *
9561 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
9563 gfc_ss *arg_ss, *tmp_ss;
9564 gfc_actual_arglist *arg;
9566 arg = expr->value.function.actual;
9568 gcc_assert (arg->expr);
9570 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
9571 gcc_assert (arg_ss != gfc_ss_terminator);
9573 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
9575 if (tmp_ss->info->type != GFC_SS_SCALAR
9576 && tmp_ss->info->type != GFC_SS_REFERENCE)
9578 gcc_assert (tmp_ss->dimen == 2);
9580 /* We just invert dimensions. */
9581 std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
9584 /* Stop when tmp_ss points to the last valid element of the chain... */
9585 if (tmp_ss->next == gfc_ss_terminator)
9586 break;
9589 /* ... so that we can attach the rest of the chain to it. */
9590 tmp_ss->next = ss;
9592 return arg_ss;
9596 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
9597 This has the side effect of reversing the nested list, so there is no
9598 need to call gfc_reverse_ss on it (the given list is assumed not to be
9599 reversed yet). */
9601 static gfc_ss *
9602 nest_loop_dimension (gfc_ss *ss, int dim)
9604 int ss_dim, i;
9605 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
9606 gfc_loopinfo *new_loop;
9608 gcc_assert (ss != gfc_ss_terminator);
9610 for (; ss != gfc_ss_terminator; ss = ss->next)
9612 new_ss = gfc_get_ss ();
9613 new_ss->next = prev_ss;
9614 new_ss->parent = ss;
9615 new_ss->info = ss->info;
9616 new_ss->info->refcount++;
9617 if (ss->dimen != 0)
9619 gcc_assert (ss->info->type != GFC_SS_SCALAR
9620 && ss->info->type != GFC_SS_REFERENCE);
9622 new_ss->dimen = 1;
9623 new_ss->dim[0] = ss->dim[dim];
9625 gcc_assert (dim < ss->dimen);
9627 ss_dim = --ss->dimen;
9628 for (i = dim; i < ss_dim; i++)
9629 ss->dim[i] = ss->dim[i + 1];
9631 ss->dim[ss_dim] = 0;
9633 prev_ss = new_ss;
9635 if (ss->nested_ss)
9637 ss->nested_ss->parent = new_ss;
9638 new_ss->nested_ss = ss->nested_ss;
9640 ss->nested_ss = new_ss;
9643 new_loop = gfc_get_loopinfo ();
9644 gfc_init_loopinfo (new_loop);
9646 gcc_assert (prev_ss != NULL);
9647 gcc_assert (prev_ss != gfc_ss_terminator);
9648 gfc_add_ss_to_loop (new_loop, prev_ss);
9649 return new_ss->parent;
9653 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
9654 is to be inlined. */
9656 static gfc_ss *
9657 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
9659 gfc_ss *tmp_ss, *tail, *array_ss;
9660 gfc_actual_arglist *arg1, *arg2, *arg3;
9661 int sum_dim;
9662 bool scalar_mask = false;
9664 /* The rank of the result will be determined later. */
9665 arg1 = expr->value.function.actual;
9666 arg2 = arg1->next;
9667 arg3 = arg2->next;
9668 gcc_assert (arg3 != NULL);
9670 if (expr->rank == 0)
9671 return ss;
9673 tmp_ss = gfc_ss_terminator;
9675 if (arg3->expr)
9677 gfc_ss *mask_ss;
9679 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
9680 if (mask_ss == tmp_ss)
9681 scalar_mask = 1;
9683 tmp_ss = mask_ss;
9686 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
9687 gcc_assert (array_ss != tmp_ss);
9689 /* Odd thing: If the mask is scalar, it is used by the frontend after
9690 the array (to make an if around the nested loop). Thus it shall
9691 be after array_ss once the gfc_ss list is reversed. */
9692 if (scalar_mask)
9693 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
9694 else
9695 tmp_ss = array_ss;
9697 /* "Hide" the dimension on which we will sum in the first arg's scalarization
9698 chain. */
9699 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
9700 tail = nest_loop_dimension (tmp_ss, sum_dim);
9701 tail->next = ss;
9703 return tmp_ss;
9707 static gfc_ss *
9708 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
9711 switch (expr->value.function.isym->id)
9713 case GFC_ISYM_PRODUCT:
9714 case GFC_ISYM_SUM:
9715 return walk_inline_intrinsic_arith (ss, expr);
9717 case GFC_ISYM_TRANSPOSE:
9718 return walk_inline_intrinsic_transpose (ss, expr);
9720 default:
9721 gcc_unreachable ();
9723 gcc_unreachable ();
9727 /* This generates code to execute before entering the scalarization loop.
9728 Currently does nothing. */
9730 void
9731 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
9733 switch (ss->info->expr->value.function.isym->id)
9735 case GFC_ISYM_UBOUND:
9736 case GFC_ISYM_LBOUND:
9737 case GFC_ISYM_UCOBOUND:
9738 case GFC_ISYM_LCOBOUND:
9739 case GFC_ISYM_THIS_IMAGE:
9740 break;
9742 default:
9743 gcc_unreachable ();
9748 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
9749 are expanded into code inside the scalarization loop. */
9751 static gfc_ss *
9752 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
9754 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
9755 gfc_add_class_array_ref (expr->value.function.actual->expr);
9757 /* The two argument version returns a scalar. */
9758 if (expr->value.function.actual->next->expr)
9759 return ss;
9761 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
9765 /* Walk an intrinsic array libcall. */
9767 static gfc_ss *
9768 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
9770 gcc_assert (expr->rank > 0);
9771 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
9775 /* Return whether the function call expression EXPR will be expanded
9776 inline by gfc_conv_intrinsic_function. */
9778 bool
9779 gfc_inline_intrinsic_function_p (gfc_expr *expr)
9781 gfc_actual_arglist *args;
9783 if (!expr->value.function.isym)
9784 return false;
9786 switch (expr->value.function.isym->id)
9788 case GFC_ISYM_PRODUCT:
9789 case GFC_ISYM_SUM:
9790 /* Disable inline expansion if code size matters. */
9791 if (optimize_size)
9792 return false;
9794 args = expr->value.function.actual;
9795 /* We need to be able to subset the SUM argument at compile-time. */
9796 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
9797 return false;
9799 return true;
9801 case GFC_ISYM_TRANSPOSE:
9802 return true;
9804 default:
9805 return false;
9810 /* Returns nonzero if the specified intrinsic function call maps directly to
9811 an external library call. Should only be used for functions that return
9812 arrays. */
9815 gfc_is_intrinsic_libcall (gfc_expr * expr)
9817 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
9818 gcc_assert (expr->rank > 0);
9820 if (gfc_inline_intrinsic_function_p (expr))
9821 return 0;
9823 switch (expr->value.function.isym->id)
9825 case GFC_ISYM_ALL:
9826 case GFC_ISYM_ANY:
9827 case GFC_ISYM_COUNT:
9828 case GFC_ISYM_JN2:
9829 case GFC_ISYM_IANY:
9830 case GFC_ISYM_IALL:
9831 case GFC_ISYM_IPARITY:
9832 case GFC_ISYM_MATMUL:
9833 case GFC_ISYM_MAXLOC:
9834 case GFC_ISYM_MAXVAL:
9835 case GFC_ISYM_MINLOC:
9836 case GFC_ISYM_MINVAL:
9837 case GFC_ISYM_NORM2:
9838 case GFC_ISYM_PARITY:
9839 case GFC_ISYM_PRODUCT:
9840 case GFC_ISYM_SUM:
9841 case GFC_ISYM_SHAPE:
9842 case GFC_ISYM_SPREAD:
9843 case GFC_ISYM_YN2:
9844 /* Ignore absent optional parameters. */
9845 return 1;
9847 case GFC_ISYM_CSHIFT:
9848 case GFC_ISYM_EOSHIFT:
9849 case GFC_ISYM_GET_TEAM:
9850 case GFC_ISYM_FAILED_IMAGES:
9851 case GFC_ISYM_STOPPED_IMAGES:
9852 case GFC_ISYM_PACK:
9853 case GFC_ISYM_RESHAPE:
9854 case GFC_ISYM_UNPACK:
9855 /* Pass absent optional parameters. */
9856 return 2;
9858 default:
9859 return 0;
9863 /* Walk an intrinsic function. */
9864 gfc_ss *
9865 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
9866 gfc_intrinsic_sym * isym)
9868 gcc_assert (isym);
9870 if (isym->elemental)
9871 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
9872 NULL, GFC_SS_SCALAR);
9874 if (expr->rank == 0)
9875 return ss;
9877 if (gfc_inline_intrinsic_function_p (expr))
9878 return walk_inline_intrinsic_function (ss, expr);
9880 if (gfc_is_intrinsic_libcall (expr))
9881 return gfc_walk_intrinsic_libfunc (ss, expr);
9883 /* Special cases. */
9884 switch (isym->id)
9886 case GFC_ISYM_LBOUND:
9887 case GFC_ISYM_LCOBOUND:
9888 case GFC_ISYM_UBOUND:
9889 case GFC_ISYM_UCOBOUND:
9890 case GFC_ISYM_THIS_IMAGE:
9891 return gfc_walk_intrinsic_bound (ss, expr);
9893 case GFC_ISYM_TRANSFER:
9894 case GFC_ISYM_CAF_GET:
9895 return gfc_walk_intrinsic_libfunc (ss, expr);
9897 default:
9898 /* This probably meant someone forgot to add an intrinsic to the above
9899 list(s) when they implemented it, or something's gone horribly
9900 wrong. */
9901 gcc_unreachable ();
9906 static tree
9907 conv_co_collective (gfc_code *code)
9909 gfc_se argse;
9910 stmtblock_t block, post_block;
9911 tree fndecl, array, strlen, image_index, stat, errmsg, errmsg_len;
9912 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
9914 gfc_start_block (&block);
9915 gfc_init_block (&post_block);
9917 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
9919 opr_expr = code->ext.actual->next->expr;
9920 image_idx_expr = code->ext.actual->next->next->expr;
9921 stat_expr = code->ext.actual->next->next->next->expr;
9922 errmsg_expr = code->ext.actual->next->next->next->next->expr;
9924 else
9926 opr_expr = NULL;
9927 image_idx_expr = code->ext.actual->next->expr;
9928 stat_expr = code->ext.actual->next->next->expr;
9929 errmsg_expr = code->ext.actual->next->next->next->expr;
9932 /* stat. */
9933 if (stat_expr)
9935 gfc_init_se (&argse, NULL);
9936 gfc_conv_expr (&argse, stat_expr);
9937 gfc_add_block_to_block (&block, &argse.pre);
9938 gfc_add_block_to_block (&post_block, &argse.post);
9939 stat = argse.expr;
9940 if (flag_coarray != GFC_FCOARRAY_SINGLE)
9941 stat = gfc_build_addr_expr (NULL_TREE, stat);
9943 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
9944 stat = NULL_TREE;
9945 else
9946 stat = null_pointer_node;
9948 /* Early exit for GFC_FCOARRAY_SINGLE. */
9949 if (flag_coarray == GFC_FCOARRAY_SINGLE)
9951 if (stat != NULL_TREE)
9952 gfc_add_modify (&block, stat,
9953 fold_convert (TREE_TYPE (stat), integer_zero_node));
9954 return gfc_finish_block (&block);
9957 /* Handle the array. */
9958 gfc_init_se (&argse, NULL);
9959 if (code->ext.actual->expr->rank == 0)
9961 symbol_attribute attr;
9962 gfc_clear_attr (&attr);
9963 gfc_init_se (&argse, NULL);
9964 gfc_conv_expr (&argse, code->ext.actual->expr);
9965 gfc_add_block_to_block (&block, &argse.pre);
9966 gfc_add_block_to_block (&post_block, &argse.post);
9967 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
9968 array = gfc_build_addr_expr (NULL_TREE, array);
9970 else
9972 argse.want_pointer = 1;
9973 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
9974 array = argse.expr;
9976 gfc_add_block_to_block (&block, &argse.pre);
9977 gfc_add_block_to_block (&post_block, &argse.post);
9979 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
9980 strlen = argse.string_length;
9981 else
9982 strlen = integer_zero_node;
9984 /* image_index. */
9985 if (image_idx_expr)
9987 gfc_init_se (&argse, NULL);
9988 gfc_conv_expr (&argse, image_idx_expr);
9989 gfc_add_block_to_block (&block, &argse.pre);
9990 gfc_add_block_to_block (&post_block, &argse.post);
9991 image_index = fold_convert (integer_type_node, argse.expr);
9993 else
9994 image_index = integer_zero_node;
9996 /* errmsg. */
9997 if (errmsg_expr)
9999 gfc_init_se (&argse, NULL);
10000 gfc_conv_expr (&argse, errmsg_expr);
10001 gfc_add_block_to_block (&block, &argse.pre);
10002 gfc_add_block_to_block (&post_block, &argse.post);
10003 errmsg = argse.expr;
10004 errmsg_len = fold_convert (size_type_node, argse.string_length);
10006 else
10008 errmsg = null_pointer_node;
10009 errmsg_len = build_zero_cst (size_type_node);
10012 /* Generate the function call. */
10013 switch (code->resolved_isym->id)
10015 case GFC_ISYM_CO_BROADCAST:
10016 fndecl = gfor_fndecl_co_broadcast;
10017 break;
10018 case GFC_ISYM_CO_MAX:
10019 fndecl = gfor_fndecl_co_max;
10020 break;
10021 case GFC_ISYM_CO_MIN:
10022 fndecl = gfor_fndecl_co_min;
10023 break;
10024 case GFC_ISYM_CO_REDUCE:
10025 fndecl = gfor_fndecl_co_reduce;
10026 break;
10027 case GFC_ISYM_CO_SUM:
10028 fndecl = gfor_fndecl_co_sum;
10029 break;
10030 default:
10031 gcc_unreachable ();
10034 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
10035 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
10036 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
10037 image_index, stat, errmsg, errmsg_len);
10038 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
10039 fndecl = build_call_expr_loc (input_location, fndecl, 6, array, image_index,
10040 stat, errmsg, strlen, errmsg_len);
10041 else
10043 tree opr, opr_flags;
10045 // FIXME: Handle TS29113's bind(C) strings with descriptor.
10046 int opr_flag_int;
10047 if (gfc_is_proc_ptr_comp (opr_expr))
10049 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
10050 opr_flag_int = sym->attr.dimension
10051 || (sym->ts.type == BT_CHARACTER
10052 && !sym->attr.is_bind_c)
10053 ? GFC_CAF_BYREF : 0;
10054 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
10055 && !sym->attr.is_bind_c
10056 ? GFC_CAF_HIDDENLEN : 0;
10057 opr_flag_int |= sym->formal->sym->attr.value ? GFC_CAF_ARG_VALUE : 0;
10059 else
10061 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
10062 ? GFC_CAF_BYREF : 0;
10063 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
10064 && !opr_expr->symtree->n.sym->attr.is_bind_c
10065 ? GFC_CAF_HIDDENLEN : 0;
10066 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
10067 ? GFC_CAF_ARG_VALUE : 0;
10069 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
10070 gfc_conv_expr (&argse, opr_expr);
10071 opr = argse.expr;
10072 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr, opr_flags,
10073 image_index, stat, errmsg, strlen, errmsg_len);
10076 gfc_add_expr_to_block (&block, fndecl);
10077 gfc_add_block_to_block (&block, &post_block);
10079 return gfc_finish_block (&block);
10083 static tree
10084 conv_intrinsic_atomic_op (gfc_code *code)
10086 gfc_se argse;
10087 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
10088 stmtblock_t block, post_block;
10089 gfc_expr *atom_expr = code->ext.actual->expr;
10090 gfc_expr *stat_expr;
10091 built_in_function fn;
10093 if (atom_expr->expr_type == EXPR_FUNCTION
10094 && atom_expr->value.function.isym
10095 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10096 atom_expr = atom_expr->value.function.actual->expr;
10098 gfc_start_block (&block);
10099 gfc_init_block (&post_block);
10101 gfc_init_se (&argse, NULL);
10102 argse.want_pointer = 1;
10103 gfc_conv_expr (&argse, atom_expr);
10104 gfc_add_block_to_block (&block, &argse.pre);
10105 gfc_add_block_to_block (&post_block, &argse.post);
10106 atom = argse.expr;
10108 gfc_init_se (&argse, NULL);
10109 if (flag_coarray == GFC_FCOARRAY_LIB
10110 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
10111 argse.want_pointer = 1;
10112 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10113 gfc_add_block_to_block (&block, &argse.pre);
10114 gfc_add_block_to_block (&post_block, &argse.post);
10115 value = argse.expr;
10117 switch (code->resolved_isym->id)
10119 case GFC_ISYM_ATOMIC_ADD:
10120 case GFC_ISYM_ATOMIC_AND:
10121 case GFC_ISYM_ATOMIC_DEF:
10122 case GFC_ISYM_ATOMIC_OR:
10123 case GFC_ISYM_ATOMIC_XOR:
10124 stat_expr = code->ext.actual->next->next->expr;
10125 if (flag_coarray == GFC_FCOARRAY_LIB)
10126 old = null_pointer_node;
10127 break;
10128 default:
10129 gfc_init_se (&argse, NULL);
10130 if (flag_coarray == GFC_FCOARRAY_LIB)
10131 argse.want_pointer = 1;
10132 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10133 gfc_add_block_to_block (&block, &argse.pre);
10134 gfc_add_block_to_block (&post_block, &argse.post);
10135 old = argse.expr;
10136 stat_expr = code->ext.actual->next->next->next->expr;
10139 /* STAT= */
10140 if (stat_expr != NULL)
10142 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
10143 gfc_init_se (&argse, NULL);
10144 if (flag_coarray == GFC_FCOARRAY_LIB)
10145 argse.want_pointer = 1;
10146 gfc_conv_expr_val (&argse, stat_expr);
10147 gfc_add_block_to_block (&block, &argse.pre);
10148 gfc_add_block_to_block (&post_block, &argse.post);
10149 stat = argse.expr;
10151 else if (flag_coarray == GFC_FCOARRAY_LIB)
10152 stat = null_pointer_node;
10154 if (flag_coarray == GFC_FCOARRAY_LIB)
10156 tree image_index, caf_decl, offset, token;
10157 int op;
10159 switch (code->resolved_isym->id)
10161 case GFC_ISYM_ATOMIC_ADD:
10162 case GFC_ISYM_ATOMIC_FETCH_ADD:
10163 op = (int) GFC_CAF_ATOMIC_ADD;
10164 break;
10165 case GFC_ISYM_ATOMIC_AND:
10166 case GFC_ISYM_ATOMIC_FETCH_AND:
10167 op = (int) GFC_CAF_ATOMIC_AND;
10168 break;
10169 case GFC_ISYM_ATOMIC_OR:
10170 case GFC_ISYM_ATOMIC_FETCH_OR:
10171 op = (int) GFC_CAF_ATOMIC_OR;
10172 break;
10173 case GFC_ISYM_ATOMIC_XOR:
10174 case GFC_ISYM_ATOMIC_FETCH_XOR:
10175 op = (int) GFC_CAF_ATOMIC_XOR;
10176 break;
10177 case GFC_ISYM_ATOMIC_DEF:
10178 op = 0; /* Unused. */
10179 break;
10180 default:
10181 gcc_unreachable ();
10184 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10185 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10186 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10188 if (gfc_is_coindexed (atom_expr))
10189 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10190 else
10191 image_index = integer_zero_node;
10193 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10195 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10196 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
10197 value = gfc_build_addr_expr (NULL_TREE, tmp);
10200 gfc_init_se (&argse, NULL);
10201 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10202 atom_expr);
10204 gfc_add_block_to_block (&block, &argse.pre);
10205 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
10206 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
10207 token, offset, image_index, value, stat,
10208 build_int_cst (integer_type_node,
10209 (int) atom_expr->ts.type),
10210 build_int_cst (integer_type_node,
10211 (int) atom_expr->ts.kind));
10212 else
10213 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
10214 build_int_cst (integer_type_node, op),
10215 token, offset, image_index, value, old, stat,
10216 build_int_cst (integer_type_node,
10217 (int) atom_expr->ts.type),
10218 build_int_cst (integer_type_node,
10219 (int) atom_expr->ts.kind));
10221 gfc_add_expr_to_block (&block, tmp);
10222 gfc_add_block_to_block (&block, &argse.post);
10223 gfc_add_block_to_block (&block, &post_block);
10224 return gfc_finish_block (&block);
10228 switch (code->resolved_isym->id)
10230 case GFC_ISYM_ATOMIC_ADD:
10231 case GFC_ISYM_ATOMIC_FETCH_ADD:
10232 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
10233 break;
10234 case GFC_ISYM_ATOMIC_AND:
10235 case GFC_ISYM_ATOMIC_FETCH_AND:
10236 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
10237 break;
10238 case GFC_ISYM_ATOMIC_DEF:
10239 fn = BUILT_IN_ATOMIC_STORE_N;
10240 break;
10241 case GFC_ISYM_ATOMIC_OR:
10242 case GFC_ISYM_ATOMIC_FETCH_OR:
10243 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
10244 break;
10245 case GFC_ISYM_ATOMIC_XOR:
10246 case GFC_ISYM_ATOMIC_FETCH_XOR:
10247 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
10248 break;
10249 default:
10250 gcc_unreachable ();
10253 tmp = TREE_TYPE (TREE_TYPE (atom));
10254 fn = (built_in_function) ((int) fn
10255 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10256 + 1);
10257 tmp = builtin_decl_explicit (fn);
10258 tree itype = TREE_TYPE (TREE_TYPE (atom));
10259 tmp = builtin_decl_explicit (fn);
10261 switch (code->resolved_isym->id)
10263 case GFC_ISYM_ATOMIC_ADD:
10264 case GFC_ISYM_ATOMIC_AND:
10265 case GFC_ISYM_ATOMIC_DEF:
10266 case GFC_ISYM_ATOMIC_OR:
10267 case GFC_ISYM_ATOMIC_XOR:
10268 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
10269 fold_convert (itype, value),
10270 build_int_cst (NULL, MEMMODEL_RELAXED));
10271 gfc_add_expr_to_block (&block, tmp);
10272 break;
10273 default:
10274 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
10275 fold_convert (itype, value),
10276 build_int_cst (NULL, MEMMODEL_RELAXED));
10277 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
10278 break;
10281 if (stat != NULL_TREE)
10282 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10283 gfc_add_block_to_block (&block, &post_block);
10284 return gfc_finish_block (&block);
10288 static tree
10289 conv_intrinsic_atomic_ref (gfc_code *code)
10291 gfc_se argse;
10292 tree tmp, atom, value, stat = NULL_TREE;
10293 stmtblock_t block, post_block;
10294 built_in_function fn;
10295 gfc_expr *atom_expr = code->ext.actual->next->expr;
10297 if (atom_expr->expr_type == EXPR_FUNCTION
10298 && atom_expr->value.function.isym
10299 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10300 atom_expr = atom_expr->value.function.actual->expr;
10302 gfc_start_block (&block);
10303 gfc_init_block (&post_block);
10304 gfc_init_se (&argse, NULL);
10305 argse.want_pointer = 1;
10306 gfc_conv_expr (&argse, atom_expr);
10307 gfc_add_block_to_block (&block, &argse.pre);
10308 gfc_add_block_to_block (&post_block, &argse.post);
10309 atom = argse.expr;
10311 gfc_init_se (&argse, NULL);
10312 if (flag_coarray == GFC_FCOARRAY_LIB
10313 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
10314 argse.want_pointer = 1;
10315 gfc_conv_expr (&argse, code->ext.actual->expr);
10316 gfc_add_block_to_block (&block, &argse.pre);
10317 gfc_add_block_to_block (&post_block, &argse.post);
10318 value = argse.expr;
10320 /* STAT= */
10321 if (code->ext.actual->next->next->expr != NULL)
10323 gcc_assert (code->ext.actual->next->next->expr->expr_type
10324 == EXPR_VARIABLE);
10325 gfc_init_se (&argse, NULL);
10326 if (flag_coarray == GFC_FCOARRAY_LIB)
10327 argse.want_pointer = 1;
10328 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10329 gfc_add_block_to_block (&block, &argse.pre);
10330 gfc_add_block_to_block (&post_block, &argse.post);
10331 stat = argse.expr;
10333 else if (flag_coarray == GFC_FCOARRAY_LIB)
10334 stat = null_pointer_node;
10336 if (flag_coarray == GFC_FCOARRAY_LIB)
10338 tree image_index, caf_decl, offset, token;
10339 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
10341 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10342 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10343 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10345 if (gfc_is_coindexed (atom_expr))
10346 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10347 else
10348 image_index = integer_zero_node;
10350 gfc_init_se (&argse, NULL);
10351 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10352 atom_expr);
10353 gfc_add_block_to_block (&block, &argse.pre);
10355 /* Different type, need type conversion. */
10356 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10358 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10359 orig_value = value;
10360 value = gfc_build_addr_expr (NULL_TREE, vardecl);
10363 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
10364 token, offset, image_index, value, stat,
10365 build_int_cst (integer_type_node,
10366 (int) atom_expr->ts.type),
10367 build_int_cst (integer_type_node,
10368 (int) atom_expr->ts.kind));
10369 gfc_add_expr_to_block (&block, tmp);
10370 if (vardecl != NULL_TREE)
10371 gfc_add_modify (&block, orig_value,
10372 fold_convert (TREE_TYPE (orig_value), vardecl));
10373 gfc_add_block_to_block (&block, &argse.post);
10374 gfc_add_block_to_block (&block, &post_block);
10375 return gfc_finish_block (&block);
10378 tmp = TREE_TYPE (TREE_TYPE (atom));
10379 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
10380 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10381 + 1);
10382 tmp = builtin_decl_explicit (fn);
10383 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
10384 build_int_cst (integer_type_node,
10385 MEMMODEL_RELAXED));
10386 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
10388 if (stat != NULL_TREE)
10389 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10390 gfc_add_block_to_block (&block, &post_block);
10391 return gfc_finish_block (&block);
10395 static tree
10396 conv_intrinsic_atomic_cas (gfc_code *code)
10398 gfc_se argse;
10399 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
10400 stmtblock_t block, post_block;
10401 built_in_function fn;
10402 gfc_expr *atom_expr = code->ext.actual->expr;
10404 if (atom_expr->expr_type == EXPR_FUNCTION
10405 && atom_expr->value.function.isym
10406 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10407 atom_expr = atom_expr->value.function.actual->expr;
10409 gfc_init_block (&block);
10410 gfc_init_block (&post_block);
10411 gfc_init_se (&argse, NULL);
10412 argse.want_pointer = 1;
10413 gfc_conv_expr (&argse, atom_expr);
10414 atom = argse.expr;
10416 gfc_init_se (&argse, NULL);
10417 if (flag_coarray == GFC_FCOARRAY_LIB)
10418 argse.want_pointer = 1;
10419 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10420 gfc_add_block_to_block (&block, &argse.pre);
10421 gfc_add_block_to_block (&post_block, &argse.post);
10422 old = argse.expr;
10424 gfc_init_se (&argse, NULL);
10425 if (flag_coarray == GFC_FCOARRAY_LIB)
10426 argse.want_pointer = 1;
10427 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10428 gfc_add_block_to_block (&block, &argse.pre);
10429 gfc_add_block_to_block (&post_block, &argse.post);
10430 comp = argse.expr;
10432 gfc_init_se (&argse, NULL);
10433 if (flag_coarray == GFC_FCOARRAY_LIB
10434 && code->ext.actual->next->next->next->expr->ts.kind
10435 == atom_expr->ts.kind)
10436 argse.want_pointer = 1;
10437 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
10438 gfc_add_block_to_block (&block, &argse.pre);
10439 gfc_add_block_to_block (&post_block, &argse.post);
10440 new_val = argse.expr;
10442 /* STAT= */
10443 if (code->ext.actual->next->next->next->next->expr != NULL)
10445 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
10446 == EXPR_VARIABLE);
10447 gfc_init_se (&argse, NULL);
10448 if (flag_coarray == GFC_FCOARRAY_LIB)
10449 argse.want_pointer = 1;
10450 gfc_conv_expr_val (&argse,
10451 code->ext.actual->next->next->next->next->expr);
10452 gfc_add_block_to_block (&block, &argse.pre);
10453 gfc_add_block_to_block (&post_block, &argse.post);
10454 stat = argse.expr;
10456 else if (flag_coarray == GFC_FCOARRAY_LIB)
10457 stat = null_pointer_node;
10459 if (flag_coarray == GFC_FCOARRAY_LIB)
10461 tree image_index, caf_decl, offset, token;
10463 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10464 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10465 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10467 if (gfc_is_coindexed (atom_expr))
10468 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10469 else
10470 image_index = integer_zero_node;
10472 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
10474 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
10475 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
10476 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
10479 /* Convert a constant to a pointer. */
10480 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
10482 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
10483 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
10484 comp = gfc_build_addr_expr (NULL_TREE, tmp);
10487 gfc_init_se (&argse, NULL);
10488 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10489 atom_expr);
10490 gfc_add_block_to_block (&block, &argse.pre);
10492 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
10493 token, offset, image_index, old, comp, new_val,
10494 stat, build_int_cst (integer_type_node,
10495 (int) atom_expr->ts.type),
10496 build_int_cst (integer_type_node,
10497 (int) atom_expr->ts.kind));
10498 gfc_add_expr_to_block (&block, tmp);
10499 gfc_add_block_to_block (&block, &argse.post);
10500 gfc_add_block_to_block (&block, &post_block);
10501 return gfc_finish_block (&block);
10504 tmp = TREE_TYPE (TREE_TYPE (atom));
10505 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
10506 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10507 + 1);
10508 tmp = builtin_decl_explicit (fn);
10510 gfc_add_modify (&block, old, comp);
10511 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
10512 gfc_build_addr_expr (NULL, old),
10513 fold_convert (TREE_TYPE (old), new_val),
10514 boolean_false_node,
10515 build_int_cst (NULL, MEMMODEL_RELAXED),
10516 build_int_cst (NULL, MEMMODEL_RELAXED));
10517 gfc_add_expr_to_block (&block, tmp);
10519 if (stat != NULL_TREE)
10520 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10521 gfc_add_block_to_block (&block, &post_block);
10522 return gfc_finish_block (&block);
10525 static tree
10526 conv_intrinsic_event_query (gfc_code *code)
10528 gfc_se se, argse;
10529 tree stat = NULL_TREE, stat2 = NULL_TREE;
10530 tree count = NULL_TREE, count2 = NULL_TREE;
10532 gfc_expr *event_expr = code->ext.actual->expr;
10534 if (code->ext.actual->next->next->expr)
10536 gcc_assert (code->ext.actual->next->next->expr->expr_type
10537 == EXPR_VARIABLE);
10538 gfc_init_se (&argse, NULL);
10539 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10540 stat = argse.expr;
10542 else if (flag_coarray == GFC_FCOARRAY_LIB)
10543 stat = null_pointer_node;
10545 if (code->ext.actual->next->expr)
10547 gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
10548 gfc_init_se (&argse, NULL);
10549 gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
10550 count = argse.expr;
10553 gfc_start_block (&se.pre);
10554 if (flag_coarray == GFC_FCOARRAY_LIB)
10556 tree tmp, token, image_index;
10557 tree index = size_zero_node;
10559 if (event_expr->expr_type == EXPR_FUNCTION
10560 && event_expr->value.function.isym
10561 && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10562 event_expr = event_expr->value.function.actual->expr;
10564 tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
10566 if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
10567 || event_expr->symtree->n.sym->ts.u.derived->from_intmod
10568 != INTMOD_ISO_FORTRAN_ENV
10569 || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
10570 != ISOFORTRAN_EVENT_TYPE)
10572 gfc_error ("Sorry, the event component of derived type at %L is not "
10573 "yet supported", &event_expr->where);
10574 return NULL_TREE;
10577 if (gfc_is_coindexed (event_expr))
10579 gfc_error ("The event variable at %L shall not be coindexed",
10580 &event_expr->where);
10581 return NULL_TREE;
10584 image_index = integer_zero_node;
10586 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
10587 event_expr);
10589 /* For arrays, obtain the array index. */
10590 if (gfc_expr_attr (event_expr).dimension)
10592 tree desc, tmp, extent, lbound, ubound;
10593 gfc_array_ref *ar, ar2;
10594 int i;
10596 /* TODO: Extend this, once DT components are supported. */
10597 ar = &event_expr->ref->u.ar;
10598 ar2 = *ar;
10599 memset (ar, '\0', sizeof (*ar));
10600 ar->as = ar2.as;
10601 ar->type = AR_FULL;
10603 gfc_init_se (&argse, NULL);
10604 argse.descriptor_only = 1;
10605 gfc_conv_expr_descriptor (&argse, event_expr);
10606 gfc_add_block_to_block (&se.pre, &argse.pre);
10607 desc = argse.expr;
10608 *ar = ar2;
10610 extent = integer_one_node;
10611 for (i = 0; i < ar->dimen; i++)
10613 gfc_init_se (&argse, NULL);
10614 gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
10615 gfc_add_block_to_block (&argse.pre, &argse.pre);
10616 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
10617 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10618 integer_type_node, argse.expr,
10619 fold_convert(integer_type_node, lbound));
10620 tmp = fold_build2_loc (input_location, MULT_EXPR,
10621 integer_type_node, extent, tmp);
10622 index = fold_build2_loc (input_location, PLUS_EXPR,
10623 integer_type_node, index, tmp);
10624 if (i < ar->dimen - 1)
10626 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
10627 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
10628 tmp = fold_convert (integer_type_node, tmp);
10629 extent = fold_build2_loc (input_location, MULT_EXPR,
10630 integer_type_node, extent, tmp);
10635 if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
10637 count2 = count;
10638 count = gfc_create_var (integer_type_node, "count");
10641 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
10643 stat2 = stat;
10644 stat = gfc_create_var (integer_type_node, "stat");
10647 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
10648 token, index, image_index, count
10649 ? gfc_build_addr_expr (NULL, count) : count,
10650 stat != null_pointer_node
10651 ? gfc_build_addr_expr (NULL, stat) : stat);
10652 gfc_add_expr_to_block (&se.pre, tmp);
10654 if (count2 != NULL_TREE)
10655 gfc_add_modify (&se.pre, count2,
10656 fold_convert (TREE_TYPE (count2), count));
10658 if (stat2 != NULL_TREE)
10659 gfc_add_modify (&se.pre, stat2,
10660 fold_convert (TREE_TYPE (stat2), stat));
10662 return gfc_finish_block (&se.pre);
10665 gfc_init_se (&argse, NULL);
10666 gfc_conv_expr_val (&argse, code->ext.actual->expr);
10667 gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
10669 if (stat != NULL_TREE)
10670 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
10672 return gfc_finish_block (&se.pre);
10675 static tree
10676 conv_intrinsic_move_alloc (gfc_code *code)
10678 stmtblock_t block;
10679 gfc_expr *from_expr, *to_expr;
10680 gfc_expr *to_expr2, *from_expr2 = NULL;
10681 gfc_se from_se, to_se;
10682 tree tmp;
10683 bool coarray;
10685 gfc_start_block (&block);
10687 from_expr = code->ext.actual->expr;
10688 to_expr = code->ext.actual->next->expr;
10690 gfc_init_se (&from_se, NULL);
10691 gfc_init_se (&to_se, NULL);
10693 gcc_assert (from_expr->ts.type != BT_CLASS
10694 || to_expr->ts.type == BT_CLASS);
10695 coarray = gfc_get_corank (from_expr) != 0;
10697 if (from_expr->rank == 0 && !coarray)
10699 if (from_expr->ts.type != BT_CLASS)
10700 from_expr2 = from_expr;
10701 else
10703 from_expr2 = gfc_copy_expr (from_expr);
10704 gfc_add_data_component (from_expr2);
10707 if (to_expr->ts.type != BT_CLASS)
10708 to_expr2 = to_expr;
10709 else
10711 to_expr2 = gfc_copy_expr (to_expr);
10712 gfc_add_data_component (to_expr2);
10715 from_se.want_pointer = 1;
10716 to_se.want_pointer = 1;
10717 gfc_conv_expr (&from_se, from_expr2);
10718 gfc_conv_expr (&to_se, to_expr2);
10719 gfc_add_block_to_block (&block, &from_se.pre);
10720 gfc_add_block_to_block (&block, &to_se.pre);
10722 /* Deallocate "to". */
10723 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10724 true, to_expr, to_expr->ts);
10725 gfc_add_expr_to_block (&block, tmp);
10727 /* Assign (_data) pointers. */
10728 gfc_add_modify_loc (input_location, &block, to_se.expr,
10729 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
10731 /* Set "from" to NULL. */
10732 gfc_add_modify_loc (input_location, &block, from_se.expr,
10733 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
10735 gfc_add_block_to_block (&block, &from_se.post);
10736 gfc_add_block_to_block (&block, &to_se.post);
10738 /* Set _vptr. */
10739 if (to_expr->ts.type == BT_CLASS)
10741 gfc_symbol *vtab;
10743 gfc_free_expr (to_expr2);
10744 gfc_init_se (&to_se, NULL);
10745 to_se.want_pointer = 1;
10746 gfc_add_vptr_component (to_expr);
10747 gfc_conv_expr (&to_se, to_expr);
10749 if (from_expr->ts.type == BT_CLASS)
10751 if (UNLIMITED_POLY (from_expr))
10752 vtab = NULL;
10753 else
10755 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10756 gcc_assert (vtab);
10759 gfc_free_expr (from_expr2);
10760 gfc_init_se (&from_se, NULL);
10761 from_se.want_pointer = 1;
10762 gfc_add_vptr_component (from_expr);
10763 gfc_conv_expr (&from_se, from_expr);
10764 gfc_add_modify_loc (input_location, &block, to_se.expr,
10765 fold_convert (TREE_TYPE (to_se.expr),
10766 from_se.expr));
10768 /* Reset _vptr component to declared type. */
10769 if (vtab == NULL)
10770 /* Unlimited polymorphic. */
10771 gfc_add_modify_loc (input_location, &block, from_se.expr,
10772 fold_convert (TREE_TYPE (from_se.expr),
10773 null_pointer_node));
10774 else
10776 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10777 gfc_add_modify_loc (input_location, &block, from_se.expr,
10778 fold_convert (TREE_TYPE (from_se.expr), tmp));
10781 else
10783 vtab = gfc_find_vtab (&from_expr->ts);
10784 gcc_assert (vtab);
10785 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10786 gfc_add_modify_loc (input_location, &block, to_se.expr,
10787 fold_convert (TREE_TYPE (to_se.expr), tmp));
10791 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
10793 gfc_add_modify_loc (input_location, &block, to_se.string_length,
10794 fold_convert (TREE_TYPE (to_se.string_length),
10795 from_se.string_length));
10796 if (from_expr->ts.deferred)
10797 gfc_add_modify_loc (input_location, &block, from_se.string_length,
10798 build_int_cst (TREE_TYPE (from_se.string_length), 0));
10801 return gfc_finish_block (&block);
10804 /* Update _vptr component. */
10805 if (to_expr->ts.type == BT_CLASS)
10807 gfc_symbol *vtab;
10809 to_se.want_pointer = 1;
10810 to_expr2 = gfc_copy_expr (to_expr);
10811 gfc_add_vptr_component (to_expr2);
10812 gfc_conv_expr (&to_se, to_expr2);
10814 if (from_expr->ts.type == BT_CLASS)
10816 if (UNLIMITED_POLY (from_expr))
10817 vtab = NULL;
10818 else
10820 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10821 gcc_assert (vtab);
10824 from_se.want_pointer = 1;
10825 from_expr2 = gfc_copy_expr (from_expr);
10826 gfc_add_vptr_component (from_expr2);
10827 gfc_conv_expr (&from_se, from_expr2);
10828 gfc_add_modify_loc (input_location, &block, to_se.expr,
10829 fold_convert (TREE_TYPE (to_se.expr),
10830 from_se.expr));
10832 /* Reset _vptr component to declared type. */
10833 if (vtab == NULL)
10834 /* Unlimited polymorphic. */
10835 gfc_add_modify_loc (input_location, &block, from_se.expr,
10836 fold_convert (TREE_TYPE (from_se.expr),
10837 null_pointer_node));
10838 else
10840 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10841 gfc_add_modify_loc (input_location, &block, from_se.expr,
10842 fold_convert (TREE_TYPE (from_se.expr), tmp));
10845 else
10847 vtab = gfc_find_vtab (&from_expr->ts);
10848 gcc_assert (vtab);
10849 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10850 gfc_add_modify_loc (input_location, &block, to_se.expr,
10851 fold_convert (TREE_TYPE (to_se.expr), tmp));
10854 gfc_free_expr (to_expr2);
10855 gfc_init_se (&to_se, NULL);
10857 if (from_expr->ts.type == BT_CLASS)
10859 gfc_free_expr (from_expr2);
10860 gfc_init_se (&from_se, NULL);
10865 /* Deallocate "to". */
10866 if (from_expr->rank == 0)
10868 to_se.want_coarray = 1;
10869 from_se.want_coarray = 1;
10871 gfc_conv_expr_descriptor (&to_se, to_expr);
10872 gfc_conv_expr_descriptor (&from_se, from_expr);
10874 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
10875 is an image control "statement", cf. IR F08/0040 in 12-006A. */
10876 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
10878 tree cond;
10880 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10881 NULL_TREE, NULL_TREE, true, to_expr,
10882 GFC_CAF_COARRAY_DEALLOCATE_ONLY);
10883 gfc_add_expr_to_block (&block, tmp);
10885 tmp = gfc_conv_descriptor_data_get (to_se.expr);
10886 cond = fold_build2_loc (input_location, EQ_EXPR,
10887 logical_type_node, tmp,
10888 fold_convert (TREE_TYPE (tmp),
10889 null_pointer_node));
10890 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
10891 3, null_pointer_node, null_pointer_node,
10892 build_int_cst (integer_type_node, 0));
10894 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
10895 tmp, build_empty_stmt (input_location));
10896 gfc_add_expr_to_block (&block, tmp);
10898 else
10900 if (to_expr->ts.type == BT_DERIVED
10901 && to_expr->ts.u.derived->attr.alloc_comp)
10903 tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
10904 to_se.expr, to_expr->rank);
10905 gfc_add_expr_to_block (&block, tmp);
10908 tmp = gfc_conv_descriptor_data_get (to_se.expr);
10909 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
10910 NULL_TREE, true, to_expr,
10911 GFC_CAF_COARRAY_NOCOARRAY);
10912 gfc_add_expr_to_block (&block, tmp);
10915 /* Move the pointer and update the array descriptor data. */
10916 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
10918 /* Set "from" to NULL. */
10919 tmp = gfc_conv_descriptor_data_get (from_se.expr);
10920 gfc_add_modify_loc (input_location, &block, tmp,
10921 fold_convert (TREE_TYPE (tmp), null_pointer_node));
10924 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
10926 gfc_add_modify_loc (input_location, &block, to_se.string_length,
10927 fold_convert (TREE_TYPE (to_se.string_length),
10928 from_se.string_length));
10929 if (from_expr->ts.deferred)
10930 gfc_add_modify_loc (input_location, &block, from_se.string_length,
10931 build_int_cst (TREE_TYPE (from_se.string_length), 0));
10934 return gfc_finish_block (&block);
10938 tree
10939 gfc_conv_intrinsic_subroutine (gfc_code *code)
10941 tree res;
10943 gcc_assert (code->resolved_isym);
10945 switch (code->resolved_isym->id)
10947 case GFC_ISYM_MOVE_ALLOC:
10948 res = conv_intrinsic_move_alloc (code);
10949 break;
10951 case GFC_ISYM_ATOMIC_CAS:
10952 res = conv_intrinsic_atomic_cas (code);
10953 break;
10955 case GFC_ISYM_ATOMIC_ADD:
10956 case GFC_ISYM_ATOMIC_AND:
10957 case GFC_ISYM_ATOMIC_DEF:
10958 case GFC_ISYM_ATOMIC_OR:
10959 case GFC_ISYM_ATOMIC_XOR:
10960 case GFC_ISYM_ATOMIC_FETCH_ADD:
10961 case GFC_ISYM_ATOMIC_FETCH_AND:
10962 case GFC_ISYM_ATOMIC_FETCH_OR:
10963 case GFC_ISYM_ATOMIC_FETCH_XOR:
10964 res = conv_intrinsic_atomic_op (code);
10965 break;
10967 case GFC_ISYM_ATOMIC_REF:
10968 res = conv_intrinsic_atomic_ref (code);
10969 break;
10971 case GFC_ISYM_EVENT_QUERY:
10972 res = conv_intrinsic_event_query (code);
10973 break;
10975 case GFC_ISYM_C_F_POINTER:
10976 case GFC_ISYM_C_F_PROCPOINTER:
10977 res = conv_isocbinding_subroutine (code);
10978 break;
10980 case GFC_ISYM_CAF_SEND:
10981 res = conv_caf_send (code);
10982 break;
10984 case GFC_ISYM_CO_BROADCAST:
10985 case GFC_ISYM_CO_MIN:
10986 case GFC_ISYM_CO_MAX:
10987 case GFC_ISYM_CO_REDUCE:
10988 case GFC_ISYM_CO_SUM:
10989 res = conv_co_collective (code);
10990 break;
10992 case GFC_ISYM_FREE:
10993 res = conv_intrinsic_free (code);
10994 break;
10996 case GFC_ISYM_KILL:
10997 res = conv_intrinsic_kill_sub (code);
10998 break;
11000 case GFC_ISYM_SYSTEM_CLOCK:
11001 res = conv_intrinsic_system_clock (code);
11002 break;
11004 default:
11005 res = NULL_TREE;
11006 break;
11009 return res;
11012 #include "gt-fortran-trans-intrinsic.h"