PR c++/65727
[official-gcc.git] / gcc / fortran / trans-intrinsic.c
blobc4ccb7b77c88602e9f24fc73c194dbf6b7fc3a60
1 /* Intrinsic translation
2 Copyright (C) 2002-2015 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 "tm.h" /* For UNITS_PER_WORD. */
28 #include "hash-set.h"
29 #include "machmode.h"
30 #include "vec.h"
31 #include "double-int.h"
32 #include "input.h"
33 #include "alias.h"
34 #include "symtab.h"
35 #include "wide-int.h"
36 #include "inchash.h"
37 #include "real.h"
38 #include "tree.h"
39 #include "fold-const.h"
40 #include "stringpool.h"
41 #include "tree-nested.h"
42 #include "stor-layout.h"
43 #include "ggc.h"
44 #include "gfortran.h"
45 #include "diagnostic-core.h" /* For internal_error. */
46 #include "toplev.h" /* For rest_of_decl_compilation. */
47 #include "flags.h"
48 #include "arith.h"
49 #include "intrinsic.h"
50 #include "trans.h"
51 #include "trans-const.h"
52 #include "trans-types.h"
53 #include "trans-array.h"
54 #include "dependency.h" /* For CAF array alias analysis. */
55 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
56 #include "trans-stmt.h"
57 #include "tree-nested.h"
59 /* This maps Fortran intrinsic math functions to external library or GCC
60 builtin functions. */
61 typedef struct GTY(()) gfc_intrinsic_map_t {
62 /* The explicit enum is required to work around inadequacies in the
63 garbage collection/gengtype parsing mechanism. */
64 enum gfc_isym_id id;
66 /* Enum value from the "language-independent", aka C-centric, part
67 of gcc, or END_BUILTINS of no such value set. */
68 enum built_in_function float_built_in;
69 enum built_in_function double_built_in;
70 enum built_in_function long_double_built_in;
71 enum built_in_function complex_float_built_in;
72 enum built_in_function complex_double_built_in;
73 enum built_in_function complex_long_double_built_in;
75 /* True if the naming pattern is to prepend "c" for complex and
76 append "f" for kind=4. False if the naming pattern is to
77 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
78 bool libm_name;
80 /* True if a complex version of the function exists. */
81 bool complex_available;
83 /* True if the function should be marked const. */
84 bool is_constant;
86 /* The base library name of this function. */
87 const char *name;
89 /* Cache decls created for the various operand types. */
90 tree real4_decl;
91 tree real8_decl;
92 tree real10_decl;
93 tree real16_decl;
94 tree complex4_decl;
95 tree complex8_decl;
96 tree complex10_decl;
97 tree complex16_decl;
99 gfc_intrinsic_map_t;
101 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
102 defines complex variants of all of the entries in mathbuiltins.def
103 except for atan2. */
104 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
105 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
106 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
107 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
108 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
110 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
111 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
112 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
113 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
114 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
116 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
117 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
118 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
119 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
120 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
122 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
123 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
124 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
125 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
126 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
128 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
130 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
131 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
132 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
133 #include "mathbuiltins.def"
135 /* Functions in libgfortran. */
136 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
138 /* End the list. */
139 LIB_FUNCTION (NONE, NULL, false)
142 #undef OTHER_BUILTIN
143 #undef LIB_FUNCTION
144 #undef DEFINE_MATH_BUILTIN
145 #undef DEFINE_MATH_BUILTIN_C
148 enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
151 /* Find the correct variant of a given builtin from its argument. */
152 static tree
153 builtin_decl_for_precision (enum built_in_function base_built_in,
154 int precision)
156 enum built_in_function i = END_BUILTINS;
158 gfc_intrinsic_map_t *m;
159 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
162 if (precision == TYPE_PRECISION (float_type_node))
163 i = m->float_built_in;
164 else if (precision == TYPE_PRECISION (double_type_node))
165 i = m->double_built_in;
166 else if (precision == TYPE_PRECISION (long_double_type_node))
167 i = m->long_double_built_in;
168 else if (precision == TYPE_PRECISION (float128_type_node))
170 /* Special treatment, because it is not exactly a built-in, but
171 a library function. */
172 return m->real16_decl;
175 return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
179 tree
180 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
181 int kind)
183 int i = gfc_validate_kind (BT_REAL, kind, false);
185 if (gfc_real_kinds[i].c_float128)
187 /* For __float128, the story is a bit different, because we return
188 a decl to a library function rather than a built-in. */
189 gfc_intrinsic_map_t *m;
190 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
193 return m->real16_decl;
196 return builtin_decl_for_precision (double_built_in,
197 gfc_real_kinds[i].mode_precision);
201 /* Evaluate the arguments to an intrinsic function. The value
202 of NARGS may be less than the actual number of arguments in EXPR
203 to allow optional "KIND" arguments that are not included in the
204 generated code to be ignored. */
206 static void
207 gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
208 tree *argarray, int nargs)
210 gfc_actual_arglist *actual;
211 gfc_expr *e;
212 gfc_intrinsic_arg *formal;
213 gfc_se argse;
214 int curr_arg;
216 formal = expr->value.function.isym->formal;
217 actual = expr->value.function.actual;
219 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
220 actual = actual->next,
221 formal = formal ? formal->next : NULL)
223 gcc_assert (actual);
224 e = actual->expr;
225 /* Skip omitted optional arguments. */
226 if (!e)
228 --curr_arg;
229 continue;
232 /* Evaluate the parameter. This will substitute scalarized
233 references automatically. */
234 gfc_init_se (&argse, se);
236 if (e->ts.type == BT_CHARACTER)
238 gfc_conv_expr (&argse, e);
239 gfc_conv_string_parameter (&argse);
240 argarray[curr_arg++] = argse.string_length;
241 gcc_assert (curr_arg < nargs);
243 else
244 gfc_conv_expr_val (&argse, e);
246 /* If an optional argument is itself an optional dummy argument,
247 check its presence and substitute a null if absent. */
248 if (e->expr_type == EXPR_VARIABLE
249 && e->symtree->n.sym->attr.optional
250 && formal
251 && formal->optional)
252 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
254 gfc_add_block_to_block (&se->pre, &argse.pre);
255 gfc_add_block_to_block (&se->post, &argse.post);
256 argarray[curr_arg] = argse.expr;
260 /* Count the number of actual arguments to the intrinsic function EXPR
261 including any "hidden" string length arguments. */
263 static unsigned int
264 gfc_intrinsic_argument_list_length (gfc_expr *expr)
266 int n = 0;
267 gfc_actual_arglist *actual;
269 for (actual = expr->value.function.actual; actual; actual = actual->next)
271 if (!actual->expr)
272 continue;
274 if (actual->expr->ts.type == BT_CHARACTER)
275 n += 2;
276 else
277 n++;
280 return n;
284 /* Conversions between different types are output by the frontend as
285 intrinsic functions. We implement these directly with inline code. */
287 static void
288 gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
290 tree type;
291 tree *args;
292 int nargs;
294 nargs = gfc_intrinsic_argument_list_length (expr);
295 args = XALLOCAVEC (tree, nargs);
297 /* Evaluate all the arguments passed. Whilst we're only interested in the
298 first one here, there are other parts of the front-end that assume this
299 and will trigger an ICE if it's not the case. */
300 type = gfc_typenode_for_spec (&expr->ts);
301 gcc_assert (expr->value.function.actual->expr);
302 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
304 /* Conversion between character kinds involves a call to a library
305 function. */
306 if (expr->ts.type == BT_CHARACTER)
308 tree fndecl, var, addr, tmp;
310 if (expr->ts.kind == 1
311 && expr->value.function.actual->expr->ts.kind == 4)
312 fndecl = gfor_fndecl_convert_char4_to_char1;
313 else if (expr->ts.kind == 4
314 && expr->value.function.actual->expr->ts.kind == 1)
315 fndecl = gfor_fndecl_convert_char1_to_char4;
316 else
317 gcc_unreachable ();
319 /* Create the variable storing the converted value. */
320 type = gfc_get_pchar_type (expr->ts.kind);
321 var = gfc_create_var (type, "str");
322 addr = gfc_build_addr_expr (build_pointer_type (type), var);
324 /* Call the library function that will perform the conversion. */
325 gcc_assert (nargs >= 2);
326 tmp = build_call_expr_loc (input_location,
327 fndecl, 3, addr, args[0], args[1]);
328 gfc_add_expr_to_block (&se->pre, tmp);
330 /* Free the temporary afterwards. */
331 tmp = gfc_call_free (var);
332 gfc_add_expr_to_block (&se->post, tmp);
334 se->expr = var;
335 se->string_length = args[0];
337 return;
340 /* Conversion from complex to non-complex involves taking the real
341 component of the value. */
342 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
343 && expr->ts.type != BT_COMPLEX)
345 tree artype;
347 artype = TREE_TYPE (TREE_TYPE (args[0]));
348 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
349 args[0]);
352 se->expr = convert (type, args[0]);
355 /* This is needed because the gcc backend only implements
356 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
357 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
358 Similarly for CEILING. */
360 static tree
361 build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
363 tree tmp;
364 tree cond;
365 tree argtype;
366 tree intval;
368 argtype = TREE_TYPE (arg);
369 arg = gfc_evaluate_now (arg, pblock);
371 intval = convert (type, arg);
372 intval = gfc_evaluate_now (intval, pblock);
374 tmp = convert (argtype, intval);
375 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
376 boolean_type_node, tmp, arg);
378 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
379 intval, build_int_cst (type, 1));
380 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
381 return tmp;
385 /* Round to nearest integer, away from zero. */
387 static tree
388 build_round_expr (tree arg, tree restype)
390 tree argtype;
391 tree fn;
392 int argprec, resprec;
394 argtype = TREE_TYPE (arg);
395 argprec = TYPE_PRECISION (argtype);
396 resprec = TYPE_PRECISION (restype);
398 /* Depending on the type of the result, choose the int intrinsic
399 (iround, available only as a builtin, therefore cannot use it for
400 __float128), long int intrinsic (lround family) or long long
401 intrinsic (llround). We might also need to convert the result
402 afterwards. */
403 if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
404 fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
405 else if (resprec <= LONG_TYPE_SIZE)
406 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
407 else if (resprec <= LONG_LONG_TYPE_SIZE)
408 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
409 else
410 gcc_unreachable ();
412 return fold_convert (restype, build_call_expr_loc (input_location,
413 fn, 1, arg));
417 /* Convert a real to an integer using a specific rounding mode.
418 Ideally we would just build the corresponding GENERIC node,
419 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
421 static tree
422 build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
423 enum rounding_mode op)
425 switch (op)
427 case RND_FLOOR:
428 return build_fixbound_expr (pblock, arg, type, 0);
429 break;
431 case RND_CEIL:
432 return build_fixbound_expr (pblock, arg, type, 1);
433 break;
435 case RND_ROUND:
436 return build_round_expr (arg, type);
437 break;
439 case RND_TRUNC:
440 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
441 break;
443 default:
444 gcc_unreachable ();
449 /* Round a real value using the specified rounding mode.
450 We use a temporary integer of that same kind size as the result.
451 Values larger than those that can be represented by this kind are
452 unchanged, as they will not be accurate enough to represent the
453 rounding.
454 huge = HUGE (KIND (a))
455 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
458 static void
459 gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
461 tree type;
462 tree itype;
463 tree arg[2];
464 tree tmp;
465 tree cond;
466 tree decl;
467 mpfr_t huge;
468 int n, nargs;
469 int kind;
471 kind = expr->ts.kind;
472 nargs = gfc_intrinsic_argument_list_length (expr);
474 decl = NULL_TREE;
475 /* We have builtin functions for some cases. */
476 switch (op)
478 case RND_ROUND:
479 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
480 break;
482 case RND_TRUNC:
483 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
484 break;
486 default:
487 gcc_unreachable ();
490 /* Evaluate the argument. */
491 gcc_assert (expr->value.function.actual->expr);
492 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
494 /* Use a builtin function if one exists. */
495 if (decl != NULL_TREE)
497 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
498 return;
501 /* This code is probably redundant, but we'll keep it lying around just
502 in case. */
503 type = gfc_typenode_for_spec (&expr->ts);
504 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
506 /* Test if the value is too large to handle sensibly. */
507 gfc_set_model_kind (kind);
508 mpfr_init (huge);
509 n = gfc_validate_kind (BT_INTEGER, kind, false);
510 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
511 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
512 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, arg[0],
513 tmp);
515 mpfr_neg (huge, huge, GFC_RND_MODE);
516 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
517 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, arg[0],
518 tmp);
519 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
520 cond, tmp);
521 itype = gfc_get_int_type (kind);
523 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
524 tmp = convert (type, tmp);
525 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
526 arg[0]);
527 mpfr_clear (huge);
531 /* Convert to an integer using the specified rounding mode. */
533 static void
534 gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
536 tree type;
537 tree *args;
538 int nargs;
540 nargs = gfc_intrinsic_argument_list_length (expr);
541 args = XALLOCAVEC (tree, nargs);
543 /* Evaluate the argument, we process all arguments even though we only
544 use the first one for code generation purposes. */
545 type = gfc_typenode_for_spec (&expr->ts);
546 gcc_assert (expr->value.function.actual->expr);
547 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
549 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
551 /* Conversion to a different integer kind. */
552 se->expr = convert (type, args[0]);
554 else
556 /* Conversion from complex to non-complex involves taking the real
557 component of the value. */
558 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
559 && expr->ts.type != BT_COMPLEX)
561 tree artype;
563 artype = TREE_TYPE (TREE_TYPE (args[0]));
564 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
565 args[0]);
568 se->expr = build_fix_expr (&se->pre, args[0], type, op);
573 /* Get the imaginary component of a value. */
575 static void
576 gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
578 tree arg;
580 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
581 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
582 TREE_TYPE (TREE_TYPE (arg)), arg);
586 /* Get the complex conjugate of a value. */
588 static void
589 gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
591 tree arg;
593 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
594 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
599 static tree
600 define_quad_builtin (const char *name, tree type, bool is_const)
602 tree fndecl;
603 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
604 type);
606 /* Mark the decl as external. */
607 DECL_EXTERNAL (fndecl) = 1;
608 TREE_PUBLIC (fndecl) = 1;
610 /* Mark it __attribute__((const)). */
611 TREE_READONLY (fndecl) = is_const;
613 rest_of_decl_compilation (fndecl, 1, 0);
615 return fndecl;
620 /* Initialize function decls for library functions. The external functions
621 are created as required. Builtin functions are added here. */
623 void
624 gfc_build_intrinsic_lib_fndecls (void)
626 gfc_intrinsic_map_t *m;
627 tree quad_decls[END_BUILTINS + 1];
629 if (gfc_real16_is_float128)
631 /* If we have soft-float types, we create the decls for their
632 C99-like library functions. For now, we only handle __float128
633 q-suffixed functions. */
635 tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
636 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
638 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
640 type = float128_type_node;
641 complex_type = complex_float128_type_node;
642 /* type (*) (type) */
643 func_1 = build_function_type_list (type, type, NULL_TREE);
644 /* int (*) (type) */
645 func_iround = build_function_type_list (integer_type_node,
646 type, NULL_TREE);
647 /* long (*) (type) */
648 func_lround = build_function_type_list (long_integer_type_node,
649 type, NULL_TREE);
650 /* long long (*) (type) */
651 func_llround = build_function_type_list (long_long_integer_type_node,
652 type, NULL_TREE);
653 /* type (*) (type, type) */
654 func_2 = build_function_type_list (type, type, type, NULL_TREE);
655 /* type (*) (type, &int) */
656 func_frexp
657 = build_function_type_list (type,
658 type,
659 build_pointer_type (integer_type_node),
660 NULL_TREE);
661 /* type (*) (type, int) */
662 func_scalbn = build_function_type_list (type,
663 type, integer_type_node, NULL_TREE);
664 /* type (*) (complex type) */
665 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
666 /* complex type (*) (complex type, complex type) */
667 func_cpow
668 = build_function_type_list (complex_type,
669 complex_type, complex_type, NULL_TREE);
671 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
672 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
673 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
675 /* Only these built-ins are actually needed here. These are used directly
676 from the code, when calling builtin_decl_for_precision() or
677 builtin_decl_for_float_type(). The others are all constructed by
678 gfc_get_intrinsic_lib_fndecl(). */
679 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
680 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
682 #include "mathbuiltins.def"
684 #undef OTHER_BUILTIN
685 #undef LIB_FUNCTION
686 #undef DEFINE_MATH_BUILTIN
687 #undef DEFINE_MATH_BUILTIN_C
691 /* Add GCC builtin functions. */
692 for (m = gfc_intrinsic_map;
693 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
695 if (m->float_built_in != END_BUILTINS)
696 m->real4_decl = builtin_decl_explicit (m->float_built_in);
697 if (m->complex_float_built_in != END_BUILTINS)
698 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
699 if (m->double_built_in != END_BUILTINS)
700 m->real8_decl = builtin_decl_explicit (m->double_built_in);
701 if (m->complex_double_built_in != END_BUILTINS)
702 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
704 /* If real(kind=10) exists, it is always long double. */
705 if (m->long_double_built_in != END_BUILTINS)
706 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
707 if (m->complex_long_double_built_in != END_BUILTINS)
708 m->complex10_decl
709 = builtin_decl_explicit (m->complex_long_double_built_in);
711 if (!gfc_real16_is_float128)
713 if (m->long_double_built_in != END_BUILTINS)
714 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
715 if (m->complex_long_double_built_in != END_BUILTINS)
716 m->complex16_decl
717 = builtin_decl_explicit (m->complex_long_double_built_in);
719 else if (quad_decls[m->double_built_in] != NULL_TREE)
721 /* Quad-precision function calls are constructed when first
722 needed by builtin_decl_for_precision(), except for those
723 that will be used directly (define by OTHER_BUILTIN). */
724 m->real16_decl = quad_decls[m->double_built_in];
726 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
728 /* Same thing for the complex ones. */
729 m->complex16_decl = quad_decls[m->double_built_in];
735 /* Create a fndecl for a simple intrinsic library function. */
737 static tree
738 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
740 tree type;
741 vec<tree, va_gc> *argtypes;
742 tree fndecl;
743 gfc_actual_arglist *actual;
744 tree *pdecl;
745 gfc_typespec *ts;
746 char name[GFC_MAX_SYMBOL_LEN + 3];
748 ts = &expr->ts;
749 if (ts->type == BT_REAL)
751 switch (ts->kind)
753 case 4:
754 pdecl = &m->real4_decl;
755 break;
756 case 8:
757 pdecl = &m->real8_decl;
758 break;
759 case 10:
760 pdecl = &m->real10_decl;
761 break;
762 case 16:
763 pdecl = &m->real16_decl;
764 break;
765 default:
766 gcc_unreachable ();
769 else if (ts->type == BT_COMPLEX)
771 gcc_assert (m->complex_available);
773 switch (ts->kind)
775 case 4:
776 pdecl = &m->complex4_decl;
777 break;
778 case 8:
779 pdecl = &m->complex8_decl;
780 break;
781 case 10:
782 pdecl = &m->complex10_decl;
783 break;
784 case 16:
785 pdecl = &m->complex16_decl;
786 break;
787 default:
788 gcc_unreachable ();
791 else
792 gcc_unreachable ();
794 if (*pdecl)
795 return *pdecl;
797 if (m->libm_name)
799 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
800 if (gfc_real_kinds[n].c_float)
801 snprintf (name, sizeof (name), "%s%s%s",
802 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
803 else if (gfc_real_kinds[n].c_double)
804 snprintf (name, sizeof (name), "%s%s",
805 ts->type == BT_COMPLEX ? "c" : "", m->name);
806 else if (gfc_real_kinds[n].c_long_double)
807 snprintf (name, sizeof (name), "%s%s%s",
808 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
809 else if (gfc_real_kinds[n].c_float128)
810 snprintf (name, sizeof (name), "%s%s%s",
811 ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
812 else
813 gcc_unreachable ();
815 else
817 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
818 ts->type == BT_COMPLEX ? 'c' : 'r',
819 ts->kind);
822 argtypes = NULL;
823 for (actual = expr->value.function.actual; actual; actual = actual->next)
825 type = gfc_typenode_for_spec (&actual->expr->ts);
826 vec_safe_push (argtypes, type);
828 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
829 fndecl = build_decl (input_location,
830 FUNCTION_DECL, get_identifier (name), type);
832 /* Mark the decl as external. */
833 DECL_EXTERNAL (fndecl) = 1;
834 TREE_PUBLIC (fndecl) = 1;
836 /* Mark it __attribute__((const)), if possible. */
837 TREE_READONLY (fndecl) = m->is_constant;
839 rest_of_decl_compilation (fndecl, 1, 0);
841 (*pdecl) = fndecl;
842 return fndecl;
846 /* Convert an intrinsic function into an external or builtin call. */
848 static void
849 gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
851 gfc_intrinsic_map_t *m;
852 tree fndecl;
853 tree rettype;
854 tree *args;
855 unsigned int num_args;
856 gfc_isym_id id;
858 id = expr->value.function.isym->id;
859 /* Find the entry for this function. */
860 for (m = gfc_intrinsic_map;
861 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
863 if (id == m->id)
864 break;
867 if (m->id == GFC_ISYM_NONE)
869 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
870 expr->value.function.name, id);
873 /* Get the decl and generate the call. */
874 num_args = gfc_intrinsic_argument_list_length (expr);
875 args = XALLOCAVEC (tree, num_args);
877 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
878 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
879 rettype = TREE_TYPE (TREE_TYPE (fndecl));
881 fndecl = build_addr (fndecl, current_function_decl);
882 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
886 /* If bounds-checking is enabled, create code to verify at runtime that the
887 string lengths for both expressions are the same (needed for e.g. MERGE).
888 If bounds-checking is not enabled, does nothing. */
890 void
891 gfc_trans_same_strlen_check (const char* intr_name, locus* where,
892 tree a, tree b, stmtblock_t* target)
894 tree cond;
895 tree name;
897 /* If bounds-checking is disabled, do nothing. */
898 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
899 return;
901 /* Compare the two string lengths. */
902 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, a, b);
904 /* Output the runtime-check. */
905 name = gfc_build_cstring_const (intr_name);
906 name = gfc_build_addr_expr (pchar_type_node, name);
907 gfc_trans_runtime_check (true, false, cond, target, where,
908 "Unequal character lengths (%ld/%ld) in %s",
909 fold_convert (long_integer_type_node, a),
910 fold_convert (long_integer_type_node, b), name);
914 /* The EXPONENT(X) intrinsic function is translated into
915 int ret;
916 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
917 so that if X is a NaN or infinity, the result is HUGE(0).
920 static void
921 gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
923 tree arg, type, res, tmp, frexp, cond, huge;
924 int i;
926 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
927 expr->value.function.actual->expr->ts.kind);
929 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
930 arg = gfc_evaluate_now (arg, &se->pre);
932 i = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
933 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_c_int_kind);
934 cond = build_call_expr_loc (input_location,
935 builtin_decl_explicit (BUILT_IN_ISFINITE),
936 1, arg);
938 res = gfc_create_var (integer_type_node, NULL);
939 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
940 gfc_build_addr_expr (NULL_TREE, res));
941 tmp = fold_build2_loc (input_location, COMPOUND_EXPR, integer_type_node,
942 tmp, res);
943 se->expr = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
944 cond, tmp, huge);
946 type = gfc_typenode_for_spec (&expr->ts);
947 se->expr = fold_convert (type, se->expr);
951 /* Fill in the following structure
952 struct caf_vector_t {
953 size_t nvec; // size of the vector
954 union {
955 struct {
956 void *vector;
957 int kind;
958 } v;
959 struct {
960 ptrdiff_t lower_bound;
961 ptrdiff_t upper_bound;
962 ptrdiff_t stride;
963 } triplet;
964 } u;
965 } */
967 static void
968 conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
969 tree lower, tree upper, tree stride,
970 tree vector, int kind, tree nvec)
972 tree field, type, tmp;
974 desc = gfc_build_array_ref (desc, gfc_rank_cst[i], NULL_TREE);
975 type = TREE_TYPE (desc);
977 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
978 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
979 desc, field, NULL_TREE);
980 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), nvec));
982 /* Access union. */
983 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
984 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
985 desc, field, NULL_TREE);
986 type = TREE_TYPE (desc);
988 /* Access the inner struct. */
989 field = gfc_advance_chain (TYPE_FIELDS (type), vector != NULL_TREE ? 0 : 1);
990 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
991 desc, field, NULL_TREE);
992 type = TREE_TYPE (desc);
994 if (vector != NULL_TREE)
996 /* Set dim.lower/upper/stride. */
997 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
998 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
999 desc, field, NULL_TREE);
1000 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), vector));
1001 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1002 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1003 desc, field, NULL_TREE);
1004 gfc_add_modify (block, tmp, build_int_cst (integer_type_node, kind));
1006 else
1008 /* Set vector and kind. */
1009 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1010 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1011 desc, field, NULL_TREE);
1012 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), lower));
1014 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1015 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1016 desc, field, NULL_TREE);
1017 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), upper));
1019 field = gfc_advance_chain (TYPE_FIELDS (type), 2);
1020 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1021 desc, field, NULL_TREE);
1022 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), stride));
1027 static tree
1028 conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
1030 gfc_se argse;
1031 tree var, lower, upper = NULL_TREE, stride = NULL_TREE, vector, nvec;
1032 tree lbound, ubound, tmp;
1033 int i;
1035 var = gfc_create_var (gfc_get_caf_vector_type (ar->dimen), "vector");
1037 for (i = 0; i < ar->dimen; i++)
1038 switch (ar->dimen_type[i])
1040 case DIMEN_RANGE:
1041 if (ar->end[i])
1043 gfc_init_se (&argse, NULL);
1044 gfc_conv_expr (&argse, ar->end[i]);
1045 gfc_add_block_to_block (block, &argse.pre);
1046 upper = gfc_evaluate_now (argse.expr, block);
1048 else
1049 upper = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1050 if (ar->stride[i])
1052 gfc_init_se (&argse, NULL);
1053 gfc_conv_expr (&argse, ar->stride[i]);
1054 gfc_add_block_to_block (block, &argse.pre);
1055 stride = gfc_evaluate_now (argse.expr, block);
1057 else
1058 stride = gfc_index_one_node;
1060 /* Fall through. */
1061 case DIMEN_ELEMENT:
1062 if (ar->start[i])
1064 gfc_init_se (&argse, NULL);
1065 gfc_conv_expr (&argse, ar->start[i]);
1066 gfc_add_block_to_block (block, &argse.pre);
1067 lower = gfc_evaluate_now (argse.expr, block);
1069 else
1070 lower = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1071 if (ar->dimen_type[i] == DIMEN_ELEMENT)
1073 upper = lower;
1074 stride = gfc_index_one_node;
1076 vector = NULL_TREE;
1077 nvec = size_zero_node;
1078 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1079 vector, 0, nvec);
1080 break;
1082 case DIMEN_VECTOR:
1083 gfc_init_se (&argse, NULL);
1084 argse.descriptor_only = 1;
1085 gfc_conv_expr_descriptor (&argse, ar->start[i]);
1086 gfc_add_block_to_block (block, &argse.pre);
1087 vector = argse.expr;
1088 lbound = gfc_conv_descriptor_lbound_get (vector, gfc_rank_cst[0]);
1089 ubound = gfc_conv_descriptor_ubound_get (vector, gfc_rank_cst[0]);
1090 nvec = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1091 tmp = gfc_conv_descriptor_stride_get (vector, gfc_rank_cst[0]);
1092 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1093 TREE_TYPE (nvec), nvec, tmp);
1094 lower = gfc_index_zero_node;
1095 upper = gfc_index_zero_node;
1096 stride = gfc_index_zero_node;
1097 vector = gfc_conv_descriptor_data_get (vector);
1098 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1099 vector, ar->start[i]->ts.kind, nvec);
1100 break;
1101 default:
1102 gcc_unreachable();
1104 return gfc_build_addr_expr (NULL_TREE, var);
1108 /* Get data from a remote coarray. */
1110 static void
1111 gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
1112 tree may_require_tmp)
1114 gfc_expr *array_expr;
1115 gfc_se argse;
1116 tree caf_decl, token, offset, image_index, tmp;
1117 tree res_var, dst_var, type, kind, vec;
1119 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1121 if (se->ss && se->ss->info->useflags)
1123 /* Access the previously obtained result. */
1124 gfc_conv_tmp_array_ref (se);
1125 return;
1128 /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1129 array_expr = (lhs == NULL_TREE) ? expr->value.function.actual->expr : expr;
1130 type = gfc_typenode_for_spec (&array_expr->ts);
1132 res_var = lhs;
1133 dst_var = lhs;
1135 vec = null_pointer_node;
1137 gfc_init_se (&argse, NULL);
1138 if (array_expr->rank == 0)
1140 symbol_attribute attr;
1142 gfc_clear_attr (&attr);
1143 gfc_conv_expr (&argse, array_expr);
1145 if (lhs == NULL_TREE)
1147 gfc_clear_attr (&attr);
1148 if (array_expr->ts.type == BT_CHARACTER)
1149 res_var = gfc_conv_string_tmp (se, build_pointer_type (type),
1150 argse.string_length);
1151 else
1152 res_var = gfc_create_var (type, "caf_res");
1153 dst_var = gfc_conv_scalar_to_descriptor (&argse, res_var, attr);
1154 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1156 argse.expr = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
1157 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1159 else
1161 /* If has_vector, pass descriptor for whole array and the
1162 vector bounds separately. */
1163 gfc_array_ref *ar, ar2;
1164 bool has_vector = false;
1166 if (gfc_is_coindexed (expr) && gfc_has_vector_subscript (expr))
1168 has_vector = true;
1169 ar = gfc_find_array_ref (expr);
1170 ar2 = *ar;
1171 memset (ar, '\0', sizeof (*ar));
1172 ar->as = ar2.as;
1173 ar->type = AR_FULL;
1175 gfc_conv_expr_descriptor (&argse, array_expr);
1176 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1177 has the wrong type if component references are done. */
1178 gfc_add_modify (&argse.pre, gfc_conv_descriptor_dtype (argse.expr),
1179 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1180 : array_expr->rank,
1181 type));
1182 if (has_vector)
1184 vec = conv_caf_vector_subscript (&argse.pre, argse.expr, &ar2);
1185 *ar = ar2;
1188 if (lhs == NULL_TREE)
1190 /* Create temporary. */
1191 for (int n = 0; n < se->ss->loop->dimen; n++)
1192 if (se->loop->to[n] == NULL_TREE)
1194 se->loop->from[n] =
1195 gfc_conv_descriptor_lbound_get (argse.expr, gfc_rank_cst[n]);
1196 se->loop->to[n] =
1197 gfc_conv_descriptor_ubound_get (argse.expr, gfc_rank_cst[n]);
1199 gfc_trans_create_temp_array (&argse.pre, &argse.post, se->ss, type,
1200 NULL_TREE, false, true, false,
1201 &array_expr->where);
1202 res_var = se->ss->info->data.array.descriptor;
1203 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1205 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1208 kind = build_int_cst (integer_type_node, expr->ts.kind);
1209 if (lhs_kind == NULL_TREE)
1210 lhs_kind = kind;
1212 gfc_add_block_to_block (&se->pre, &argse.pre);
1213 gfc_add_block_to_block (&se->post, &argse.post);
1215 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1216 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1217 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1218 image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
1219 gfc_get_caf_token_offset (&token, &offset, caf_decl, argse.expr, array_expr);
1221 /* No overlap possible as we have generated a temporary. */
1222 if (lhs == NULL_TREE)
1223 may_require_tmp = boolean_false_node;
1225 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 9,
1226 token, offset, image_index, argse.expr, vec,
1227 dst_var, kind, lhs_kind, may_require_tmp);
1228 gfc_add_expr_to_block (&se->pre, tmp);
1230 if (se->ss)
1231 gfc_advance_se_ss_chain (se);
1233 se->expr = res_var;
1234 if (array_expr->ts.type == BT_CHARACTER)
1235 se->string_length = argse.string_length;
1239 /* Send data to a remove coarray. */
1241 static tree
1242 conv_caf_send (gfc_code *code) {
1243 gfc_expr *lhs_expr, *rhs_expr;
1244 gfc_se lhs_se, rhs_se;
1245 stmtblock_t block;
1246 tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
1247 tree may_require_tmp;
1248 tree lhs_type = NULL_TREE;
1249 tree vec = null_pointer_node, rhs_vec = null_pointer_node;
1251 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1253 lhs_expr = code->ext.actual->expr;
1254 rhs_expr = code->ext.actual->next->expr;
1255 may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, false) == 0
1256 ? boolean_false_node : boolean_true_node;
1257 gfc_init_block (&block);
1259 /* LHS. */
1260 gfc_init_se (&lhs_se, NULL);
1261 if (lhs_expr->rank == 0)
1263 symbol_attribute attr;
1264 gfc_clear_attr (&attr);
1265 gfc_conv_expr (&lhs_se, lhs_expr);
1266 lhs_type = TREE_TYPE (lhs_se.expr);
1267 lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr, attr);
1268 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1270 else
1272 /* If has_vector, pass descriptor for whole array and the
1273 vector bounds separately. */
1274 gfc_array_ref *ar, ar2;
1275 bool has_vector = false;
1277 if (gfc_is_coindexed (lhs_expr) && gfc_has_vector_subscript (lhs_expr))
1279 has_vector = true;
1280 ar = gfc_find_array_ref (lhs_expr);
1281 ar2 = *ar;
1282 memset (ar, '\0', sizeof (*ar));
1283 ar->as = ar2.as;
1284 ar->type = AR_FULL;
1286 lhs_se.want_pointer = 1;
1287 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1288 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1289 has the wrong type if component references are done. */
1290 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1291 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1292 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1293 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1294 : lhs_expr->rank,
1295 lhs_type));
1296 if (has_vector)
1298 vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
1299 *ar = ar2;
1303 lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
1304 gfc_add_block_to_block (&block, &lhs_se.pre);
1306 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
1307 temporary and a loop. */
1308 if (!gfc_is_coindexed (lhs_expr))
1310 gcc_assert (gfc_is_coindexed (rhs_expr));
1311 gfc_init_se (&rhs_se, NULL);
1312 gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
1313 may_require_tmp);
1314 gfc_add_block_to_block (&block, &rhs_se.pre);
1315 gfc_add_block_to_block (&block, &rhs_se.post);
1316 gfc_add_block_to_block (&block, &lhs_se.post);
1317 return gfc_finish_block (&block);
1320 /* Obtain token, offset and image index for the LHS. */
1322 caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
1323 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1324 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1325 image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
1326 gfc_get_caf_token_offset (&token, &offset, caf_decl, lhs_se.expr, lhs_expr);
1328 /* RHS. */
1329 gfc_init_se (&rhs_se, NULL);
1330 if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
1331 && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
1332 rhs_expr = rhs_expr->value.function.actual->expr;
1333 if (rhs_expr->rank == 0)
1335 symbol_attribute attr;
1336 gfc_clear_attr (&attr);
1337 gfc_conv_expr (&rhs_se, rhs_expr);
1338 if (!gfc_is_coindexed (rhs_expr) && rhs_expr->ts.type != BT_CHARACTER)
1339 rhs_se.expr = fold_convert (lhs_type , rhs_se.expr);
1340 rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
1341 rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
1343 else
1345 /* If has_vector, pass descriptor for whole array and the
1346 vector bounds separately. */
1347 gfc_array_ref *ar, ar2;
1348 bool has_vector = false;
1349 tree tmp2;
1351 if (gfc_is_coindexed (rhs_expr) && gfc_has_vector_subscript (rhs_expr))
1353 has_vector = true;
1354 ar = gfc_find_array_ref (rhs_expr);
1355 ar2 = *ar;
1356 memset (ar, '\0', sizeof (*ar));
1357 ar->as = ar2.as;
1358 ar->type = AR_FULL;
1360 rhs_se.want_pointer = 1;
1361 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
1362 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1363 has the wrong type if component references are done. */
1364 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
1365 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
1366 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1367 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1368 : rhs_expr->rank,
1369 tmp2));
1370 if (has_vector)
1372 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
1373 *ar = ar2;
1377 gfc_add_block_to_block (&block, &rhs_se.pre);
1379 rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
1381 if (!gfc_is_coindexed (rhs_expr))
1382 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 9, token,
1383 offset, image_index, lhs_se.expr, vec,
1384 rhs_se.expr, lhs_kind, rhs_kind, may_require_tmp);
1385 else
1387 tree rhs_token, rhs_offset, rhs_image_index;
1389 caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
1390 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1391 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1392 rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
1393 gfc_get_caf_token_offset (&rhs_token, &rhs_offset, caf_decl, rhs_se.expr,
1394 rhs_expr);
1395 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget, 13,
1396 token, offset, image_index, lhs_se.expr, vec,
1397 rhs_token, rhs_offset, rhs_image_index,
1398 rhs_se.expr, rhs_vec, lhs_kind, rhs_kind,
1399 may_require_tmp);
1401 gfc_add_expr_to_block (&block, tmp);
1402 gfc_add_block_to_block (&block, &lhs_se.post);
1403 gfc_add_block_to_block (&block, &rhs_se.post);
1404 return gfc_finish_block (&block);
1408 static void
1409 trans_this_image (gfc_se * se, gfc_expr *expr)
1411 stmtblock_t loop;
1412 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
1413 lbound, ubound, extent, ml;
1414 gfc_se argse;
1415 int rank, corank;
1416 gfc_expr *distance = expr->value.function.actual->next->next->expr;
1418 if (expr->value.function.actual->expr
1419 && !gfc_is_coarray (expr->value.function.actual->expr))
1420 distance = expr->value.function.actual->expr;
1422 /* The case -fcoarray=single is handled elsewhere. */
1423 gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
1425 /* Argument-free version: THIS_IMAGE(). */
1426 if (distance || expr->value.function.actual->expr == NULL)
1428 if (distance)
1430 gfc_init_se (&argse, NULL);
1431 gfc_conv_expr_val (&argse, distance);
1432 gfc_add_block_to_block (&se->pre, &argse.pre);
1433 gfc_add_block_to_block (&se->post, &argse.post);
1434 tmp = fold_convert (integer_type_node, argse.expr);
1436 else
1437 tmp = integer_zero_node;
1438 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
1439 tmp);
1440 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
1441 tmp);
1442 return;
1445 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
1447 type = gfc_get_int_type (gfc_default_integer_kind);
1448 corank = gfc_get_corank (expr->value.function.actual->expr);
1449 rank = expr->value.function.actual->expr->rank;
1451 /* Obtain the descriptor of the COARRAY. */
1452 gfc_init_se (&argse, NULL);
1453 argse.want_coarray = 1;
1454 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
1455 gfc_add_block_to_block (&se->pre, &argse.pre);
1456 gfc_add_block_to_block (&se->post, &argse.post);
1457 desc = argse.expr;
1459 if (se->ss)
1461 /* Create an implicit second parameter from the loop variable. */
1462 gcc_assert (!expr->value.function.actual->next->expr);
1463 gcc_assert (corank > 0);
1464 gcc_assert (se->loop->dimen == 1);
1465 gcc_assert (se->ss->info->expr == expr);
1467 dim_arg = se->loop->loopvar[0];
1468 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
1469 gfc_array_index_type, dim_arg,
1470 build_int_cst (TREE_TYPE (dim_arg), 1));
1471 gfc_advance_se_ss_chain (se);
1473 else
1475 /* Use the passed DIM= argument. */
1476 gcc_assert (expr->value.function.actual->next->expr);
1477 gfc_init_se (&argse, NULL);
1478 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
1479 gfc_array_index_type);
1480 gfc_add_block_to_block (&se->pre, &argse.pre);
1481 dim_arg = argse.expr;
1483 if (INTEGER_CST_P (dim_arg))
1485 if (wi::ltu_p (dim_arg, 1)
1486 || wi::gtu_p (dim_arg, GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
1487 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
1488 "dimension index", expr->value.function.isym->name,
1489 &expr->where);
1491 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1493 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
1494 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1495 dim_arg,
1496 build_int_cst (TREE_TYPE (dim_arg), 1));
1497 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
1498 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1499 dim_arg, tmp);
1500 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1501 boolean_type_node, cond, tmp);
1502 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1503 gfc_msg_fault);
1507 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
1508 one always has a dim_arg argument.
1510 m = this_image() - 1
1511 if (corank == 1)
1513 sub(1) = m + lcobound(corank)
1514 return;
1516 i = rank
1517 min_var = min (rank + corank - 2, rank + dim_arg - 1)
1518 for (;;)
1520 extent = gfc_extent(i)
1521 ml = m
1522 m = m/extent
1523 if (i >= min_var)
1524 goto exit_label
1527 exit_label:
1528 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
1529 : m + lcobound(corank)
1532 /* this_image () - 1. */
1533 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
1534 integer_zero_node);
1535 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
1536 fold_convert (type, tmp), build_int_cst (type, 1));
1537 if (corank == 1)
1539 /* sub(1) = m + lcobound(corank). */
1540 lbound = gfc_conv_descriptor_lbound_get (desc,
1541 build_int_cst (TREE_TYPE (gfc_array_index_type),
1542 corank+rank-1));
1543 lbound = fold_convert (type, lbound);
1544 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
1546 se->expr = tmp;
1547 return;
1550 m = gfc_create_var (type, NULL);
1551 ml = gfc_create_var (type, NULL);
1552 loop_var = gfc_create_var (integer_type_node, NULL);
1553 min_var = gfc_create_var (integer_type_node, NULL);
1555 /* m = this_image () - 1. */
1556 gfc_add_modify (&se->pre, m, tmp);
1558 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
1559 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
1560 fold_convert (integer_type_node, dim_arg),
1561 build_int_cst (integer_type_node, rank - 1));
1562 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
1563 build_int_cst (integer_type_node, rank + corank - 2),
1564 tmp);
1565 gfc_add_modify (&se->pre, min_var, tmp);
1567 /* i = rank. */
1568 tmp = build_int_cst (integer_type_node, rank);
1569 gfc_add_modify (&se->pre, loop_var, tmp);
1571 exit_label = gfc_build_label_decl (NULL_TREE);
1572 TREE_USED (exit_label) = 1;
1574 /* Loop body. */
1575 gfc_init_block (&loop);
1577 /* ml = m. */
1578 gfc_add_modify (&loop, ml, m);
1580 /* extent = ... */
1581 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
1582 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
1583 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1584 extent = fold_convert (type, extent);
1586 /* m = m/extent. */
1587 gfc_add_modify (&loop, m,
1588 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
1589 m, extent));
1591 /* Exit condition: if (i >= min_var) goto exit_label. */
1592 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, loop_var,
1593 min_var);
1594 tmp = build1_v (GOTO_EXPR, exit_label);
1595 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
1596 build_empty_stmt (input_location));
1597 gfc_add_expr_to_block (&loop, tmp);
1599 /* Increment loop variable: i++. */
1600 gfc_add_modify (&loop, loop_var,
1601 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
1602 loop_var,
1603 build_int_cst (integer_type_node, 1)));
1605 /* Making the loop... actually loop! */
1606 tmp = gfc_finish_block (&loop);
1607 tmp = build1_v (LOOP_EXPR, tmp);
1608 gfc_add_expr_to_block (&se->pre, tmp);
1610 /* The exit label. */
1611 tmp = build1_v (LABEL_EXPR, exit_label);
1612 gfc_add_expr_to_block (&se->pre, tmp);
1614 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
1615 : m + lcobound(corank) */
1617 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, dim_arg,
1618 build_int_cst (TREE_TYPE (dim_arg), corank));
1620 lbound = gfc_conv_descriptor_lbound_get (desc,
1621 fold_build2_loc (input_location, PLUS_EXPR,
1622 gfc_array_index_type, dim_arg,
1623 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
1624 lbound = fold_convert (type, lbound);
1626 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
1627 fold_build2_loc (input_location, MULT_EXPR, type,
1628 m, extent));
1629 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
1631 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
1632 fold_build2_loc (input_location, PLUS_EXPR, type,
1633 m, lbound));
1637 static void
1638 trans_image_index (gfc_se * se, gfc_expr *expr)
1640 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
1641 tmp, invalid_bound;
1642 gfc_se argse, subse;
1643 int rank, corank, codim;
1645 type = gfc_get_int_type (gfc_default_integer_kind);
1646 corank = gfc_get_corank (expr->value.function.actual->expr);
1647 rank = expr->value.function.actual->expr->rank;
1649 /* Obtain the descriptor of the COARRAY. */
1650 gfc_init_se (&argse, NULL);
1651 argse.want_coarray = 1;
1652 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
1653 gfc_add_block_to_block (&se->pre, &argse.pre);
1654 gfc_add_block_to_block (&se->post, &argse.post);
1655 desc = argse.expr;
1657 /* Obtain a handle to the SUB argument. */
1658 gfc_init_se (&subse, NULL);
1659 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
1660 gfc_add_block_to_block (&se->pre, &subse.pre);
1661 gfc_add_block_to_block (&se->post, &subse.post);
1662 subdesc = build_fold_indirect_ref_loc (input_location,
1663 gfc_conv_descriptor_data_get (subse.expr));
1665 /* Fortran 2008 does not require that the values remain in the cobounds,
1666 thus we need explicitly check this - and return 0 if they are exceeded. */
1668 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
1669 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
1670 invalid_bound = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1671 fold_convert (gfc_array_index_type, tmp),
1672 lbound);
1674 for (codim = corank + rank - 2; codim >= rank; codim--)
1676 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1677 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
1678 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
1679 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1680 fold_convert (gfc_array_index_type, tmp),
1681 lbound);
1682 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1683 boolean_type_node, invalid_bound, cond);
1684 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1685 fold_convert (gfc_array_index_type, tmp),
1686 ubound);
1687 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1688 boolean_type_node, invalid_bound, cond);
1691 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
1693 /* See Fortran 2008, C.10 for the following algorithm. */
1695 /* coindex = sub(corank) - lcobound(n). */
1696 coindex = fold_convert (gfc_array_index_type,
1697 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
1698 NULL));
1699 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
1700 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1701 fold_convert (gfc_array_index_type, coindex),
1702 lbound);
1704 for (codim = corank + rank - 2; codim >= rank; codim--)
1706 tree extent, ubound;
1708 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
1709 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1710 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
1711 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1713 /* coindex *= extent. */
1714 coindex = fold_build2_loc (input_location, MULT_EXPR,
1715 gfc_array_index_type, coindex, extent);
1717 /* coindex += sub(codim). */
1718 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
1719 coindex = fold_build2_loc (input_location, PLUS_EXPR,
1720 gfc_array_index_type, coindex,
1721 fold_convert (gfc_array_index_type, tmp));
1723 /* coindex -= lbound(codim). */
1724 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1725 coindex = fold_build2_loc (input_location, MINUS_EXPR,
1726 gfc_array_index_type, coindex, lbound);
1729 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
1730 fold_convert(type, coindex),
1731 build_int_cst (type, 1));
1733 /* Return 0 if "coindex" exceeds num_images(). */
1735 if (flag_coarray == GFC_FCOARRAY_SINGLE)
1736 num_images = build_int_cst (type, 1);
1737 else
1739 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
1740 integer_zero_node,
1741 build_int_cst (integer_type_node, -1));
1742 num_images = fold_convert (type, tmp);
1745 tmp = gfc_create_var (type, NULL);
1746 gfc_add_modify (&se->pre, tmp, coindex);
1748 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, tmp,
1749 num_images);
1750 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
1751 cond,
1752 fold_convert (boolean_type_node, invalid_bound));
1753 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
1754 build_int_cst (type, 0), tmp);
1758 static void
1759 trans_num_images (gfc_se * se, gfc_expr *expr)
1761 tree tmp, distance, failed;
1762 gfc_se argse;
1764 if (expr->value.function.actual->expr)
1766 gfc_init_se (&argse, NULL);
1767 gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
1768 gfc_add_block_to_block (&se->pre, &argse.pre);
1769 gfc_add_block_to_block (&se->post, &argse.post);
1770 distance = fold_convert (integer_type_node, argse.expr);
1772 else
1773 distance = integer_zero_node;
1775 if (expr->value.function.actual->next->expr)
1777 gfc_init_se (&argse, NULL);
1778 gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
1779 gfc_add_block_to_block (&se->pre, &argse.pre);
1780 gfc_add_block_to_block (&se->post, &argse.post);
1781 failed = fold_convert (integer_type_node, argse.expr);
1783 else
1784 failed = build_int_cst (integer_type_node, -1);
1786 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
1787 distance, failed);
1788 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
1792 static void
1793 gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
1795 gfc_se argse;
1797 gfc_init_se (&argse, NULL);
1798 argse.data_not_needed = 1;
1799 argse.descriptor_only = 1;
1801 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
1802 gfc_add_block_to_block (&se->pre, &argse.pre);
1803 gfc_add_block_to_block (&se->post, &argse.post);
1805 se->expr = gfc_conv_descriptor_rank (argse.expr);
1809 /* Evaluate a single upper or lower bound. */
1810 /* TODO: bound intrinsic generates way too much unnecessary code. */
1812 static void
1813 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
1815 gfc_actual_arglist *arg;
1816 gfc_actual_arglist *arg2;
1817 tree desc;
1818 tree type;
1819 tree bound;
1820 tree tmp;
1821 tree cond, cond1, cond3, cond4, size;
1822 tree ubound;
1823 tree lbound;
1824 gfc_se argse;
1825 gfc_array_spec * as;
1826 bool assumed_rank_lb_one;
1828 arg = expr->value.function.actual;
1829 arg2 = arg->next;
1831 if (se->ss)
1833 /* Create an implicit second parameter from the loop variable. */
1834 gcc_assert (!arg2->expr);
1835 gcc_assert (se->loop->dimen == 1);
1836 gcc_assert (se->ss->info->expr == expr);
1837 gfc_advance_se_ss_chain (se);
1838 bound = se->loop->loopvar[0];
1839 bound = fold_build2_loc (input_location, MINUS_EXPR,
1840 gfc_array_index_type, bound,
1841 se->loop->from[0]);
1843 else
1845 /* use the passed argument. */
1846 gcc_assert (arg2->expr);
1847 gfc_init_se (&argse, NULL);
1848 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
1849 gfc_add_block_to_block (&se->pre, &argse.pre);
1850 bound = argse.expr;
1851 /* Convert from one based to zero based. */
1852 bound = fold_build2_loc (input_location, MINUS_EXPR,
1853 gfc_array_index_type, bound,
1854 gfc_index_one_node);
1857 /* TODO: don't re-evaluate the descriptor on each iteration. */
1858 /* Get a descriptor for the first parameter. */
1859 gfc_init_se (&argse, NULL);
1860 gfc_conv_expr_descriptor (&argse, arg->expr);
1861 gfc_add_block_to_block (&se->pre, &argse.pre);
1862 gfc_add_block_to_block (&se->post, &argse.post);
1864 desc = argse.expr;
1866 as = gfc_get_full_arrayspec_from_expr (arg->expr);
1868 if (INTEGER_CST_P (bound))
1870 if (((!as || as->type != AS_ASSUMED_RANK)
1871 && wi::geu_p (bound, GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
1872 || wi::gtu_p (bound, GFC_MAX_DIMENSIONS))
1873 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
1874 "dimension index", upper ? "UBOUND" : "LBOUND",
1875 &expr->where);
1878 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
1880 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1882 bound = gfc_evaluate_now (bound, &se->pre);
1883 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1884 bound, build_int_cst (TREE_TYPE (bound), 0));
1885 if (as && as->type == AS_ASSUMED_RANK)
1886 tmp = gfc_conv_descriptor_rank (desc);
1887 else
1888 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
1889 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1890 bound, fold_convert(TREE_TYPE (bound), tmp));
1891 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1892 boolean_type_node, cond, tmp);
1893 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1894 gfc_msg_fault);
1898 /* Take care of the lbound shift for assumed-rank arrays, which are
1899 nonallocatable and nonpointers. Those has a lbound of 1. */
1900 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
1901 && ((arg->expr->ts.type != BT_CLASS
1902 && !arg->expr->symtree->n.sym->attr.allocatable
1903 && !arg->expr->symtree->n.sym->attr.pointer)
1904 || (arg->expr->ts.type == BT_CLASS
1905 && !CLASS_DATA (arg->expr)->attr.allocatable
1906 && !CLASS_DATA (arg->expr)->attr.class_pointer));
1908 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
1909 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
1911 /* 13.14.53: Result value for LBOUND
1913 Case (i): For an array section or for an array expression other than a
1914 whole array or array structure component, LBOUND(ARRAY, DIM)
1915 has the value 1. For a whole array or array structure
1916 component, LBOUND(ARRAY, DIM) has the value:
1917 (a) equal to the lower bound for subscript DIM of ARRAY if
1918 dimension DIM of ARRAY does not have extent zero
1919 or if ARRAY is an assumed-size array of rank DIM,
1920 or (b) 1 otherwise.
1922 13.14.113: Result value for UBOUND
1924 Case (i): For an array section or for an array expression other than a
1925 whole array or array structure component, UBOUND(ARRAY, DIM)
1926 has the value equal to the number of elements in the given
1927 dimension; otherwise, it has a value equal to the upper bound
1928 for subscript DIM of ARRAY if dimension DIM of ARRAY does
1929 not have size zero and has value zero if dimension DIM has
1930 size zero. */
1932 if (!upper && assumed_rank_lb_one)
1933 se->expr = gfc_index_one_node;
1934 else if (as)
1936 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
1938 cond1 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1939 ubound, lbound);
1940 cond3 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1941 stride, gfc_index_zero_node);
1942 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1943 boolean_type_node, cond3, cond1);
1944 cond4 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1945 stride, gfc_index_zero_node);
1947 if (upper)
1949 tree cond5;
1950 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1951 boolean_type_node, cond3, cond4);
1952 cond5 = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1953 gfc_index_one_node, lbound);
1954 cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1955 boolean_type_node, cond4, cond5);
1957 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1958 boolean_type_node, cond, cond5);
1960 if (assumed_rank_lb_one)
1962 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1963 gfc_array_index_type, ubound, lbound);
1964 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1965 gfc_array_index_type, tmp, gfc_index_one_node);
1967 else
1968 tmp = ubound;
1970 se->expr = fold_build3_loc (input_location, COND_EXPR,
1971 gfc_array_index_type, cond,
1972 tmp, gfc_index_zero_node);
1974 else
1976 if (as->type == AS_ASSUMED_SIZE)
1977 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1978 bound, build_int_cst (TREE_TYPE (bound),
1979 arg->expr->rank - 1));
1980 else
1981 cond = boolean_false_node;
1983 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1984 boolean_type_node, cond3, cond4);
1985 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1986 boolean_type_node, cond, cond1);
1988 se->expr = fold_build3_loc (input_location, COND_EXPR,
1989 gfc_array_index_type, cond,
1990 lbound, gfc_index_one_node);
1993 else
1995 if (upper)
1997 size = fold_build2_loc (input_location, MINUS_EXPR,
1998 gfc_array_index_type, ubound, lbound);
1999 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
2000 gfc_array_index_type, size,
2001 gfc_index_one_node);
2002 se->expr = fold_build2_loc (input_location, MAX_EXPR,
2003 gfc_array_index_type, se->expr,
2004 gfc_index_zero_node);
2006 else
2007 se->expr = gfc_index_one_node;
2010 type = gfc_typenode_for_spec (&expr->ts);
2011 se->expr = convert (type, se->expr);
2015 static void
2016 conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
2018 gfc_actual_arglist *arg;
2019 gfc_actual_arglist *arg2;
2020 gfc_se argse;
2021 tree bound, resbound, resbound2, desc, cond, tmp;
2022 tree type;
2023 int corank;
2025 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
2026 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
2027 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
2029 arg = expr->value.function.actual;
2030 arg2 = arg->next;
2032 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
2033 corank = gfc_get_corank (arg->expr);
2035 gfc_init_se (&argse, NULL);
2036 argse.want_coarray = 1;
2038 gfc_conv_expr_descriptor (&argse, arg->expr);
2039 gfc_add_block_to_block (&se->pre, &argse.pre);
2040 gfc_add_block_to_block (&se->post, &argse.post);
2041 desc = argse.expr;
2043 if (se->ss)
2045 /* Create an implicit second parameter from the loop variable. */
2046 gcc_assert (!arg2->expr);
2047 gcc_assert (corank > 0);
2048 gcc_assert (se->loop->dimen == 1);
2049 gcc_assert (se->ss->info->expr == expr);
2051 bound = se->loop->loopvar[0];
2052 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2053 bound, gfc_rank_cst[arg->expr->rank]);
2054 gfc_advance_se_ss_chain (se);
2056 else
2058 /* use the passed argument. */
2059 gcc_assert (arg2->expr);
2060 gfc_init_se (&argse, NULL);
2061 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2062 gfc_add_block_to_block (&se->pre, &argse.pre);
2063 bound = argse.expr;
2065 if (INTEGER_CST_P (bound))
2067 if (wi::ltu_p (bound, 1)
2068 || wi::gtu_p (bound, GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2069 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2070 "dimension index", expr->value.function.isym->name,
2071 &expr->where);
2073 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2075 bound = gfc_evaluate_now (bound, &se->pre);
2076 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2077 bound, build_int_cst (TREE_TYPE (bound), 1));
2078 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2079 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2080 bound, tmp);
2081 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2082 boolean_type_node, cond, tmp);
2083 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2084 gfc_msg_fault);
2088 /* Subtract 1 to get to zero based and add dimensions. */
2089 switch (arg->expr->rank)
2091 case 0:
2092 bound = fold_build2_loc (input_location, MINUS_EXPR,
2093 gfc_array_index_type, bound,
2094 gfc_index_one_node);
2095 case 1:
2096 break;
2097 default:
2098 bound = fold_build2_loc (input_location, PLUS_EXPR,
2099 gfc_array_index_type, bound,
2100 gfc_rank_cst[arg->expr->rank - 1]);
2104 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
2106 /* Handle UCOBOUND with special handling of the last codimension. */
2107 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
2109 /* Last codimension: For -fcoarray=single just return
2110 the lcobound - otherwise add
2111 ceiling (real (num_images ()) / real (size)) - 1
2112 = (num_images () + size - 1) / size - 1
2113 = (num_images - 1) / size(),
2114 where size is the product of the extent of all but the last
2115 codimension. */
2117 if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
2119 tree cosize;
2121 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
2122 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
2123 2, integer_zero_node,
2124 build_int_cst (integer_type_node, -1));
2125 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2126 gfc_array_index_type,
2127 fold_convert (gfc_array_index_type, tmp),
2128 build_int_cst (gfc_array_index_type, 1));
2129 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
2130 gfc_array_index_type, tmp,
2131 fold_convert (gfc_array_index_type, cosize));
2132 resbound = fold_build2_loc (input_location, PLUS_EXPR,
2133 gfc_array_index_type, resbound, tmp);
2135 else if (flag_coarray != GFC_FCOARRAY_SINGLE)
2137 /* ubound = lbound + num_images() - 1. */
2138 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
2139 2, integer_zero_node,
2140 build_int_cst (integer_type_node, -1));
2141 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2142 gfc_array_index_type,
2143 fold_convert (gfc_array_index_type, tmp),
2144 build_int_cst (gfc_array_index_type, 1));
2145 resbound = fold_build2_loc (input_location, PLUS_EXPR,
2146 gfc_array_index_type, resbound, tmp);
2149 if (corank > 1)
2151 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2152 bound,
2153 build_int_cst (TREE_TYPE (bound),
2154 arg->expr->rank + corank - 1));
2156 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
2157 se->expr = fold_build3_loc (input_location, COND_EXPR,
2158 gfc_array_index_type, cond,
2159 resbound, resbound2);
2161 else
2162 se->expr = resbound;
2164 else
2165 se->expr = resbound;
2167 type = gfc_typenode_for_spec (&expr->ts);
2168 se->expr = convert (type, se->expr);
2172 static void
2173 conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
2175 gfc_actual_arglist *array_arg;
2176 gfc_actual_arglist *dim_arg;
2177 gfc_se argse;
2178 tree desc, tmp;
2180 array_arg = expr->value.function.actual;
2181 dim_arg = array_arg->next;
2183 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
2185 gfc_init_se (&argse, NULL);
2186 gfc_conv_expr_descriptor (&argse, array_arg->expr);
2187 gfc_add_block_to_block (&se->pre, &argse.pre);
2188 gfc_add_block_to_block (&se->post, &argse.post);
2189 desc = argse.expr;
2191 gcc_assert (dim_arg->expr);
2192 gfc_init_se (&argse, NULL);
2193 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
2194 gfc_add_block_to_block (&se->pre, &argse.pre);
2195 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2196 argse.expr, gfc_index_one_node);
2197 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
2201 static void
2202 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
2204 tree arg, cabs;
2206 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
2208 switch (expr->value.function.actual->expr->ts.type)
2210 case BT_INTEGER:
2211 case BT_REAL:
2212 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
2213 arg);
2214 break;
2216 case BT_COMPLEX:
2217 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
2218 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
2219 break;
2221 default:
2222 gcc_unreachable ();
2227 /* Create a complex value from one or two real components. */
2229 static void
2230 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
2232 tree real;
2233 tree imag;
2234 tree type;
2235 tree *args;
2236 unsigned int num_args;
2238 num_args = gfc_intrinsic_argument_list_length (expr);
2239 args = XALLOCAVEC (tree, num_args);
2241 type = gfc_typenode_for_spec (&expr->ts);
2242 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2243 real = convert (TREE_TYPE (type), args[0]);
2244 if (both)
2245 imag = convert (TREE_TYPE (type), args[1]);
2246 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
2248 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
2249 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
2250 imag = convert (TREE_TYPE (type), imag);
2252 else
2253 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
2255 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
2259 /* Remainder function MOD(A, P) = A - INT(A / P) * P
2260 MODULO(A, P) = A - FLOOR (A / P) * P
2262 The obvious algorithms above are numerically instable for large
2263 arguments, hence these intrinsics are instead implemented via calls
2264 to the fmod family of functions. It is the responsibility of the
2265 user to ensure that the second argument is non-zero. */
2267 static void
2268 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
2270 tree type;
2271 tree tmp;
2272 tree test;
2273 tree test2;
2274 tree fmod;
2275 tree zero;
2276 tree args[2];
2278 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2280 switch (expr->ts.type)
2282 case BT_INTEGER:
2283 /* Integer case is easy, we've got a builtin op. */
2284 type = TREE_TYPE (args[0]);
2286 if (modulo)
2287 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
2288 args[0], args[1]);
2289 else
2290 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
2291 args[0], args[1]);
2292 break;
2294 case BT_REAL:
2295 fmod = NULL_TREE;
2296 /* Check if we have a builtin fmod. */
2297 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
2299 /* The builtin should always be available. */
2300 gcc_assert (fmod != NULL_TREE);
2302 tmp = build_addr (fmod, current_function_decl);
2303 se->expr = build_call_array_loc (input_location,
2304 TREE_TYPE (TREE_TYPE (fmod)),
2305 tmp, 2, args);
2306 if (modulo == 0)
2307 return;
2309 type = TREE_TYPE (args[0]);
2311 args[0] = gfc_evaluate_now (args[0], &se->pre);
2312 args[1] = gfc_evaluate_now (args[1], &se->pre);
2314 /* Definition:
2315 modulo = arg - floor (arg/arg2) * arg2
2317 In order to calculate the result accurately, we use the fmod
2318 function as follows.
2320 res = fmod (arg, arg2);
2321 if (res)
2323 if ((arg < 0) xor (arg2 < 0))
2324 res += arg2;
2326 else
2327 res = copysign (0., arg2);
2329 => As two nested ternary exprs:
2331 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
2332 : copysign (0., arg2);
2336 zero = gfc_build_const (type, integer_zero_node);
2337 tmp = gfc_evaluate_now (se->expr, &se->pre);
2338 if (!flag_signed_zeros)
2340 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2341 args[0], zero);
2342 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2343 args[1], zero);
2344 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
2345 boolean_type_node, test, test2);
2346 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
2347 tmp, zero);
2348 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2349 boolean_type_node, test, test2);
2350 test = gfc_evaluate_now (test, &se->pre);
2351 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
2352 fold_build2_loc (input_location,
2353 PLUS_EXPR,
2354 type, tmp, args[1]),
2355 tmp);
2357 else
2359 tree expr1, copysign, cscall;
2360 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
2361 expr->ts.kind);
2362 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2363 args[0], zero);
2364 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2365 args[1], zero);
2366 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
2367 boolean_type_node, test, test2);
2368 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
2369 fold_build2_loc (input_location,
2370 PLUS_EXPR,
2371 type, tmp, args[1]),
2372 tmp);
2373 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
2374 tmp, zero);
2375 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
2376 args[1]);
2377 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
2378 expr1, cscall);
2380 return;
2382 default:
2383 gcc_unreachable ();
2387 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
2388 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
2389 where the right shifts are logical (i.e. 0's are shifted in).
2390 Because SHIFT_EXPR's want shifts strictly smaller than the integral
2391 type width, we have to special-case both S == 0 and S == BITSIZE(J):
2392 DSHIFTL(I,J,0) = I
2393 DSHIFTL(I,J,BITSIZE) = J
2394 DSHIFTR(I,J,0) = J
2395 DSHIFTR(I,J,BITSIZE) = I. */
2397 static void
2398 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
2400 tree type, utype, stype, arg1, arg2, shift, res, left, right;
2401 tree args[3], cond, tmp;
2402 int bitsize;
2404 gfc_conv_intrinsic_function_args (se, expr, args, 3);
2406 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
2407 type = TREE_TYPE (args[0]);
2408 bitsize = TYPE_PRECISION (type);
2409 utype = unsigned_type_for (type);
2410 stype = TREE_TYPE (args[2]);
2412 arg1 = gfc_evaluate_now (args[0], &se->pre);
2413 arg2 = gfc_evaluate_now (args[1], &se->pre);
2414 shift = gfc_evaluate_now (args[2], &se->pre);
2416 /* The generic case. */
2417 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
2418 build_int_cst (stype, bitsize), shift);
2419 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
2420 arg1, dshiftl ? shift : tmp);
2422 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
2423 fold_convert (utype, arg2), dshiftl ? tmp : shift);
2424 right = fold_convert (type, right);
2426 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
2428 /* Special cases. */
2429 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
2430 build_int_cst (stype, 0));
2431 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
2432 dshiftl ? arg1 : arg2, res);
2434 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
2435 build_int_cst (stype, bitsize));
2436 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
2437 dshiftl ? arg2 : arg1, res);
2439 se->expr = res;
2443 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
2445 static void
2446 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
2448 tree val;
2449 tree tmp;
2450 tree type;
2451 tree zero;
2452 tree args[2];
2454 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2455 type = TREE_TYPE (args[0]);
2457 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
2458 val = gfc_evaluate_now (val, &se->pre);
2460 zero = gfc_build_const (type, integer_zero_node);
2461 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, val, zero);
2462 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
2466 /* SIGN(A, B) is absolute value of A times sign of B.
2467 The real value versions use library functions to ensure the correct
2468 handling of negative zero. Integer case implemented as:
2469 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
2472 static void
2473 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
2475 tree tmp;
2476 tree type;
2477 tree args[2];
2479 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2480 if (expr->ts.type == BT_REAL)
2482 tree abs;
2484 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
2485 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
2487 /* We explicitly have to ignore the minus sign. We do so by using
2488 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
2489 if (!flag_sign_zero
2490 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
2492 tree cond, zero;
2493 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
2494 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2495 args[1], zero);
2496 se->expr = fold_build3_loc (input_location, COND_EXPR,
2497 TREE_TYPE (args[0]), cond,
2498 build_call_expr_loc (input_location, abs, 1,
2499 args[0]),
2500 build_call_expr_loc (input_location, tmp, 2,
2501 args[0], args[1]));
2503 else
2504 se->expr = build_call_expr_loc (input_location, tmp, 2,
2505 args[0], args[1]);
2506 return;
2509 /* Having excluded floating point types, we know we are now dealing
2510 with signed integer types. */
2511 type = TREE_TYPE (args[0]);
2513 /* Args[0] is used multiple times below. */
2514 args[0] = gfc_evaluate_now (args[0], &se->pre);
2516 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
2517 the signs of A and B are the same, and of all ones if they differ. */
2518 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
2519 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
2520 build_int_cst (type, TYPE_PRECISION (type) - 1));
2521 tmp = gfc_evaluate_now (tmp, &se->pre);
2523 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
2524 is all ones (i.e. -1). */
2525 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
2526 fold_build2_loc (input_location, PLUS_EXPR,
2527 type, args[0], tmp), tmp);
2531 /* Test for the presence of an optional argument. */
2533 static void
2534 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
2536 gfc_expr *arg;
2538 arg = expr->value.function.actual->expr;
2539 gcc_assert (arg->expr_type == EXPR_VARIABLE);
2540 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
2541 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
2545 /* Calculate the double precision product of two single precision values. */
2547 static void
2548 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
2550 tree type;
2551 tree args[2];
2553 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2555 /* Convert the args to double precision before multiplying. */
2556 type = gfc_typenode_for_spec (&expr->ts);
2557 args[0] = convert (type, args[0]);
2558 args[1] = convert (type, args[1]);
2559 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
2560 args[1]);
2564 /* Return a length one character string containing an ascii character. */
2566 static void
2567 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
2569 tree arg[2];
2570 tree var;
2571 tree type;
2572 unsigned int num_args;
2574 num_args = gfc_intrinsic_argument_list_length (expr);
2575 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
2577 type = gfc_get_char_type (expr->ts.kind);
2578 var = gfc_create_var (type, "char");
2580 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
2581 gfc_add_modify (&se->pre, var, arg[0]);
2582 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
2583 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
2587 static void
2588 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
2590 tree var;
2591 tree len;
2592 tree tmp;
2593 tree cond;
2594 tree fndecl;
2595 tree *args;
2596 unsigned int num_args;
2598 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2599 args = XALLOCAVEC (tree, num_args);
2601 var = gfc_create_var (pchar_type_node, "pstr");
2602 len = gfc_create_var (gfc_charlen_type_node, "len");
2604 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2605 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2606 args[1] = gfc_build_addr_expr (NULL_TREE, len);
2608 fndecl = build_addr (gfor_fndecl_ctime, current_function_decl);
2609 tmp = build_call_array_loc (input_location,
2610 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
2611 fndecl, num_args, args);
2612 gfc_add_expr_to_block (&se->pre, tmp);
2614 /* Free the temporary afterwards, if necessary. */
2615 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2616 len, build_int_cst (TREE_TYPE (len), 0));
2617 tmp = gfc_call_free (var);
2618 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2619 gfc_add_expr_to_block (&se->post, tmp);
2621 se->expr = var;
2622 se->string_length = len;
2626 static void
2627 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
2629 tree var;
2630 tree len;
2631 tree tmp;
2632 tree cond;
2633 tree fndecl;
2634 tree *args;
2635 unsigned int num_args;
2637 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2638 args = XALLOCAVEC (tree, num_args);
2640 var = gfc_create_var (pchar_type_node, "pstr");
2641 len = gfc_create_var (gfc_charlen_type_node, "len");
2643 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2644 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2645 args[1] = gfc_build_addr_expr (NULL_TREE, len);
2647 fndecl = build_addr (gfor_fndecl_fdate, current_function_decl);
2648 tmp = build_call_array_loc (input_location,
2649 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
2650 fndecl, num_args, args);
2651 gfc_add_expr_to_block (&se->pre, tmp);
2653 /* Free the temporary afterwards, if necessary. */
2654 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2655 len, build_int_cst (TREE_TYPE (len), 0));
2656 tmp = gfc_call_free (var);
2657 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2658 gfc_add_expr_to_block (&se->post, tmp);
2660 se->expr = var;
2661 se->string_length = len;
2665 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
2666 conversions. */
2668 static tree
2669 conv_intrinsic_system_clock (gfc_code *code)
2671 stmtblock_t block;
2672 gfc_se count_se, count_rate_se, count_max_se;
2673 tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
2674 tree tmp;
2675 int least;
2677 gfc_expr *count = code->ext.actual->expr;
2678 gfc_expr *count_rate = code->ext.actual->next->expr;
2679 gfc_expr *count_max = code->ext.actual->next->next->expr;
2681 /* Evaluate our arguments. */
2682 if (count)
2684 gfc_init_se (&count_se, NULL);
2685 gfc_conv_expr (&count_se, count);
2688 if (count_rate)
2690 gfc_init_se (&count_rate_se, NULL);
2691 gfc_conv_expr (&count_rate_se, count_rate);
2694 if (count_max)
2696 gfc_init_se (&count_max_se, NULL);
2697 gfc_conv_expr (&count_max_se, count_max);
2700 /* Find the smallest kind found of the arguments. */
2701 least = 16;
2702 least = (count && count->ts.kind < least) ? count->ts.kind : least;
2703 least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
2704 : least;
2705 least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
2706 : least;
2708 /* Prepare temporary variables. */
2710 if (count)
2712 if (least >= 8)
2713 arg1 = gfc_create_var (gfc_get_int_type (8), "count");
2714 else if (least == 4)
2715 arg1 = gfc_create_var (gfc_get_int_type (4), "count");
2716 else if (count->ts.kind == 1)
2717 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
2718 count->ts.kind);
2719 else
2720 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
2721 count->ts.kind);
2724 if (count_rate)
2726 if (least >= 8)
2727 arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
2728 else if (least == 4)
2729 arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
2730 else
2731 arg2 = integer_zero_node;
2734 if (count_max)
2736 if (least >= 8)
2737 arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
2738 else if (least == 4)
2739 arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
2740 else
2741 arg3 = integer_zero_node;
2744 /* Make the function call. */
2745 gfc_init_block (&block);
2747 if (least <= 2)
2749 if (least == 1)
2751 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
2752 : null_pointer_node;
2753 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
2754 : null_pointer_node;
2755 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
2756 : null_pointer_node;
2759 if (least == 2)
2761 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
2762 : null_pointer_node;
2763 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
2764 : null_pointer_node;
2765 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
2766 : null_pointer_node;
2769 else
2771 if (least == 4)
2773 tmp = build_call_expr_loc (input_location,
2774 gfor_fndecl_system_clock4, 3,
2775 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
2776 : null_pointer_node,
2777 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
2778 : null_pointer_node,
2779 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
2780 : null_pointer_node);
2781 gfc_add_expr_to_block (&block, tmp);
2783 /* Handle kind>=8, 10, or 16 arguments */
2784 if (least >= 8)
2786 tmp = build_call_expr_loc (input_location,
2787 gfor_fndecl_system_clock8, 3,
2788 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
2789 : null_pointer_node,
2790 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
2791 : null_pointer_node,
2792 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
2793 : null_pointer_node);
2794 gfc_add_expr_to_block (&block, tmp);
2798 /* And store values back if needed. */
2799 if (arg1 && arg1 != count_se.expr)
2800 gfc_add_modify (&block, count_se.expr,
2801 fold_convert (TREE_TYPE (count_se.expr), arg1));
2802 if (arg2 && arg2 != count_rate_se.expr)
2803 gfc_add_modify (&block, count_rate_se.expr,
2804 fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
2805 if (arg3 && arg3 != count_max_se.expr)
2806 gfc_add_modify (&block, count_max_se.expr,
2807 fold_convert (TREE_TYPE (count_max_se.expr), arg3));
2809 return gfc_finish_block (&block);
2813 /* Return a character string containing the tty name. */
2815 static void
2816 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
2818 tree var;
2819 tree len;
2820 tree tmp;
2821 tree cond;
2822 tree fndecl;
2823 tree *args;
2824 unsigned int num_args;
2826 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2827 args = XALLOCAVEC (tree, num_args);
2829 var = gfc_create_var (pchar_type_node, "pstr");
2830 len = gfc_create_var (gfc_charlen_type_node, "len");
2832 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2833 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2834 args[1] = gfc_build_addr_expr (NULL_TREE, len);
2836 fndecl = build_addr (gfor_fndecl_ttynam, current_function_decl);
2837 tmp = build_call_array_loc (input_location,
2838 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
2839 fndecl, num_args, args);
2840 gfc_add_expr_to_block (&se->pre, tmp);
2842 /* Free the temporary afterwards, if necessary. */
2843 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2844 len, build_int_cst (TREE_TYPE (len), 0));
2845 tmp = gfc_call_free (var);
2846 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2847 gfc_add_expr_to_block (&se->post, tmp);
2849 se->expr = var;
2850 se->string_length = len;
2854 /* Get the minimum/maximum value of all the parameters.
2855 minmax (a1, a2, a3, ...)
2857 mvar = a1;
2858 if (a2 .op. mvar || isnan (mvar))
2859 mvar = a2;
2860 if (a3 .op. mvar || isnan (mvar))
2861 mvar = a3;
2863 return mvar
2867 /* TODO: Mismatching types can occur when specific names are used.
2868 These should be handled during resolution. */
2869 static void
2870 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
2872 tree tmp;
2873 tree mvar;
2874 tree val;
2875 tree thencase;
2876 tree *args;
2877 tree type;
2878 gfc_actual_arglist *argexpr;
2879 unsigned int i, nargs;
2881 nargs = gfc_intrinsic_argument_list_length (expr);
2882 args = XALLOCAVEC (tree, nargs);
2884 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
2885 type = gfc_typenode_for_spec (&expr->ts);
2887 argexpr = expr->value.function.actual;
2888 if (TREE_TYPE (args[0]) != type)
2889 args[0] = convert (type, args[0]);
2890 /* Only evaluate the argument once. */
2891 if (TREE_CODE (args[0]) != VAR_DECL && !TREE_CONSTANT (args[0]))
2892 args[0] = gfc_evaluate_now (args[0], &se->pre);
2894 mvar = gfc_create_var (type, "M");
2895 gfc_add_modify (&se->pre, mvar, args[0]);
2896 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
2898 tree cond, isnan;
2900 val = args[i];
2902 /* Handle absent optional arguments by ignoring the comparison. */
2903 if (argexpr->expr->expr_type == EXPR_VARIABLE
2904 && argexpr->expr->symtree->n.sym->attr.optional
2905 && TREE_CODE (val) == INDIRECT_REF)
2906 cond = fold_build2_loc (input_location,
2907 NE_EXPR, boolean_type_node,
2908 TREE_OPERAND (val, 0),
2909 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
2910 else
2912 cond = NULL_TREE;
2914 /* Only evaluate the argument once. */
2915 if (TREE_CODE (val) != VAR_DECL && !TREE_CONSTANT (val))
2916 val = gfc_evaluate_now (val, &se->pre);
2919 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
2921 tmp = fold_build2_loc (input_location, op, boolean_type_node,
2922 convert (type, val), mvar);
2924 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
2925 __builtin_isnan might be made dependent on that module being loaded,
2926 to help performance of programs that don't rely on IEEE semantics. */
2927 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
2929 isnan = build_call_expr_loc (input_location,
2930 builtin_decl_explicit (BUILT_IN_ISNAN),
2931 1, mvar);
2932 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2933 boolean_type_node, tmp,
2934 fold_convert (boolean_type_node, isnan));
2936 tmp = build3_v (COND_EXPR, tmp, thencase,
2937 build_empty_stmt (input_location));
2939 if (cond != NULL_TREE)
2940 tmp = build3_v (COND_EXPR, cond, tmp,
2941 build_empty_stmt (input_location));
2943 gfc_add_expr_to_block (&se->pre, tmp);
2944 argexpr = argexpr->next;
2946 se->expr = mvar;
2950 /* Generate library calls for MIN and MAX intrinsics for character
2951 variables. */
2952 static void
2953 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
2955 tree *args;
2956 tree var, len, fndecl, tmp, cond, function;
2957 unsigned int nargs;
2959 nargs = gfc_intrinsic_argument_list_length (expr);
2960 args = XALLOCAVEC (tree, nargs + 4);
2961 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
2963 /* Create the result variables. */
2964 len = gfc_create_var (gfc_charlen_type_node, "len");
2965 args[0] = gfc_build_addr_expr (NULL_TREE, len);
2966 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
2967 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
2968 args[2] = build_int_cst (integer_type_node, op);
2969 args[3] = build_int_cst (integer_type_node, nargs / 2);
2971 if (expr->ts.kind == 1)
2972 function = gfor_fndecl_string_minmax;
2973 else if (expr->ts.kind == 4)
2974 function = gfor_fndecl_string_minmax_char4;
2975 else
2976 gcc_unreachable ();
2978 /* Make the function call. */
2979 fndecl = build_addr (function, current_function_decl);
2980 tmp = build_call_array_loc (input_location,
2981 TREE_TYPE (TREE_TYPE (function)), fndecl,
2982 nargs + 4, args);
2983 gfc_add_expr_to_block (&se->pre, tmp);
2985 /* Free the temporary afterwards, if necessary. */
2986 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2987 len, build_int_cst (TREE_TYPE (len), 0));
2988 tmp = gfc_call_free (var);
2989 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2990 gfc_add_expr_to_block (&se->post, tmp);
2992 se->expr = var;
2993 se->string_length = len;
2997 /* Create a symbol node for this intrinsic. The symbol from the frontend
2998 has the generic name. */
3000 static gfc_symbol *
3001 gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
3003 gfc_symbol *sym;
3005 /* TODO: Add symbols for intrinsic function to the global namespace. */
3006 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
3007 sym = gfc_new_symbol (expr->value.function.name, NULL);
3009 sym->ts = expr->ts;
3010 sym->attr.external = 1;
3011 sym->attr.function = 1;
3012 sym->attr.always_explicit = 1;
3013 sym->attr.proc = PROC_INTRINSIC;
3014 sym->attr.flavor = FL_PROCEDURE;
3015 sym->result = sym;
3016 if (expr->rank > 0)
3018 sym->attr.dimension = 1;
3019 sym->as = gfc_get_array_spec ();
3020 sym->as->type = AS_ASSUMED_SHAPE;
3021 sym->as->rank = expr->rank;
3024 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
3025 ignore_optional ? expr->value.function.actual
3026 : NULL);
3028 return sym;
3031 /* Generate a call to an external intrinsic function. */
3032 static void
3033 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
3035 gfc_symbol *sym;
3036 vec<tree, va_gc> *append_args;
3038 gcc_assert (!se->ss || se->ss->info->expr == expr);
3040 if (se->ss)
3041 gcc_assert (expr->rank > 0);
3042 else
3043 gcc_assert (expr->rank == 0);
3045 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
3047 /* Calls to libgfortran_matmul need to be appended special arguments,
3048 to be able to call the BLAS ?gemm functions if required and possible. */
3049 append_args = NULL;
3050 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
3051 && sym->ts.type != BT_LOGICAL)
3053 tree cint = gfc_get_int_type (gfc_c_int_kind);
3055 if (flag_external_blas
3056 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
3057 && (sym->ts.kind == 4 || sym->ts.kind == 8))
3059 tree gemm_fndecl;
3061 if (sym->ts.type == BT_REAL)
3063 if (sym->ts.kind == 4)
3064 gemm_fndecl = gfor_fndecl_sgemm;
3065 else
3066 gemm_fndecl = gfor_fndecl_dgemm;
3068 else
3070 if (sym->ts.kind == 4)
3071 gemm_fndecl = gfor_fndecl_cgemm;
3072 else
3073 gemm_fndecl = gfor_fndecl_zgemm;
3076 vec_alloc (append_args, 3);
3077 append_args->quick_push (build_int_cst (cint, 1));
3078 append_args->quick_push (build_int_cst (cint,
3079 flag_blas_matmul_limit));
3080 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
3081 gemm_fndecl));
3083 else
3085 vec_alloc (append_args, 3);
3086 append_args->quick_push (build_int_cst (cint, 0));
3087 append_args->quick_push (build_int_cst (cint, 0));
3088 append_args->quick_push (null_pointer_node);
3092 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
3093 append_args);
3094 gfc_free_symbol (sym);
3097 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
3098 Implemented as
3099 any(a)
3101 forall (i=...)
3102 if (a[i] != 0)
3103 return 1
3104 end forall
3105 return 0
3107 all(a)
3109 forall (i=...)
3110 if (a[i] == 0)
3111 return 0
3112 end forall
3113 return 1
3116 static void
3117 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
3119 tree resvar;
3120 stmtblock_t block;
3121 stmtblock_t body;
3122 tree type;
3123 tree tmp;
3124 tree found;
3125 gfc_loopinfo loop;
3126 gfc_actual_arglist *actual;
3127 gfc_ss *arrayss;
3128 gfc_se arrayse;
3129 tree exit_label;
3131 if (se->ss)
3133 gfc_conv_intrinsic_funcall (se, expr);
3134 return;
3137 actual = expr->value.function.actual;
3138 type = gfc_typenode_for_spec (&expr->ts);
3139 /* Initialize the result. */
3140 resvar = gfc_create_var (type, "test");
3141 if (op == EQ_EXPR)
3142 tmp = convert (type, boolean_true_node);
3143 else
3144 tmp = convert (type, boolean_false_node);
3145 gfc_add_modify (&se->pre, resvar, tmp);
3147 /* Walk the arguments. */
3148 arrayss = gfc_walk_expr (actual->expr);
3149 gcc_assert (arrayss != gfc_ss_terminator);
3151 /* Initialize the scalarizer. */
3152 gfc_init_loopinfo (&loop);
3153 exit_label = gfc_build_label_decl (NULL_TREE);
3154 TREE_USED (exit_label) = 1;
3155 gfc_add_ss_to_loop (&loop, arrayss);
3157 /* Initialize the loop. */
3158 gfc_conv_ss_startstride (&loop);
3159 gfc_conv_loop_setup (&loop, &expr->where);
3161 gfc_mark_ss_chain_used (arrayss, 1);
3162 /* Generate the loop body. */
3163 gfc_start_scalarized_body (&loop, &body);
3165 /* If the condition matches then set the return value. */
3166 gfc_start_block (&block);
3167 if (op == EQ_EXPR)
3168 tmp = convert (type, boolean_false_node);
3169 else
3170 tmp = convert (type, boolean_true_node);
3171 gfc_add_modify (&block, resvar, tmp);
3173 /* And break out of the loop. */
3174 tmp = build1_v (GOTO_EXPR, exit_label);
3175 gfc_add_expr_to_block (&block, tmp);
3177 found = gfc_finish_block (&block);
3179 /* Check this element. */
3180 gfc_init_se (&arrayse, NULL);
3181 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3182 arrayse.ss = arrayss;
3183 gfc_conv_expr_val (&arrayse, actual->expr);
3185 gfc_add_block_to_block (&body, &arrayse.pre);
3186 tmp = fold_build2_loc (input_location, op, boolean_type_node, arrayse.expr,
3187 build_int_cst (TREE_TYPE (arrayse.expr), 0));
3188 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
3189 gfc_add_expr_to_block (&body, tmp);
3190 gfc_add_block_to_block (&body, &arrayse.post);
3192 gfc_trans_scalarizing_loops (&loop, &body);
3194 /* Add the exit label. */
3195 tmp = build1_v (LABEL_EXPR, exit_label);
3196 gfc_add_expr_to_block (&loop.pre, tmp);
3198 gfc_add_block_to_block (&se->pre, &loop.pre);
3199 gfc_add_block_to_block (&se->pre, &loop.post);
3200 gfc_cleanup_loop (&loop);
3202 se->expr = resvar;
3205 /* COUNT(A) = Number of true elements in A. */
3206 static void
3207 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
3209 tree resvar;
3210 tree type;
3211 stmtblock_t body;
3212 tree tmp;
3213 gfc_loopinfo loop;
3214 gfc_actual_arglist *actual;
3215 gfc_ss *arrayss;
3216 gfc_se arrayse;
3218 if (se->ss)
3220 gfc_conv_intrinsic_funcall (se, expr);
3221 return;
3224 actual = expr->value.function.actual;
3226 type = gfc_typenode_for_spec (&expr->ts);
3227 /* Initialize the result. */
3228 resvar = gfc_create_var (type, "count");
3229 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
3231 /* Walk the arguments. */
3232 arrayss = gfc_walk_expr (actual->expr);
3233 gcc_assert (arrayss != gfc_ss_terminator);
3235 /* Initialize the scalarizer. */
3236 gfc_init_loopinfo (&loop);
3237 gfc_add_ss_to_loop (&loop, arrayss);
3239 /* Initialize the loop. */
3240 gfc_conv_ss_startstride (&loop);
3241 gfc_conv_loop_setup (&loop, &expr->where);
3243 gfc_mark_ss_chain_used (arrayss, 1);
3244 /* Generate the loop body. */
3245 gfc_start_scalarized_body (&loop, &body);
3247 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
3248 resvar, build_int_cst (TREE_TYPE (resvar), 1));
3249 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
3251 gfc_init_se (&arrayse, NULL);
3252 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3253 arrayse.ss = arrayss;
3254 gfc_conv_expr_val (&arrayse, actual->expr);
3255 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
3256 build_empty_stmt (input_location));
3258 gfc_add_block_to_block (&body, &arrayse.pre);
3259 gfc_add_expr_to_block (&body, tmp);
3260 gfc_add_block_to_block (&body, &arrayse.post);
3262 gfc_trans_scalarizing_loops (&loop, &body);
3264 gfc_add_block_to_block (&se->pre, &loop.pre);
3265 gfc_add_block_to_block (&se->pre, &loop.post);
3266 gfc_cleanup_loop (&loop);
3268 se->expr = resvar;
3272 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
3273 struct and return the corresponding loopinfo. */
3275 static gfc_loopinfo *
3276 enter_nested_loop (gfc_se *se)
3278 se->ss = se->ss->nested_ss;
3279 gcc_assert (se->ss == se->ss->loop->ss);
3281 return se->ss->loop;
3285 /* Inline implementation of the sum and product intrinsics. */
3286 static void
3287 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
3288 bool norm2)
3290 tree resvar;
3291 tree scale = NULL_TREE;
3292 tree type;
3293 stmtblock_t body;
3294 stmtblock_t block;
3295 tree tmp;
3296 gfc_loopinfo loop, *ploop;
3297 gfc_actual_arglist *arg_array, *arg_mask;
3298 gfc_ss *arrayss = NULL;
3299 gfc_ss *maskss = NULL;
3300 gfc_se arrayse;
3301 gfc_se maskse;
3302 gfc_se *parent_se;
3303 gfc_expr *arrayexpr;
3304 gfc_expr *maskexpr;
3306 if (expr->rank > 0)
3308 gcc_assert (gfc_inline_intrinsic_function_p (expr));
3309 parent_se = se;
3311 else
3312 parent_se = NULL;
3314 type = gfc_typenode_for_spec (&expr->ts);
3315 /* Initialize the result. */
3316 resvar = gfc_create_var (type, "val");
3317 if (norm2)
3319 /* result = 0.0;
3320 scale = 1.0. */
3321 scale = gfc_create_var (type, "scale");
3322 gfc_add_modify (&se->pre, scale,
3323 gfc_build_const (type, integer_one_node));
3324 tmp = gfc_build_const (type, integer_zero_node);
3326 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
3327 tmp = gfc_build_const (type, integer_zero_node);
3328 else if (op == NE_EXPR)
3329 /* PARITY. */
3330 tmp = convert (type, boolean_false_node);
3331 else if (op == BIT_AND_EXPR)
3332 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
3333 type, integer_one_node));
3334 else
3335 tmp = gfc_build_const (type, integer_one_node);
3337 gfc_add_modify (&se->pre, resvar, tmp);
3339 arg_array = expr->value.function.actual;
3341 arrayexpr = arg_array->expr;
3343 if (op == NE_EXPR || norm2)
3344 /* PARITY and NORM2. */
3345 maskexpr = NULL;
3346 else
3348 arg_mask = arg_array->next->next;
3349 gcc_assert (arg_mask != NULL);
3350 maskexpr = arg_mask->expr;
3353 if (expr->rank == 0)
3355 /* Walk the arguments. */
3356 arrayss = gfc_walk_expr (arrayexpr);
3357 gcc_assert (arrayss != gfc_ss_terminator);
3359 if (maskexpr && maskexpr->rank > 0)
3361 maskss = gfc_walk_expr (maskexpr);
3362 gcc_assert (maskss != gfc_ss_terminator);
3364 else
3365 maskss = NULL;
3367 /* Initialize the scalarizer. */
3368 gfc_init_loopinfo (&loop);
3369 gfc_add_ss_to_loop (&loop, arrayss);
3370 if (maskexpr && maskexpr->rank > 0)
3371 gfc_add_ss_to_loop (&loop, maskss);
3373 /* Initialize the loop. */
3374 gfc_conv_ss_startstride (&loop);
3375 gfc_conv_loop_setup (&loop, &expr->where);
3377 gfc_mark_ss_chain_used (arrayss, 1);
3378 if (maskexpr && maskexpr->rank > 0)
3379 gfc_mark_ss_chain_used (maskss, 1);
3381 ploop = &loop;
3383 else
3384 /* All the work has been done in the parent loops. */
3385 ploop = enter_nested_loop (se);
3387 gcc_assert (ploop);
3389 /* Generate the loop body. */
3390 gfc_start_scalarized_body (ploop, &body);
3392 /* If we have a mask, only add this element if the mask is set. */
3393 if (maskexpr && maskexpr->rank > 0)
3395 gfc_init_se (&maskse, parent_se);
3396 gfc_copy_loopinfo_to_se (&maskse, ploop);
3397 if (expr->rank == 0)
3398 maskse.ss = maskss;
3399 gfc_conv_expr_val (&maskse, maskexpr);
3400 gfc_add_block_to_block (&body, &maskse.pre);
3402 gfc_start_block (&block);
3404 else
3405 gfc_init_block (&block);
3407 /* Do the actual summation/product. */
3408 gfc_init_se (&arrayse, parent_se);
3409 gfc_copy_loopinfo_to_se (&arrayse, ploop);
3410 if (expr->rank == 0)
3411 arrayse.ss = arrayss;
3412 gfc_conv_expr_val (&arrayse, arrayexpr);
3413 gfc_add_block_to_block (&block, &arrayse.pre);
3415 if (norm2)
3417 /* if (x (i) != 0.0)
3419 absX = abs(x(i))
3420 if (absX > scale)
3422 val = scale/absX;
3423 result = 1.0 + result * val * val;
3424 scale = absX;
3426 else
3428 val = absX/scale;
3429 result += val * val;
3431 } */
3432 tree res1, res2, cond, absX, val;
3433 stmtblock_t ifblock1, ifblock2, ifblock3;
3435 gfc_init_block (&ifblock1);
3437 absX = gfc_create_var (type, "absX");
3438 gfc_add_modify (&ifblock1, absX,
3439 fold_build1_loc (input_location, ABS_EXPR, type,
3440 arrayse.expr));
3441 val = gfc_create_var (type, "val");
3442 gfc_add_expr_to_block (&ifblock1, val);
3444 gfc_init_block (&ifblock2);
3445 gfc_add_modify (&ifblock2, val,
3446 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
3447 absX));
3448 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
3449 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
3450 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
3451 gfc_build_const (type, integer_one_node));
3452 gfc_add_modify (&ifblock2, resvar, res1);
3453 gfc_add_modify (&ifblock2, scale, absX);
3454 res1 = gfc_finish_block (&ifblock2);
3456 gfc_init_block (&ifblock3);
3457 gfc_add_modify (&ifblock3, val,
3458 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
3459 scale));
3460 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
3461 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
3462 gfc_add_modify (&ifblock3, resvar, res2);
3463 res2 = gfc_finish_block (&ifblock3);
3465 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
3466 absX, scale);
3467 tmp = build3_v (COND_EXPR, cond, res1, res2);
3468 gfc_add_expr_to_block (&ifblock1, tmp);
3469 tmp = gfc_finish_block (&ifblock1);
3471 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
3472 arrayse.expr,
3473 gfc_build_const (type, integer_zero_node));
3475 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3476 gfc_add_expr_to_block (&block, tmp);
3478 else
3480 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
3481 gfc_add_modify (&block, resvar, tmp);
3484 gfc_add_block_to_block (&block, &arrayse.post);
3486 if (maskexpr && maskexpr->rank > 0)
3488 /* We enclose the above in if (mask) {...} . */
3490 tmp = gfc_finish_block (&block);
3491 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3492 build_empty_stmt (input_location));
3494 else
3495 tmp = gfc_finish_block (&block);
3496 gfc_add_expr_to_block (&body, tmp);
3498 gfc_trans_scalarizing_loops (ploop, &body);
3500 /* For a scalar mask, enclose the loop in an if statement. */
3501 if (maskexpr && maskexpr->rank == 0)
3503 gfc_init_block (&block);
3504 gfc_add_block_to_block (&block, &ploop->pre);
3505 gfc_add_block_to_block (&block, &ploop->post);
3506 tmp = gfc_finish_block (&block);
3508 if (expr->rank > 0)
3510 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
3511 build_empty_stmt (input_location));
3512 gfc_advance_se_ss_chain (se);
3514 else
3516 gcc_assert (expr->rank == 0);
3517 gfc_init_se (&maskse, NULL);
3518 gfc_conv_expr_val (&maskse, maskexpr);
3519 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3520 build_empty_stmt (input_location));
3523 gfc_add_expr_to_block (&block, tmp);
3524 gfc_add_block_to_block (&se->pre, &block);
3525 gcc_assert (se->post.head == NULL);
3527 else
3529 gfc_add_block_to_block (&se->pre, &ploop->pre);
3530 gfc_add_block_to_block (&se->pre, &ploop->post);
3533 if (expr->rank == 0)
3534 gfc_cleanup_loop (ploop);
3536 if (norm2)
3538 /* result = scale * sqrt(result). */
3539 tree sqrt;
3540 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
3541 resvar = build_call_expr_loc (input_location,
3542 sqrt, 1, resvar);
3543 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
3546 se->expr = resvar;
3550 /* Inline implementation of the dot_product intrinsic. This function
3551 is based on gfc_conv_intrinsic_arith (the previous function). */
3552 static void
3553 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
3555 tree resvar;
3556 tree type;
3557 stmtblock_t body;
3558 stmtblock_t block;
3559 tree tmp;
3560 gfc_loopinfo loop;
3561 gfc_actual_arglist *actual;
3562 gfc_ss *arrayss1, *arrayss2;
3563 gfc_se arrayse1, arrayse2;
3564 gfc_expr *arrayexpr1, *arrayexpr2;
3566 type = gfc_typenode_for_spec (&expr->ts);
3568 /* Initialize the result. */
3569 resvar = gfc_create_var (type, "val");
3570 if (expr->ts.type == BT_LOGICAL)
3571 tmp = build_int_cst (type, 0);
3572 else
3573 tmp = gfc_build_const (type, integer_zero_node);
3575 gfc_add_modify (&se->pre, resvar, tmp);
3577 /* Walk argument #1. */
3578 actual = expr->value.function.actual;
3579 arrayexpr1 = actual->expr;
3580 arrayss1 = gfc_walk_expr (arrayexpr1);
3581 gcc_assert (arrayss1 != gfc_ss_terminator);
3583 /* Walk argument #2. */
3584 actual = actual->next;
3585 arrayexpr2 = actual->expr;
3586 arrayss2 = gfc_walk_expr (arrayexpr2);
3587 gcc_assert (arrayss2 != gfc_ss_terminator);
3589 /* Initialize the scalarizer. */
3590 gfc_init_loopinfo (&loop);
3591 gfc_add_ss_to_loop (&loop, arrayss1);
3592 gfc_add_ss_to_loop (&loop, arrayss2);
3594 /* Initialize the loop. */
3595 gfc_conv_ss_startstride (&loop);
3596 gfc_conv_loop_setup (&loop, &expr->where);
3598 gfc_mark_ss_chain_used (arrayss1, 1);
3599 gfc_mark_ss_chain_used (arrayss2, 1);
3601 /* Generate the loop body. */
3602 gfc_start_scalarized_body (&loop, &body);
3603 gfc_init_block (&block);
3605 /* Make the tree expression for [conjg(]array1[)]. */
3606 gfc_init_se (&arrayse1, NULL);
3607 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
3608 arrayse1.ss = arrayss1;
3609 gfc_conv_expr_val (&arrayse1, arrayexpr1);
3610 if (expr->ts.type == BT_COMPLEX)
3611 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
3612 arrayse1.expr);
3613 gfc_add_block_to_block (&block, &arrayse1.pre);
3615 /* Make the tree expression for array2. */
3616 gfc_init_se (&arrayse2, NULL);
3617 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
3618 arrayse2.ss = arrayss2;
3619 gfc_conv_expr_val (&arrayse2, arrayexpr2);
3620 gfc_add_block_to_block (&block, &arrayse2.pre);
3622 /* Do the actual product and sum. */
3623 if (expr->ts.type == BT_LOGICAL)
3625 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
3626 arrayse1.expr, arrayse2.expr);
3627 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
3629 else
3631 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
3632 arrayse2.expr);
3633 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
3635 gfc_add_modify (&block, resvar, tmp);
3637 /* Finish up the loop block and the loop. */
3638 tmp = gfc_finish_block (&block);
3639 gfc_add_expr_to_block (&body, tmp);
3641 gfc_trans_scalarizing_loops (&loop, &body);
3642 gfc_add_block_to_block (&se->pre, &loop.pre);
3643 gfc_add_block_to_block (&se->pre, &loop.post);
3644 gfc_cleanup_loop (&loop);
3646 se->expr = resvar;
3650 /* Emit code for minloc or maxloc intrinsic. There are many different cases
3651 we need to handle. For performance reasons we sometimes create two
3652 loops instead of one, where the second one is much simpler.
3653 Examples for minloc intrinsic:
3654 1) Result is an array, a call is generated
3655 2) Array mask is used and NaNs need to be supported:
3656 limit = Infinity;
3657 pos = 0;
3658 S = from;
3659 while (S <= to) {
3660 if (mask[S]) {
3661 if (pos == 0) pos = S + (1 - from);
3662 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3664 S++;
3666 goto lab2;
3667 lab1:;
3668 while (S <= to) {
3669 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3670 S++;
3672 lab2:;
3673 3) NaNs need to be supported, but it is known at compile time or cheaply
3674 at runtime whether array is nonempty or not:
3675 limit = Infinity;
3676 pos = 0;
3677 S = from;
3678 while (S <= to) {
3679 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3680 S++;
3682 if (from <= to) pos = 1;
3683 goto lab2;
3684 lab1:;
3685 while (S <= to) {
3686 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3687 S++;
3689 lab2:;
3690 4) NaNs aren't supported, array mask is used:
3691 limit = infinities_supported ? Infinity : huge (limit);
3692 pos = 0;
3693 S = from;
3694 while (S <= to) {
3695 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3696 S++;
3698 goto lab2;
3699 lab1:;
3700 while (S <= to) {
3701 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3702 S++;
3704 lab2:;
3705 5) Same without array mask:
3706 limit = infinities_supported ? Infinity : huge (limit);
3707 pos = (from <= to) ? 1 : 0;
3708 S = from;
3709 while (S <= to) {
3710 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3711 S++;
3713 For 3) and 5), if mask is scalar, this all goes into a conditional,
3714 setting pos = 0; in the else branch. */
3716 static void
3717 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
3719 stmtblock_t body;
3720 stmtblock_t block;
3721 stmtblock_t ifblock;
3722 stmtblock_t elseblock;
3723 tree limit;
3724 tree type;
3725 tree tmp;
3726 tree cond;
3727 tree elsetmp;
3728 tree ifbody;
3729 tree offset;
3730 tree nonempty;
3731 tree lab1, lab2;
3732 gfc_loopinfo loop;
3733 gfc_actual_arglist *actual;
3734 gfc_ss *arrayss;
3735 gfc_ss *maskss;
3736 gfc_se arrayse;
3737 gfc_se maskse;
3738 gfc_expr *arrayexpr;
3739 gfc_expr *maskexpr;
3740 tree pos;
3741 int n;
3743 if (se->ss)
3745 gfc_conv_intrinsic_funcall (se, expr);
3746 return;
3749 /* Initialize the result. */
3750 pos = gfc_create_var (gfc_array_index_type, "pos");
3751 offset = gfc_create_var (gfc_array_index_type, "offset");
3752 type = gfc_typenode_for_spec (&expr->ts);
3754 /* Walk the arguments. */
3755 actual = expr->value.function.actual;
3756 arrayexpr = actual->expr;
3757 arrayss = gfc_walk_expr (arrayexpr);
3758 gcc_assert (arrayss != gfc_ss_terminator);
3760 actual = actual->next->next;
3761 gcc_assert (actual);
3762 maskexpr = actual->expr;
3763 nonempty = NULL;
3764 if (maskexpr && maskexpr->rank != 0)
3766 maskss = gfc_walk_expr (maskexpr);
3767 gcc_assert (maskss != gfc_ss_terminator);
3769 else
3771 mpz_t asize;
3772 if (gfc_array_size (arrayexpr, &asize))
3774 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
3775 mpz_clear (asize);
3776 nonempty = fold_build2_loc (input_location, GT_EXPR,
3777 boolean_type_node, nonempty,
3778 gfc_index_zero_node);
3780 maskss = NULL;
3783 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
3784 switch (arrayexpr->ts.type)
3786 case BT_REAL:
3787 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
3788 break;
3790 case BT_INTEGER:
3791 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
3792 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
3793 arrayexpr->ts.kind);
3794 break;
3796 default:
3797 gcc_unreachable ();
3800 /* We start with the most negative possible value for MAXLOC, and the most
3801 positive possible value for MINLOC. The most negative possible value is
3802 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
3803 possible value is HUGE in both cases. */
3804 if (op == GT_EXPR)
3805 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
3806 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
3807 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
3808 build_int_cst (TREE_TYPE (tmp), 1));
3810 gfc_add_modify (&se->pre, limit, tmp);
3812 /* Initialize the scalarizer. */
3813 gfc_init_loopinfo (&loop);
3814 gfc_add_ss_to_loop (&loop, arrayss);
3815 if (maskss)
3816 gfc_add_ss_to_loop (&loop, maskss);
3818 /* Initialize the loop. */
3819 gfc_conv_ss_startstride (&loop);
3821 /* The code generated can have more than one loop in sequence (see the
3822 comment at the function header). This doesn't work well with the
3823 scalarizer, which changes arrays' offset when the scalarization loops
3824 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
3825 are currently inlined in the scalar case only (for which loop is of rank
3826 one). As there is no dependency to care about in that case, there is no
3827 temporary, so that we can use the scalarizer temporary code to handle
3828 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
3829 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
3830 to restore offset.
3831 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
3832 should eventually go away. We could either create two loops properly,
3833 or find another way to save/restore the array offsets between the two
3834 loops (without conflicting with temporary management), or use a single
3835 loop minmaxloc implementation. See PR 31067. */
3836 loop.temp_dim = loop.dimen;
3837 gfc_conv_loop_setup (&loop, &expr->where);
3839 gcc_assert (loop.dimen == 1);
3840 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
3841 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3842 loop.from[0], loop.to[0]);
3844 lab1 = NULL;
3845 lab2 = NULL;
3846 /* Initialize the position to zero, following Fortran 2003. We are free
3847 to do this because Fortran 95 allows the result of an entirely false
3848 mask to be processor dependent. If we know at compile time the array
3849 is non-empty and no MASK is used, we can initialize to 1 to simplify
3850 the inner loop. */
3851 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
3852 gfc_add_modify (&loop.pre, pos,
3853 fold_build3_loc (input_location, COND_EXPR,
3854 gfc_array_index_type,
3855 nonempty, gfc_index_one_node,
3856 gfc_index_zero_node));
3857 else
3859 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
3860 lab1 = gfc_build_label_decl (NULL_TREE);
3861 TREE_USED (lab1) = 1;
3862 lab2 = gfc_build_label_decl (NULL_TREE);
3863 TREE_USED (lab2) = 1;
3866 /* An offset must be added to the loop
3867 counter to obtain the required position. */
3868 gcc_assert (loop.from[0]);
3870 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3871 gfc_index_one_node, loop.from[0]);
3872 gfc_add_modify (&loop.pre, offset, tmp);
3874 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
3875 if (maskss)
3876 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
3877 /* Generate the loop body. */
3878 gfc_start_scalarized_body (&loop, &body);
3880 /* If we have a mask, only check this element if the mask is set. */
3881 if (maskss)
3883 gfc_init_se (&maskse, NULL);
3884 gfc_copy_loopinfo_to_se (&maskse, &loop);
3885 maskse.ss = maskss;
3886 gfc_conv_expr_val (&maskse, maskexpr);
3887 gfc_add_block_to_block (&body, &maskse.pre);
3889 gfc_start_block (&block);
3891 else
3892 gfc_init_block (&block);
3894 /* Compare with the current limit. */
3895 gfc_init_se (&arrayse, NULL);
3896 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3897 arrayse.ss = arrayss;
3898 gfc_conv_expr_val (&arrayse, arrayexpr);
3899 gfc_add_block_to_block (&block, &arrayse.pre);
3901 /* We do the following if this is a more extreme value. */
3902 gfc_start_block (&ifblock);
3904 /* Assign the value to the limit... */
3905 gfc_add_modify (&ifblock, limit, arrayse.expr);
3907 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
3909 stmtblock_t ifblock2;
3910 tree ifbody2;
3912 gfc_start_block (&ifblock2);
3913 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3914 loop.loopvar[0], offset);
3915 gfc_add_modify (&ifblock2, pos, tmp);
3916 ifbody2 = gfc_finish_block (&ifblock2);
3917 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, pos,
3918 gfc_index_zero_node);
3919 tmp = build3_v (COND_EXPR, cond, ifbody2,
3920 build_empty_stmt (input_location));
3921 gfc_add_expr_to_block (&block, tmp);
3924 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3925 loop.loopvar[0], offset);
3926 gfc_add_modify (&ifblock, pos, tmp);
3928 if (lab1)
3929 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
3931 ifbody = gfc_finish_block (&ifblock);
3933 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
3935 if (lab1)
3936 cond = fold_build2_loc (input_location,
3937 op == GT_EXPR ? GE_EXPR : LE_EXPR,
3938 boolean_type_node, arrayse.expr, limit);
3939 else
3940 cond = fold_build2_loc (input_location, op, boolean_type_node,
3941 arrayse.expr, limit);
3943 ifbody = build3_v (COND_EXPR, cond, ifbody,
3944 build_empty_stmt (input_location));
3946 gfc_add_expr_to_block (&block, ifbody);
3948 if (maskss)
3950 /* We enclose the above in if (mask) {...}. */
3951 tmp = gfc_finish_block (&block);
3953 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3954 build_empty_stmt (input_location));
3956 else
3957 tmp = gfc_finish_block (&block);
3958 gfc_add_expr_to_block (&body, tmp);
3960 if (lab1)
3962 gfc_trans_scalarized_loop_boundary (&loop, &body);
3964 if (HONOR_NANS (DECL_MODE (limit)))
3966 if (nonempty != NULL)
3968 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
3969 tmp = build3_v (COND_EXPR, nonempty, ifbody,
3970 build_empty_stmt (input_location));
3971 gfc_add_expr_to_block (&loop.code[0], tmp);
3975 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
3976 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
3978 /* If we have a mask, only check this element if the mask is set. */
3979 if (maskss)
3981 gfc_init_se (&maskse, NULL);
3982 gfc_copy_loopinfo_to_se (&maskse, &loop);
3983 maskse.ss = maskss;
3984 gfc_conv_expr_val (&maskse, maskexpr);
3985 gfc_add_block_to_block (&body, &maskse.pre);
3987 gfc_start_block (&block);
3989 else
3990 gfc_init_block (&block);
3992 /* Compare with the current limit. */
3993 gfc_init_se (&arrayse, NULL);
3994 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3995 arrayse.ss = arrayss;
3996 gfc_conv_expr_val (&arrayse, arrayexpr);
3997 gfc_add_block_to_block (&block, &arrayse.pre);
3999 /* We do the following if this is a more extreme value. */
4000 gfc_start_block (&ifblock);
4002 /* Assign the value to the limit... */
4003 gfc_add_modify (&ifblock, limit, arrayse.expr);
4005 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4006 loop.loopvar[0], offset);
4007 gfc_add_modify (&ifblock, pos, tmp);
4009 ifbody = gfc_finish_block (&ifblock);
4011 cond = fold_build2_loc (input_location, op, boolean_type_node,
4012 arrayse.expr, limit);
4014 tmp = build3_v (COND_EXPR, cond, ifbody,
4015 build_empty_stmt (input_location));
4016 gfc_add_expr_to_block (&block, tmp);
4018 if (maskss)
4020 /* We enclose the above in if (mask) {...}. */
4021 tmp = gfc_finish_block (&block);
4023 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4024 build_empty_stmt (input_location));
4026 else
4027 tmp = gfc_finish_block (&block);
4028 gfc_add_expr_to_block (&body, tmp);
4029 /* Avoid initializing loopvar[0] again, it should be left where
4030 it finished by the first loop. */
4031 loop.from[0] = loop.loopvar[0];
4034 gfc_trans_scalarizing_loops (&loop, &body);
4036 if (lab2)
4037 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
4039 /* For a scalar mask, enclose the loop in an if statement. */
4040 if (maskexpr && maskss == NULL)
4042 gfc_init_se (&maskse, NULL);
4043 gfc_conv_expr_val (&maskse, maskexpr);
4044 gfc_init_block (&block);
4045 gfc_add_block_to_block (&block, &loop.pre);
4046 gfc_add_block_to_block (&block, &loop.post);
4047 tmp = gfc_finish_block (&block);
4049 /* For the else part of the scalar mask, just initialize
4050 the pos variable the same way as above. */
4052 gfc_init_block (&elseblock);
4053 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
4054 elsetmp = gfc_finish_block (&elseblock);
4056 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
4057 gfc_add_expr_to_block (&block, tmp);
4058 gfc_add_block_to_block (&se->pre, &block);
4060 else
4062 gfc_add_block_to_block (&se->pre, &loop.pre);
4063 gfc_add_block_to_block (&se->pre, &loop.post);
4065 gfc_cleanup_loop (&loop);
4067 se->expr = convert (type, pos);
4070 /* Emit code for minval or maxval intrinsic. There are many different cases
4071 we need to handle. For performance reasons we sometimes create two
4072 loops instead of one, where the second one is much simpler.
4073 Examples for minval intrinsic:
4074 1) Result is an array, a call is generated
4075 2) Array mask is used and NaNs need to be supported, rank 1:
4076 limit = Infinity;
4077 nonempty = false;
4078 S = from;
4079 while (S <= to) {
4080 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
4081 S++;
4083 limit = nonempty ? NaN : huge (limit);
4084 lab:
4085 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
4086 3) NaNs need to be supported, but it is known at compile time or cheaply
4087 at runtime whether array is nonempty or not, rank 1:
4088 limit = Infinity;
4089 S = from;
4090 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
4091 limit = (from <= to) ? NaN : huge (limit);
4092 lab:
4093 while (S <= to) { limit = min (a[S], limit); S++; }
4094 4) Array mask is used and NaNs need to be supported, rank > 1:
4095 limit = Infinity;
4096 nonempty = false;
4097 fast = false;
4098 S1 = from1;
4099 while (S1 <= to1) {
4100 S2 = from2;
4101 while (S2 <= to2) {
4102 if (mask[S1][S2]) {
4103 if (fast) limit = min (a[S1][S2], limit);
4104 else {
4105 nonempty = true;
4106 if (a[S1][S2] <= limit) {
4107 limit = a[S1][S2];
4108 fast = true;
4112 S2++;
4114 S1++;
4116 if (!fast)
4117 limit = nonempty ? NaN : huge (limit);
4118 5) NaNs need to be supported, but it is known at compile time or cheaply
4119 at runtime whether array is nonempty or not, rank > 1:
4120 limit = Infinity;
4121 fast = false;
4122 S1 = from1;
4123 while (S1 <= to1) {
4124 S2 = from2;
4125 while (S2 <= to2) {
4126 if (fast) limit = min (a[S1][S2], limit);
4127 else {
4128 if (a[S1][S2] <= limit) {
4129 limit = a[S1][S2];
4130 fast = true;
4133 S2++;
4135 S1++;
4137 if (!fast)
4138 limit = (nonempty_array) ? NaN : huge (limit);
4139 6) NaNs aren't supported, but infinities are. Array mask is used:
4140 limit = Infinity;
4141 nonempty = false;
4142 S = from;
4143 while (S <= to) {
4144 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
4145 S++;
4147 limit = nonempty ? limit : huge (limit);
4148 7) Same without array mask:
4149 limit = Infinity;
4150 S = from;
4151 while (S <= to) { limit = min (a[S], limit); S++; }
4152 limit = (from <= to) ? limit : huge (limit);
4153 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
4154 limit = huge (limit);
4155 S = from;
4156 while (S <= to) { limit = min (a[S], limit); S++); }
4158 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
4159 with array mask instead).
4160 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
4161 setting limit = huge (limit); in the else branch. */
4163 static void
4164 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
4166 tree limit;
4167 tree type;
4168 tree tmp;
4169 tree ifbody;
4170 tree nonempty;
4171 tree nonempty_var;
4172 tree lab;
4173 tree fast;
4174 tree huge_cst = NULL, nan_cst = NULL;
4175 stmtblock_t body;
4176 stmtblock_t block, block2;
4177 gfc_loopinfo loop;
4178 gfc_actual_arglist *actual;
4179 gfc_ss *arrayss;
4180 gfc_ss *maskss;
4181 gfc_se arrayse;
4182 gfc_se maskse;
4183 gfc_expr *arrayexpr;
4184 gfc_expr *maskexpr;
4185 int n;
4187 if (se->ss)
4189 gfc_conv_intrinsic_funcall (se, expr);
4190 return;
4193 type = gfc_typenode_for_spec (&expr->ts);
4194 /* Initialize the result. */
4195 limit = gfc_create_var (type, "limit");
4196 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
4197 switch (expr->ts.type)
4199 case BT_REAL:
4200 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
4201 expr->ts.kind, 0);
4202 if (HONOR_INFINITIES (DECL_MODE (limit)))
4204 REAL_VALUE_TYPE real;
4205 real_inf (&real);
4206 tmp = build_real (type, real);
4208 else
4209 tmp = huge_cst;
4210 if (HONOR_NANS (DECL_MODE (limit)))
4211 nan_cst = gfc_build_nan (type, "");
4212 break;
4214 case BT_INTEGER:
4215 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
4216 break;
4218 default:
4219 gcc_unreachable ();
4222 /* We start with the most negative possible value for MAXVAL, and the most
4223 positive possible value for MINVAL. The most negative possible value is
4224 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
4225 possible value is HUGE in both cases. */
4226 if (op == GT_EXPR)
4228 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
4229 if (huge_cst)
4230 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
4231 TREE_TYPE (huge_cst), huge_cst);
4234 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
4235 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
4236 tmp, build_int_cst (type, 1));
4238 gfc_add_modify (&se->pre, limit, tmp);
4240 /* Walk the arguments. */
4241 actual = expr->value.function.actual;
4242 arrayexpr = actual->expr;
4243 arrayss = gfc_walk_expr (arrayexpr);
4244 gcc_assert (arrayss != gfc_ss_terminator);
4246 actual = actual->next->next;
4247 gcc_assert (actual);
4248 maskexpr = actual->expr;
4249 nonempty = NULL;
4250 if (maskexpr && maskexpr->rank != 0)
4252 maskss = gfc_walk_expr (maskexpr);
4253 gcc_assert (maskss != gfc_ss_terminator);
4255 else
4257 mpz_t asize;
4258 if (gfc_array_size (arrayexpr, &asize))
4260 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
4261 mpz_clear (asize);
4262 nonempty = fold_build2_loc (input_location, GT_EXPR,
4263 boolean_type_node, nonempty,
4264 gfc_index_zero_node);
4266 maskss = NULL;
4269 /* Initialize the scalarizer. */
4270 gfc_init_loopinfo (&loop);
4271 gfc_add_ss_to_loop (&loop, arrayss);
4272 if (maskss)
4273 gfc_add_ss_to_loop (&loop, maskss);
4275 /* Initialize the loop. */
4276 gfc_conv_ss_startstride (&loop);
4278 /* The code generated can have more than one loop in sequence (see the
4279 comment at the function header). This doesn't work well with the
4280 scalarizer, which changes arrays' offset when the scalarization loops
4281 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
4282 are currently inlined in the scalar case only. As there is no dependency
4283 to care about in that case, there is no temporary, so that we can use the
4284 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
4285 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
4286 gfc_trans_scalarized_loop_boundary even later to restore offset.
4287 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
4288 should eventually go away. We could either create two loops properly,
4289 or find another way to save/restore the array offsets between the two
4290 loops (without conflicting with temporary management), or use a single
4291 loop minmaxval implementation. See PR 31067. */
4292 loop.temp_dim = loop.dimen;
4293 gfc_conv_loop_setup (&loop, &expr->where);
4295 if (nonempty == NULL && maskss == NULL
4296 && loop.dimen == 1 && loop.from[0] && loop.to[0])
4297 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
4298 loop.from[0], loop.to[0]);
4299 nonempty_var = NULL;
4300 if (nonempty == NULL
4301 && (HONOR_INFINITIES (DECL_MODE (limit))
4302 || HONOR_NANS (DECL_MODE (limit))))
4304 nonempty_var = gfc_create_var (boolean_type_node, "nonempty");
4305 gfc_add_modify (&se->pre, nonempty_var, boolean_false_node);
4306 nonempty = nonempty_var;
4308 lab = NULL;
4309 fast = NULL;
4310 if (HONOR_NANS (DECL_MODE (limit)))
4312 if (loop.dimen == 1)
4314 lab = gfc_build_label_decl (NULL_TREE);
4315 TREE_USED (lab) = 1;
4317 else
4319 fast = gfc_create_var (boolean_type_node, "fast");
4320 gfc_add_modify (&se->pre, fast, boolean_false_node);
4324 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
4325 if (maskss)
4326 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
4327 /* Generate the loop body. */
4328 gfc_start_scalarized_body (&loop, &body);
4330 /* If we have a mask, only add this element if the mask is set. */
4331 if (maskss)
4333 gfc_init_se (&maskse, NULL);
4334 gfc_copy_loopinfo_to_se (&maskse, &loop);
4335 maskse.ss = maskss;
4336 gfc_conv_expr_val (&maskse, maskexpr);
4337 gfc_add_block_to_block (&body, &maskse.pre);
4339 gfc_start_block (&block);
4341 else
4342 gfc_init_block (&block);
4344 /* Compare with the current limit. */
4345 gfc_init_se (&arrayse, NULL);
4346 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4347 arrayse.ss = arrayss;
4348 gfc_conv_expr_val (&arrayse, arrayexpr);
4349 gfc_add_block_to_block (&block, &arrayse.pre);
4351 gfc_init_block (&block2);
4353 if (nonempty_var)
4354 gfc_add_modify (&block2, nonempty_var, boolean_true_node);
4356 if (HONOR_NANS (DECL_MODE (limit)))
4358 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
4359 boolean_type_node, arrayse.expr, limit);
4360 if (lab)
4361 ifbody = build1_v (GOTO_EXPR, lab);
4362 else
4364 stmtblock_t ifblock;
4366 gfc_init_block (&ifblock);
4367 gfc_add_modify (&ifblock, limit, arrayse.expr);
4368 gfc_add_modify (&ifblock, fast, boolean_true_node);
4369 ifbody = gfc_finish_block (&ifblock);
4371 tmp = build3_v (COND_EXPR, tmp, ifbody,
4372 build_empty_stmt (input_location));
4373 gfc_add_expr_to_block (&block2, tmp);
4375 else
4377 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
4378 signed zeros. */
4379 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
4381 tmp = fold_build2_loc (input_location, op, boolean_type_node,
4382 arrayse.expr, limit);
4383 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
4384 tmp = build3_v (COND_EXPR, tmp, ifbody,
4385 build_empty_stmt (input_location));
4386 gfc_add_expr_to_block (&block2, tmp);
4388 else
4390 tmp = fold_build2_loc (input_location,
4391 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
4392 type, arrayse.expr, limit);
4393 gfc_add_modify (&block2, limit, tmp);
4397 if (fast)
4399 tree elsebody = gfc_finish_block (&block2);
4401 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
4402 signed zeros. */
4403 if (HONOR_NANS (DECL_MODE (limit))
4404 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
4406 tmp = fold_build2_loc (input_location, op, boolean_type_node,
4407 arrayse.expr, limit);
4408 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
4409 ifbody = build3_v (COND_EXPR, tmp, ifbody,
4410 build_empty_stmt (input_location));
4412 else
4414 tmp = fold_build2_loc (input_location,
4415 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
4416 type, arrayse.expr, limit);
4417 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
4419 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
4420 gfc_add_expr_to_block (&block, tmp);
4422 else
4423 gfc_add_block_to_block (&block, &block2);
4425 gfc_add_block_to_block (&block, &arrayse.post);
4427 tmp = gfc_finish_block (&block);
4428 if (maskss)
4429 /* We enclose the above in if (mask) {...}. */
4430 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4431 build_empty_stmt (input_location));
4432 gfc_add_expr_to_block (&body, tmp);
4434 if (lab)
4436 gfc_trans_scalarized_loop_boundary (&loop, &body);
4438 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
4439 nan_cst, huge_cst);
4440 gfc_add_modify (&loop.code[0], limit, tmp);
4441 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
4443 /* If we have a mask, only add this element if the mask is set. */
4444 if (maskss)
4446 gfc_init_se (&maskse, NULL);
4447 gfc_copy_loopinfo_to_se (&maskse, &loop);
4448 maskse.ss = maskss;
4449 gfc_conv_expr_val (&maskse, maskexpr);
4450 gfc_add_block_to_block (&body, &maskse.pre);
4452 gfc_start_block (&block);
4454 else
4455 gfc_init_block (&block);
4457 /* Compare with the current limit. */
4458 gfc_init_se (&arrayse, NULL);
4459 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4460 arrayse.ss = arrayss;
4461 gfc_conv_expr_val (&arrayse, arrayexpr);
4462 gfc_add_block_to_block (&block, &arrayse.pre);
4464 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
4465 signed zeros. */
4466 if (HONOR_NANS (DECL_MODE (limit))
4467 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
4469 tmp = fold_build2_loc (input_location, op, boolean_type_node,
4470 arrayse.expr, limit);
4471 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
4472 tmp = build3_v (COND_EXPR, tmp, ifbody,
4473 build_empty_stmt (input_location));
4474 gfc_add_expr_to_block (&block, tmp);
4476 else
4478 tmp = fold_build2_loc (input_location,
4479 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
4480 type, arrayse.expr, limit);
4481 gfc_add_modify (&block, limit, tmp);
4484 gfc_add_block_to_block (&block, &arrayse.post);
4486 tmp = gfc_finish_block (&block);
4487 if (maskss)
4488 /* We enclose the above in if (mask) {...}. */
4489 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4490 build_empty_stmt (input_location));
4491 gfc_add_expr_to_block (&body, tmp);
4492 /* Avoid initializing loopvar[0] again, it should be left where
4493 it finished by the first loop. */
4494 loop.from[0] = loop.loopvar[0];
4496 gfc_trans_scalarizing_loops (&loop, &body);
4498 if (fast)
4500 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
4501 nan_cst, huge_cst);
4502 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
4503 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
4504 ifbody);
4505 gfc_add_expr_to_block (&loop.pre, tmp);
4507 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
4509 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
4510 huge_cst);
4511 gfc_add_modify (&loop.pre, limit, tmp);
4514 /* For a scalar mask, enclose the loop in an if statement. */
4515 if (maskexpr && maskss == NULL)
4517 tree else_stmt;
4519 gfc_init_se (&maskse, NULL);
4520 gfc_conv_expr_val (&maskse, maskexpr);
4521 gfc_init_block (&block);
4522 gfc_add_block_to_block (&block, &loop.pre);
4523 gfc_add_block_to_block (&block, &loop.post);
4524 tmp = gfc_finish_block (&block);
4526 if (HONOR_INFINITIES (DECL_MODE (limit)))
4527 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
4528 else
4529 else_stmt = build_empty_stmt (input_location);
4530 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
4531 gfc_add_expr_to_block (&block, tmp);
4532 gfc_add_block_to_block (&se->pre, &block);
4534 else
4536 gfc_add_block_to_block (&se->pre, &loop.pre);
4537 gfc_add_block_to_block (&se->pre, &loop.post);
4540 gfc_cleanup_loop (&loop);
4542 se->expr = limit;
4545 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
4546 static void
4547 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
4549 tree args[2];
4550 tree type;
4551 tree tmp;
4553 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4554 type = TREE_TYPE (args[0]);
4556 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
4557 build_int_cst (type, 1), args[1]);
4558 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
4559 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
4560 build_int_cst (type, 0));
4561 type = gfc_typenode_for_spec (&expr->ts);
4562 se->expr = convert (type, tmp);
4566 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
4567 static void
4568 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
4570 tree args[2];
4572 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4574 /* Convert both arguments to the unsigned type of the same size. */
4575 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
4576 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
4578 /* If they have unequal type size, convert to the larger one. */
4579 if (TYPE_PRECISION (TREE_TYPE (args[0]))
4580 > TYPE_PRECISION (TREE_TYPE (args[1])))
4581 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
4582 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
4583 > TYPE_PRECISION (TREE_TYPE (args[0])))
4584 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
4586 /* Now, we compare them. */
4587 se->expr = fold_build2_loc (input_location, op, boolean_type_node,
4588 args[0], args[1]);
4592 /* Generate code to perform the specified operation. */
4593 static void
4594 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
4596 tree args[2];
4598 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4599 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
4600 args[0], args[1]);
4603 /* Bitwise not. */
4604 static void
4605 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
4607 tree arg;
4609 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4610 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
4611 TREE_TYPE (arg), arg);
4614 /* Set or clear a single bit. */
4615 static void
4616 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
4618 tree args[2];
4619 tree type;
4620 tree tmp;
4621 enum tree_code op;
4623 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4624 type = TREE_TYPE (args[0]);
4626 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
4627 build_int_cst (type, 1), args[1]);
4628 if (set)
4629 op = BIT_IOR_EXPR;
4630 else
4632 op = BIT_AND_EXPR;
4633 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
4635 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
4638 /* Extract a sequence of bits.
4639 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
4640 static void
4641 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
4643 tree args[3];
4644 tree type;
4645 tree tmp;
4646 tree mask;
4648 gfc_conv_intrinsic_function_args (se, expr, args, 3);
4649 type = TREE_TYPE (args[0]);
4651 mask = build_int_cst (type, -1);
4652 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
4653 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
4655 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
4657 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
4660 static void
4661 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
4662 bool arithmetic)
4664 tree args[2], type, num_bits, cond;
4666 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4668 args[0] = gfc_evaluate_now (args[0], &se->pre);
4669 args[1] = gfc_evaluate_now (args[1], &se->pre);
4670 type = TREE_TYPE (args[0]);
4672 if (!arithmetic)
4673 args[0] = fold_convert (unsigned_type_for (type), args[0]);
4674 else
4675 gcc_assert (right_shift);
4677 se->expr = fold_build2_loc (input_location,
4678 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
4679 TREE_TYPE (args[0]), args[0], args[1]);
4681 if (!arithmetic)
4682 se->expr = fold_convert (type, se->expr);
4684 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4685 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4686 special case. */
4687 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
4688 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
4689 args[1], num_bits);
4691 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
4692 build_int_cst (type, 0), se->expr);
4695 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
4697 : ((shift >= 0) ? i << shift : i >> -shift)
4698 where all shifts are logical shifts. */
4699 static void
4700 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
4702 tree args[2];
4703 tree type;
4704 tree utype;
4705 tree tmp;
4706 tree width;
4707 tree num_bits;
4708 tree cond;
4709 tree lshift;
4710 tree rshift;
4712 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4714 args[0] = gfc_evaluate_now (args[0], &se->pre);
4715 args[1] = gfc_evaluate_now (args[1], &se->pre);
4717 type = TREE_TYPE (args[0]);
4718 utype = unsigned_type_for (type);
4720 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
4721 args[1]);
4723 /* Left shift if positive. */
4724 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
4726 /* Right shift if negative.
4727 We convert to an unsigned type because we want a logical shift.
4728 The standard doesn't define the case of shifting negative
4729 numbers, and we try to be compatible with other compilers, most
4730 notably g77, here. */
4731 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
4732 utype, convert (utype, args[0]), width));
4734 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, args[1],
4735 build_int_cst (TREE_TYPE (args[1]), 0));
4736 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
4738 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4739 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4740 special case. */
4741 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
4742 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, width,
4743 num_bits);
4744 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
4745 build_int_cst (type, 0), tmp);
4749 /* Circular shift. AKA rotate or barrel shift. */
4751 static void
4752 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
4754 tree *args;
4755 tree type;
4756 tree tmp;
4757 tree lrot;
4758 tree rrot;
4759 tree zero;
4760 unsigned int num_args;
4762 num_args = gfc_intrinsic_argument_list_length (expr);
4763 args = XALLOCAVEC (tree, num_args);
4765 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4767 if (num_args == 3)
4769 /* Use a library function for the 3 parameter version. */
4770 tree int4type = gfc_get_int_type (4);
4772 type = TREE_TYPE (args[0]);
4773 /* We convert the first argument to at least 4 bytes, and
4774 convert back afterwards. This removes the need for library
4775 functions for all argument sizes, and function will be
4776 aligned to at least 32 bits, so there's no loss. */
4777 if (expr->ts.kind < 4)
4778 args[0] = convert (int4type, args[0]);
4780 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
4781 need loads of library functions. They cannot have values >
4782 BIT_SIZE (I) so the conversion is safe. */
4783 args[1] = convert (int4type, args[1]);
4784 args[2] = convert (int4type, args[2]);
4786 switch (expr->ts.kind)
4788 case 1:
4789 case 2:
4790 case 4:
4791 tmp = gfor_fndecl_math_ishftc4;
4792 break;
4793 case 8:
4794 tmp = gfor_fndecl_math_ishftc8;
4795 break;
4796 case 16:
4797 tmp = gfor_fndecl_math_ishftc16;
4798 break;
4799 default:
4800 gcc_unreachable ();
4802 se->expr = build_call_expr_loc (input_location,
4803 tmp, 3, args[0], args[1], args[2]);
4804 /* Convert the result back to the original type, if we extended
4805 the first argument's width above. */
4806 if (expr->ts.kind < 4)
4807 se->expr = convert (type, se->expr);
4809 return;
4811 type = TREE_TYPE (args[0]);
4813 /* Evaluate arguments only once. */
4814 args[0] = gfc_evaluate_now (args[0], &se->pre);
4815 args[1] = gfc_evaluate_now (args[1], &se->pre);
4817 /* Rotate left if positive. */
4818 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
4820 /* Rotate right if negative. */
4821 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
4822 args[1]);
4823 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
4825 zero = build_int_cst (TREE_TYPE (args[1]), 0);
4826 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, args[1],
4827 zero);
4828 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
4830 /* Do nothing if shift == 0. */
4831 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, args[1],
4832 zero);
4833 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
4834 rrot);
4838 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
4839 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
4841 The conditional expression is necessary because the result of LEADZ(0)
4842 is defined, but the result of __builtin_clz(0) is undefined for most
4843 targets.
4845 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
4846 difference in bit size between the argument of LEADZ and the C int. */
4848 static void
4849 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
4851 tree arg;
4852 tree arg_type;
4853 tree cond;
4854 tree result_type;
4855 tree leadz;
4856 tree bit_size;
4857 tree tmp;
4858 tree func;
4859 int s, argsize;
4861 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4862 argsize = TYPE_PRECISION (TREE_TYPE (arg));
4864 /* Which variant of __builtin_clz* should we call? */
4865 if (argsize <= INT_TYPE_SIZE)
4867 arg_type = unsigned_type_node;
4868 func = builtin_decl_explicit (BUILT_IN_CLZ);
4870 else if (argsize <= LONG_TYPE_SIZE)
4872 arg_type = long_unsigned_type_node;
4873 func = builtin_decl_explicit (BUILT_IN_CLZL);
4875 else if (argsize <= LONG_LONG_TYPE_SIZE)
4877 arg_type = long_long_unsigned_type_node;
4878 func = builtin_decl_explicit (BUILT_IN_CLZLL);
4880 else
4882 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4883 arg_type = gfc_build_uint_type (argsize);
4884 func = NULL_TREE;
4887 /* Convert the actual argument twice: first, to the unsigned type of the
4888 same size; then, to the proper argument type for the built-in
4889 function. But the return type is of the default INTEGER kind. */
4890 arg = fold_convert (gfc_build_uint_type (argsize), arg);
4891 arg = fold_convert (arg_type, arg);
4892 arg = gfc_evaluate_now (arg, &se->pre);
4893 result_type = gfc_get_int_type (gfc_default_integer_kind);
4895 /* Compute LEADZ for the case i .ne. 0. */
4896 if (func)
4898 s = TYPE_PRECISION (arg_type) - argsize;
4899 tmp = fold_convert (result_type,
4900 build_call_expr_loc (input_location, func,
4901 1, arg));
4902 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
4903 tmp, build_int_cst (result_type, s));
4905 else
4907 /* We end up here if the argument type is larger than 'long long'.
4908 We generate this code:
4910 if (x & (ULL_MAX << ULL_SIZE) != 0)
4911 return clzll ((unsigned long long) (x >> ULLSIZE));
4912 else
4913 return ULL_SIZE + clzll ((unsigned long long) x);
4914 where ULL_MAX is the largest value that a ULL_MAX can hold
4915 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
4916 is the bit-size of the long long type (64 in this example). */
4917 tree ullsize, ullmax, tmp1, tmp2, btmp;
4919 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
4920 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
4921 long_long_unsigned_type_node,
4922 build_int_cst (long_long_unsigned_type_node,
4923 0));
4925 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
4926 fold_convert (arg_type, ullmax), ullsize);
4927 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
4928 arg, cond);
4929 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
4930 cond, build_int_cst (arg_type, 0));
4932 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
4933 arg, ullsize);
4934 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
4935 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4936 tmp1 = fold_convert (result_type,
4937 build_call_expr_loc (input_location, btmp, 1, tmp1));
4939 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
4940 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4941 tmp2 = fold_convert (result_type,
4942 build_call_expr_loc (input_location, btmp, 1, tmp2));
4943 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4944 tmp2, ullsize);
4946 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
4947 cond, tmp1, tmp2);
4950 /* Build BIT_SIZE. */
4951 bit_size = build_int_cst (result_type, argsize);
4953 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4954 arg, build_int_cst (arg_type, 0));
4955 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
4956 bit_size, leadz);
4960 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
4962 The conditional expression is necessary because the result of TRAILZ(0)
4963 is defined, but the result of __builtin_ctz(0) is undefined for most
4964 targets. */
4966 static void
4967 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
4969 tree arg;
4970 tree arg_type;
4971 tree cond;
4972 tree result_type;
4973 tree trailz;
4974 tree bit_size;
4975 tree func;
4976 int argsize;
4978 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4979 argsize = TYPE_PRECISION (TREE_TYPE (arg));
4981 /* Which variant of __builtin_ctz* should we call? */
4982 if (argsize <= INT_TYPE_SIZE)
4984 arg_type = unsigned_type_node;
4985 func = builtin_decl_explicit (BUILT_IN_CTZ);
4987 else if (argsize <= LONG_TYPE_SIZE)
4989 arg_type = long_unsigned_type_node;
4990 func = builtin_decl_explicit (BUILT_IN_CTZL);
4992 else if (argsize <= LONG_LONG_TYPE_SIZE)
4994 arg_type = long_long_unsigned_type_node;
4995 func = builtin_decl_explicit (BUILT_IN_CTZLL);
4997 else
4999 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
5000 arg_type = gfc_build_uint_type (argsize);
5001 func = NULL_TREE;
5004 /* Convert the actual argument twice: first, to the unsigned type of the
5005 same size; then, to the proper argument type for the built-in
5006 function. But the return type is of the default INTEGER kind. */
5007 arg = fold_convert (gfc_build_uint_type (argsize), arg);
5008 arg = fold_convert (arg_type, arg);
5009 arg = gfc_evaluate_now (arg, &se->pre);
5010 result_type = gfc_get_int_type (gfc_default_integer_kind);
5012 /* Compute TRAILZ for the case i .ne. 0. */
5013 if (func)
5014 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
5015 func, 1, arg));
5016 else
5018 /* We end up here if the argument type is larger than 'long long'.
5019 We generate this code:
5021 if ((x & ULL_MAX) == 0)
5022 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
5023 else
5024 return ctzll ((unsigned long long) x);
5026 where ULL_MAX is the largest value that a ULL_MAX can hold
5027 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
5028 is the bit-size of the long long type (64 in this example). */
5029 tree ullsize, ullmax, tmp1, tmp2, btmp;
5031 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
5032 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
5033 long_long_unsigned_type_node,
5034 build_int_cst (long_long_unsigned_type_node, 0));
5036 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
5037 fold_convert (arg_type, ullmax));
5038 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, cond,
5039 build_int_cst (arg_type, 0));
5041 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
5042 arg, ullsize);
5043 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
5044 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
5045 tmp1 = fold_convert (result_type,
5046 build_call_expr_loc (input_location, btmp, 1, tmp1));
5047 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
5048 tmp1, ullsize);
5050 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
5051 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
5052 tmp2 = fold_convert (result_type,
5053 build_call_expr_loc (input_location, btmp, 1, tmp2));
5055 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
5056 cond, tmp1, tmp2);
5059 /* Build BIT_SIZE. */
5060 bit_size = build_int_cst (result_type, argsize);
5062 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5063 arg, build_int_cst (arg_type, 0));
5064 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
5065 bit_size, trailz);
5068 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
5069 for types larger than "long long", we call the long long built-in for
5070 the lower and higher bits and combine the result. */
5072 static void
5073 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
5075 tree arg;
5076 tree arg_type;
5077 tree result_type;
5078 tree func;
5079 int argsize;
5081 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5082 argsize = TYPE_PRECISION (TREE_TYPE (arg));
5083 result_type = gfc_get_int_type (gfc_default_integer_kind);
5085 /* Which variant of the builtin should we call? */
5086 if (argsize <= INT_TYPE_SIZE)
5088 arg_type = unsigned_type_node;
5089 func = builtin_decl_explicit (parity
5090 ? BUILT_IN_PARITY
5091 : BUILT_IN_POPCOUNT);
5093 else if (argsize <= LONG_TYPE_SIZE)
5095 arg_type = long_unsigned_type_node;
5096 func = builtin_decl_explicit (parity
5097 ? BUILT_IN_PARITYL
5098 : BUILT_IN_POPCOUNTL);
5100 else if (argsize <= LONG_LONG_TYPE_SIZE)
5102 arg_type = long_long_unsigned_type_node;
5103 func = builtin_decl_explicit (parity
5104 ? BUILT_IN_PARITYLL
5105 : BUILT_IN_POPCOUNTLL);
5107 else
5109 /* Our argument type is larger than 'long long', which mean none
5110 of the POPCOUNT builtins covers it. We thus call the 'long long'
5111 variant multiple times, and add the results. */
5112 tree utype, arg2, call1, call2;
5114 /* For now, we only cover the case where argsize is twice as large
5115 as 'long long'. */
5116 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
5118 func = builtin_decl_explicit (parity
5119 ? BUILT_IN_PARITYLL
5120 : BUILT_IN_POPCOUNTLL);
5122 /* Convert it to an integer, and store into a variable. */
5123 utype = gfc_build_uint_type (argsize);
5124 arg = fold_convert (utype, arg);
5125 arg = gfc_evaluate_now (arg, &se->pre);
5127 /* Call the builtin twice. */
5128 call1 = build_call_expr_loc (input_location, func, 1,
5129 fold_convert (long_long_unsigned_type_node,
5130 arg));
5132 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
5133 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
5134 call2 = build_call_expr_loc (input_location, func, 1,
5135 fold_convert (long_long_unsigned_type_node,
5136 arg2));
5138 /* Combine the results. */
5139 if (parity)
5140 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
5141 call1, call2);
5142 else
5143 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
5144 call1, call2);
5146 return;
5149 /* Convert the actual argument twice: first, to the unsigned type of the
5150 same size; then, to the proper argument type for the built-in
5151 function. */
5152 arg = fold_convert (gfc_build_uint_type (argsize), arg);
5153 arg = fold_convert (arg_type, arg);
5155 se->expr = fold_convert (result_type,
5156 build_call_expr_loc (input_location, func, 1, arg));
5160 /* Process an intrinsic with unspecified argument-types that has an optional
5161 argument (which could be of type character), e.g. EOSHIFT. For those, we
5162 need to append the string length of the optional argument if it is not
5163 present and the type is really character.
5164 primary specifies the position (starting at 1) of the non-optional argument
5165 specifying the type and optional gives the position of the optional
5166 argument in the arglist. */
5168 static void
5169 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
5170 unsigned primary, unsigned optional)
5172 gfc_actual_arglist* prim_arg;
5173 gfc_actual_arglist* opt_arg;
5174 unsigned cur_pos;
5175 gfc_actual_arglist* arg;
5176 gfc_symbol* sym;
5177 vec<tree, va_gc> *append_args;
5179 /* Find the two arguments given as position. */
5180 cur_pos = 0;
5181 prim_arg = NULL;
5182 opt_arg = NULL;
5183 for (arg = expr->value.function.actual; arg; arg = arg->next)
5185 ++cur_pos;
5187 if (cur_pos == primary)
5188 prim_arg = arg;
5189 if (cur_pos == optional)
5190 opt_arg = arg;
5192 if (cur_pos >= primary && cur_pos >= optional)
5193 break;
5195 gcc_assert (prim_arg);
5196 gcc_assert (prim_arg->expr);
5197 gcc_assert (opt_arg);
5199 /* If we do have type CHARACTER and the optional argument is really absent,
5200 append a dummy 0 as string length. */
5201 append_args = NULL;
5202 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
5204 tree dummy;
5206 dummy = build_int_cst (gfc_charlen_type_node, 0);
5207 vec_alloc (append_args, 1);
5208 append_args->quick_push (dummy);
5211 /* Build the call itself. */
5212 gcc_assert (!se->ignore_optional);
5213 sym = gfc_get_symbol_for_expr (expr, false);
5214 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
5215 append_args);
5216 gfc_free_symbol (sym);
5220 /* The length of a character string. */
5221 static void
5222 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
5224 tree len;
5225 tree type;
5226 tree decl;
5227 gfc_symbol *sym;
5228 gfc_se argse;
5229 gfc_expr *arg;
5231 gcc_assert (!se->ss);
5233 arg = expr->value.function.actual->expr;
5235 type = gfc_typenode_for_spec (&expr->ts);
5236 switch (arg->expr_type)
5238 case EXPR_CONSTANT:
5239 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
5240 break;
5242 case EXPR_ARRAY:
5243 /* Obtain the string length from the function used by
5244 trans-array.c(gfc_trans_array_constructor). */
5245 len = NULL_TREE;
5246 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
5247 break;
5249 case EXPR_VARIABLE:
5250 if (arg->ref == NULL
5251 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
5253 /* This doesn't catch all cases.
5254 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
5255 and the surrounding thread. */
5256 sym = arg->symtree->n.sym;
5257 decl = gfc_get_symbol_decl (sym);
5258 if (decl == current_function_decl && sym->attr.function
5259 && (sym->result == sym))
5260 decl = gfc_get_fake_result_decl (sym, 0);
5262 len = sym->ts.u.cl->backend_decl;
5263 gcc_assert (len);
5264 break;
5267 /* Otherwise fall through. */
5269 default:
5270 /* Anybody stupid enough to do this deserves inefficient code. */
5271 gfc_init_se (&argse, se);
5272 if (arg->rank == 0)
5273 gfc_conv_expr (&argse, arg);
5274 else
5275 gfc_conv_expr_descriptor (&argse, arg);
5276 gfc_add_block_to_block (&se->pre, &argse.pre);
5277 gfc_add_block_to_block (&se->post, &argse.post);
5278 len = argse.string_length;
5279 break;
5281 se->expr = convert (type, len);
5284 /* The length of a character string not including trailing blanks. */
5285 static void
5286 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
5288 int kind = expr->value.function.actual->expr->ts.kind;
5289 tree args[2], type, fndecl;
5291 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5292 type = gfc_typenode_for_spec (&expr->ts);
5294 if (kind == 1)
5295 fndecl = gfor_fndecl_string_len_trim;
5296 else if (kind == 4)
5297 fndecl = gfor_fndecl_string_len_trim_char4;
5298 else
5299 gcc_unreachable ();
5301 se->expr = build_call_expr_loc (input_location,
5302 fndecl, 2, args[0], args[1]);
5303 se->expr = convert (type, se->expr);
5307 /* Returns the starting position of a substring within a string. */
5309 static void
5310 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
5311 tree function)
5313 tree logical4_type_node = gfc_get_logical_type (4);
5314 tree type;
5315 tree fndecl;
5316 tree *args;
5317 unsigned int num_args;
5319 args = XALLOCAVEC (tree, 5);
5321 /* Get number of arguments; characters count double due to the
5322 string length argument. Kind= is not passed to the library
5323 and thus ignored. */
5324 if (expr->value.function.actual->next->next->expr == NULL)
5325 num_args = 4;
5326 else
5327 num_args = 5;
5329 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
5330 type = gfc_typenode_for_spec (&expr->ts);
5332 if (num_args == 4)
5333 args[4] = build_int_cst (logical4_type_node, 0);
5334 else
5335 args[4] = convert (logical4_type_node, args[4]);
5337 fndecl = build_addr (function, current_function_decl);
5338 se->expr = build_call_array_loc (input_location,
5339 TREE_TYPE (TREE_TYPE (function)), fndecl,
5340 5, args);
5341 se->expr = convert (type, se->expr);
5345 /* The ascii value for a single character. */
5346 static void
5347 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
5349 tree args[3], type, pchartype;
5350 int nargs;
5352 nargs = gfc_intrinsic_argument_list_length (expr);
5353 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
5354 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
5355 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
5356 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
5357 type = gfc_typenode_for_spec (&expr->ts);
5359 se->expr = build_fold_indirect_ref_loc (input_location,
5360 args[1]);
5361 se->expr = convert (type, se->expr);
5365 /* Intrinsic ISNAN calls __builtin_isnan. */
5367 static void
5368 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
5370 tree arg;
5372 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5373 se->expr = build_call_expr_loc (input_location,
5374 builtin_decl_explicit (BUILT_IN_ISNAN),
5375 1, arg);
5376 STRIP_TYPE_NOPS (se->expr);
5377 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
5381 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
5382 their argument against a constant integer value. */
5384 static void
5385 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
5387 tree arg;
5389 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5390 se->expr = fold_build2_loc (input_location, EQ_EXPR,
5391 gfc_typenode_for_spec (&expr->ts),
5392 arg, build_int_cst (TREE_TYPE (arg), value));
5397 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
5399 static void
5400 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
5402 tree tsource;
5403 tree fsource;
5404 tree mask;
5405 tree type;
5406 tree len, len2;
5407 tree *args;
5408 unsigned int num_args;
5410 num_args = gfc_intrinsic_argument_list_length (expr);
5411 args = XALLOCAVEC (tree, num_args);
5413 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
5414 if (expr->ts.type != BT_CHARACTER)
5416 tsource = args[0];
5417 fsource = args[1];
5418 mask = args[2];
5420 else
5422 /* We do the same as in the non-character case, but the argument
5423 list is different because of the string length arguments. We
5424 also have to set the string length for the result. */
5425 len = args[0];
5426 tsource = args[1];
5427 len2 = args[2];
5428 fsource = args[3];
5429 mask = args[4];
5431 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
5432 &se->pre);
5433 se->string_length = len;
5435 type = TREE_TYPE (tsource);
5436 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
5437 fold_convert (type, fsource));
5441 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
5443 static void
5444 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
5446 tree args[3], mask, type;
5448 gfc_conv_intrinsic_function_args (se, expr, args, 3);
5449 mask = gfc_evaluate_now (args[2], &se->pre);
5451 type = TREE_TYPE (args[0]);
5452 gcc_assert (TREE_TYPE (args[1]) == type);
5453 gcc_assert (TREE_TYPE (mask) == type);
5455 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
5456 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
5457 fold_build1_loc (input_location, BIT_NOT_EXPR,
5458 type, mask));
5459 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
5460 args[0], args[1]);
5464 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
5465 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
5467 static void
5468 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
5470 tree arg, allones, type, utype, res, cond, bitsize;
5471 int i;
5473 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5474 arg = gfc_evaluate_now (arg, &se->pre);
5476 type = gfc_get_int_type (expr->ts.kind);
5477 utype = unsigned_type_for (type);
5479 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
5480 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
5482 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
5483 build_int_cst (utype, 0));
5485 if (left)
5487 /* Left-justified mask. */
5488 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
5489 bitsize, arg);
5490 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
5491 fold_convert (utype, res));
5493 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
5494 smaller than type width. */
5495 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
5496 build_int_cst (TREE_TYPE (arg), 0));
5497 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
5498 build_int_cst (utype, 0), res);
5500 else
5502 /* Right-justified mask. */
5503 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
5504 fold_convert (utype, arg));
5505 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
5507 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
5508 strictly smaller than type width. */
5509 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5510 arg, bitsize);
5511 res = fold_build3_loc (input_location, COND_EXPR, utype,
5512 cond, allones, res);
5515 se->expr = fold_convert (type, res);
5519 /* FRACTION (s) is translated into:
5520 isfinite (s) ? frexp (s, &dummy_int) : NaN */
5521 static void
5522 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
5524 tree arg, type, tmp, res, frexp, cond;
5526 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
5528 type = gfc_typenode_for_spec (&expr->ts);
5529 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5530 arg = gfc_evaluate_now (arg, &se->pre);
5532 cond = build_call_expr_loc (input_location,
5533 builtin_decl_explicit (BUILT_IN_ISFINITE),
5534 1, arg);
5536 tmp = gfc_create_var (integer_type_node, NULL);
5537 res = build_call_expr_loc (input_location, frexp, 2,
5538 fold_convert (type, arg),
5539 gfc_build_addr_expr (NULL_TREE, tmp));
5540 res = fold_convert (type, res);
5542 se->expr = fold_build3_loc (input_location, COND_EXPR, type,
5543 cond, res, gfc_build_nan (type, ""));
5547 /* NEAREST (s, dir) is translated into
5548 tmp = copysign (HUGE_VAL, dir);
5549 return nextafter (s, tmp);
5551 static void
5552 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
5554 tree args[2], type, tmp, nextafter, copysign, huge_val;
5556 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
5557 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
5559 type = gfc_typenode_for_spec (&expr->ts);
5560 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5562 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
5563 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
5564 fold_convert (type, args[1]));
5565 se->expr = build_call_expr_loc (input_location, nextafter, 2,
5566 fold_convert (type, args[0]), tmp);
5567 se->expr = fold_convert (type, se->expr);
5571 /* SPACING (s) is translated into
5572 int e;
5573 if (!isfinite (s))
5574 res = NaN;
5575 else if (s == 0)
5576 res = tiny;
5577 else
5579 frexp (s, &e);
5580 e = e - prec;
5581 e = MAX_EXPR (e, emin);
5582 res = scalbn (1., e);
5584 return res;
5586 where prec is the precision of s, gfc_real_kinds[k].digits,
5587 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
5588 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
5590 static void
5591 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
5593 tree arg, type, prec, emin, tiny, res, e;
5594 tree cond, nan, tmp, frexp, scalbn;
5595 int k;
5596 stmtblock_t block;
5598 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
5599 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
5600 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
5601 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
5603 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
5604 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5606 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5607 arg = gfc_evaluate_now (arg, &se->pre);
5609 type = gfc_typenode_for_spec (&expr->ts);
5610 e = gfc_create_var (integer_type_node, NULL);
5611 res = gfc_create_var (type, NULL);
5614 /* Build the block for s /= 0. */
5615 gfc_start_block (&block);
5616 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
5617 gfc_build_addr_expr (NULL_TREE, e));
5618 gfc_add_expr_to_block (&block, tmp);
5620 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
5621 prec);
5622 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
5623 integer_type_node, tmp, emin));
5625 tmp = build_call_expr_loc (input_location, scalbn, 2,
5626 build_real_from_int_cst (type, integer_one_node), e);
5627 gfc_add_modify (&block, res, tmp);
5629 /* Finish by building the IF statement for value zero. */
5630 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
5631 build_real_from_int_cst (type, integer_zero_node));
5632 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
5633 gfc_finish_block (&block));
5635 /* And deal with infinities and NaNs. */
5636 cond = build_call_expr_loc (input_location,
5637 builtin_decl_explicit (BUILT_IN_ISFINITE),
5638 1, arg);
5639 nan = gfc_build_nan (type, "");
5640 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
5642 gfc_add_expr_to_block (&se->pre, tmp);
5643 se->expr = res;
5647 /* RRSPACING (s) is translated into
5648 int e;
5649 real x;
5650 x = fabs (s);
5651 if (isfinite (x))
5653 if (x != 0)
5655 frexp (s, &e);
5656 x = scalbn (x, precision - e);
5659 else
5660 x = NaN;
5661 return x;
5663 where precision is gfc_real_kinds[k].digits. */
5665 static void
5666 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
5668 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
5669 int prec, k;
5670 stmtblock_t block;
5672 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
5673 prec = gfc_real_kinds[k].digits;
5675 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
5676 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5677 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
5679 type = gfc_typenode_for_spec (&expr->ts);
5680 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5681 arg = gfc_evaluate_now (arg, &se->pre);
5683 e = gfc_create_var (integer_type_node, NULL);
5684 x = gfc_create_var (type, NULL);
5685 gfc_add_modify (&se->pre, x,
5686 build_call_expr_loc (input_location, fabs, 1, arg));
5689 gfc_start_block (&block);
5690 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
5691 gfc_build_addr_expr (NULL_TREE, e));
5692 gfc_add_expr_to_block (&block, tmp);
5694 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
5695 build_int_cst (integer_type_node, prec), e);
5696 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
5697 gfc_add_modify (&block, x, tmp);
5698 stmt = gfc_finish_block (&block);
5700 /* if (x != 0) */
5701 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, x,
5702 build_real_from_int_cst (type, integer_zero_node));
5703 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
5705 /* And deal with infinities and NaNs. */
5706 cond = build_call_expr_loc (input_location,
5707 builtin_decl_explicit (BUILT_IN_ISFINITE),
5708 1, x);
5709 nan = gfc_build_nan (type, "");
5710 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
5712 gfc_add_expr_to_block (&se->pre, tmp);
5713 se->expr = fold_convert (type, x);
5717 /* SCALE (s, i) is translated into scalbn (s, i). */
5718 static void
5719 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
5721 tree args[2], type, scalbn;
5723 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5725 type = gfc_typenode_for_spec (&expr->ts);
5726 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5727 se->expr = build_call_expr_loc (input_location, scalbn, 2,
5728 fold_convert (type, args[0]),
5729 fold_convert (integer_type_node, args[1]));
5730 se->expr = fold_convert (type, se->expr);
5734 /* SET_EXPONENT (s, i) is translated into
5735 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
5736 static void
5737 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
5739 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
5741 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
5742 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5744 type = gfc_typenode_for_spec (&expr->ts);
5745 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5746 args[0] = gfc_evaluate_now (args[0], &se->pre);
5748 tmp = gfc_create_var (integer_type_node, NULL);
5749 tmp = build_call_expr_loc (input_location, frexp, 2,
5750 fold_convert (type, args[0]),
5751 gfc_build_addr_expr (NULL_TREE, tmp));
5752 res = build_call_expr_loc (input_location, scalbn, 2, tmp,
5753 fold_convert (integer_type_node, args[1]));
5754 res = fold_convert (type, res);
5756 /* Call to isfinite */
5757 cond = build_call_expr_loc (input_location,
5758 builtin_decl_explicit (BUILT_IN_ISFINITE),
5759 1, args[0]);
5760 nan = gfc_build_nan (type, "");
5762 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5763 res, nan);
5767 static void
5768 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
5770 gfc_actual_arglist *actual;
5771 tree arg1;
5772 tree type;
5773 tree fncall0;
5774 tree fncall1;
5775 gfc_se argse;
5777 gfc_init_se (&argse, NULL);
5778 actual = expr->value.function.actual;
5780 if (actual->expr->ts.type == BT_CLASS)
5781 gfc_add_class_array_ref (actual->expr);
5783 argse.want_pointer = 1;
5784 argse.data_not_needed = 1;
5785 gfc_conv_expr_descriptor (&argse, actual->expr);
5786 gfc_add_block_to_block (&se->pre, &argse.pre);
5787 gfc_add_block_to_block (&se->post, &argse.post);
5788 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
5790 /* Build the call to size0. */
5791 fncall0 = build_call_expr_loc (input_location,
5792 gfor_fndecl_size0, 1, arg1);
5794 actual = actual->next;
5796 if (actual->expr)
5798 gfc_init_se (&argse, NULL);
5799 gfc_conv_expr_type (&argse, actual->expr,
5800 gfc_array_index_type);
5801 gfc_add_block_to_block (&se->pre, &argse.pre);
5803 /* Unusually, for an intrinsic, size does not exclude
5804 an optional arg2, so we must test for it. */
5805 if (actual->expr->expr_type == EXPR_VARIABLE
5806 && actual->expr->symtree->n.sym->attr.dummy
5807 && actual->expr->symtree->n.sym->attr.optional)
5809 tree tmp;
5810 /* Build the call to size1. */
5811 fncall1 = build_call_expr_loc (input_location,
5812 gfor_fndecl_size1, 2,
5813 arg1, argse.expr);
5815 gfc_init_se (&argse, NULL);
5816 argse.want_pointer = 1;
5817 argse.data_not_needed = 1;
5818 gfc_conv_expr (&argse, actual->expr);
5819 gfc_add_block_to_block (&se->pre, &argse.pre);
5820 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5821 argse.expr, null_pointer_node);
5822 tmp = gfc_evaluate_now (tmp, &se->pre);
5823 se->expr = fold_build3_loc (input_location, COND_EXPR,
5824 pvoid_type_node, tmp, fncall1, fncall0);
5826 else
5828 se->expr = NULL_TREE;
5829 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
5830 gfc_array_index_type,
5831 argse.expr, gfc_index_one_node);
5834 else if (expr->value.function.actual->expr->rank == 1)
5836 argse.expr = gfc_index_zero_node;
5837 se->expr = NULL_TREE;
5839 else
5840 se->expr = fncall0;
5842 if (se->expr == NULL_TREE)
5844 tree ubound, lbound;
5846 arg1 = build_fold_indirect_ref_loc (input_location,
5847 arg1);
5848 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
5849 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
5850 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
5851 gfc_array_index_type, ubound, lbound);
5852 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
5853 gfc_array_index_type,
5854 se->expr, gfc_index_one_node);
5855 se->expr = fold_build2_loc (input_location, MAX_EXPR,
5856 gfc_array_index_type, se->expr,
5857 gfc_index_zero_node);
5860 type = gfc_typenode_for_spec (&expr->ts);
5861 se->expr = convert (type, se->expr);
5865 /* Helper function to compute the size of a character variable,
5866 excluding the terminating null characters. The result has
5867 gfc_array_index_type type. */
5869 tree
5870 size_of_string_in_bytes (int kind, tree string_length)
5872 tree bytesize;
5873 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
5875 bytesize = build_int_cst (gfc_array_index_type,
5876 gfc_character_kinds[i].bit_size / 8);
5878 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5879 bytesize,
5880 fold_convert (gfc_array_index_type, string_length));
5884 static void
5885 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
5887 gfc_expr *arg;
5888 gfc_se argse;
5889 tree source_bytes;
5890 tree tmp;
5891 tree lower;
5892 tree upper;
5893 tree byte_size;
5894 int n;
5896 gfc_init_se (&argse, NULL);
5897 arg = expr->value.function.actual->expr;
5899 if (arg->rank || arg->ts.type == BT_ASSUMED)
5900 gfc_conv_expr_descriptor (&argse, arg);
5901 else
5902 gfc_conv_expr_reference (&argse, arg);
5904 if (arg->ts.type == BT_ASSUMED)
5906 /* This only works if an array descriptor has been passed; thus, extract
5907 the size from the descriptor. */
5908 gcc_assert (TYPE_PRECISION (gfc_array_index_type)
5909 == TYPE_PRECISION (size_type_node));
5910 tmp = arg->symtree->n.sym->backend_decl;
5911 tmp = DECL_LANG_SPECIFIC (tmp)
5912 && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
5913 ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
5914 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
5915 tmp = build_fold_indirect_ref_loc (input_location, tmp);
5916 tmp = fold_convert (size_type_node, gfc_conv_descriptor_dtype (tmp));
5917 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, TREE_TYPE (tmp), tmp,
5918 build_int_cst (TREE_TYPE (tmp),
5919 GFC_DTYPE_SIZE_SHIFT));
5920 byte_size = fold_convert (gfc_array_index_type, tmp);
5922 else if (arg->ts.type == BT_CLASS)
5924 if (arg->rank)
5925 byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
5926 else
5927 byte_size = gfc_class_vtab_size_get (argse.expr);
5929 else
5931 if (arg->ts.type == BT_CHARACTER)
5932 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
5933 else
5935 if (arg->rank == 0)
5936 byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5937 argse.expr));
5938 else
5939 byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
5940 byte_size = fold_convert (gfc_array_index_type,
5941 size_in_bytes (byte_size));
5945 if (arg->rank == 0)
5946 se->expr = byte_size;
5947 else
5949 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
5950 gfc_add_modify (&argse.pre, source_bytes, byte_size);
5952 if (arg->rank == -1)
5954 tree cond, loop_var, exit_label;
5955 stmtblock_t body;
5957 tmp = fold_convert (gfc_array_index_type,
5958 gfc_conv_descriptor_rank (argse.expr));
5959 loop_var = gfc_create_var (gfc_array_index_type, "i");
5960 gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
5961 exit_label = gfc_build_label_decl (NULL_TREE);
5963 /* Create loop:
5964 for (;;)
5966 if (i >= rank)
5967 goto exit;
5968 source_bytes = source_bytes * array.dim[i].extent;
5969 i = i + 1;
5971 exit: */
5972 gfc_start_block (&body);
5973 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
5974 loop_var, tmp);
5975 tmp = build1_v (GOTO_EXPR, exit_label);
5976 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5977 cond, tmp, build_empty_stmt (input_location));
5978 gfc_add_expr_to_block (&body, tmp);
5980 lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
5981 upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
5982 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
5983 tmp = fold_build2_loc (input_location, MULT_EXPR,
5984 gfc_array_index_type, tmp, source_bytes);
5985 gfc_add_modify (&body, source_bytes, tmp);
5987 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5988 gfc_array_index_type, loop_var,
5989 gfc_index_one_node);
5990 gfc_add_modify_loc (input_location, &body, loop_var, tmp);
5992 tmp = gfc_finish_block (&body);
5994 tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
5995 tmp);
5996 gfc_add_expr_to_block (&argse.pre, tmp);
5998 tmp = build1_v (LABEL_EXPR, exit_label);
5999 gfc_add_expr_to_block (&argse.pre, tmp);
6001 else
6003 /* Obtain the size of the array in bytes. */
6004 for (n = 0; n < arg->rank; n++)
6006 tree idx;
6007 idx = gfc_rank_cst[n];
6008 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
6009 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
6010 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
6011 tmp = fold_build2_loc (input_location, MULT_EXPR,
6012 gfc_array_index_type, tmp, source_bytes);
6013 gfc_add_modify (&argse.pre, source_bytes, tmp);
6016 se->expr = source_bytes;
6019 gfc_add_block_to_block (&se->pre, &argse.pre);
6023 static void
6024 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
6026 gfc_expr *arg;
6027 gfc_se argse;
6028 tree type, result_type, tmp;
6030 arg = expr->value.function.actual->expr;
6032 gfc_init_se (&argse, NULL);
6033 result_type = gfc_get_int_type (expr->ts.kind);
6035 if (arg->rank == 0)
6037 if (arg->ts.type == BT_CLASS)
6039 gfc_add_vptr_component (arg);
6040 gfc_add_size_component (arg);
6041 gfc_conv_expr (&argse, arg);
6042 tmp = fold_convert (result_type, argse.expr);
6043 goto done;
6046 gfc_conv_expr_reference (&argse, arg);
6047 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
6048 argse.expr));
6050 else
6052 argse.want_pointer = 0;
6053 gfc_conv_expr_descriptor (&argse, arg);
6054 if (arg->ts.type == BT_CLASS)
6056 tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
6057 tmp = fold_convert (result_type, tmp);
6058 goto done;
6060 type = gfc_get_element_type (TREE_TYPE (argse.expr));
6063 /* Obtain the argument's word length. */
6064 if (arg->ts.type == BT_CHARACTER)
6065 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
6066 else
6067 tmp = size_in_bytes (type);
6068 tmp = fold_convert (result_type, tmp);
6070 done:
6071 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
6072 build_int_cst (result_type, BITS_PER_UNIT));
6073 gfc_add_block_to_block (&se->pre, &argse.pre);
6077 /* Intrinsic string comparison functions. */
6079 static void
6080 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
6082 tree args[4];
6084 gfc_conv_intrinsic_function_args (se, expr, args, 4);
6086 se->expr
6087 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
6088 expr->value.function.actual->expr->ts.kind,
6089 op);
6090 se->expr = fold_build2_loc (input_location, op,
6091 gfc_typenode_for_spec (&expr->ts), se->expr,
6092 build_int_cst (TREE_TYPE (se->expr), 0));
6095 /* Generate a call to the adjustl/adjustr library function. */
6096 static void
6097 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
6099 tree args[3];
6100 tree len;
6101 tree type;
6102 tree var;
6103 tree tmp;
6105 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
6106 len = args[1];
6108 type = TREE_TYPE (args[2]);
6109 var = gfc_conv_string_tmp (se, type, len);
6110 args[0] = var;
6112 tmp = build_call_expr_loc (input_location,
6113 fndecl, 3, args[0], args[1], args[2]);
6114 gfc_add_expr_to_block (&se->pre, tmp);
6115 se->expr = var;
6116 se->string_length = len;
6120 /* Generate code for the TRANSFER intrinsic:
6121 For scalar results:
6122 DEST = TRANSFER (SOURCE, MOLD)
6123 where:
6124 typeof<DEST> = typeof<MOLD>
6125 and:
6126 MOLD is scalar.
6128 For array results:
6129 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
6130 where:
6131 typeof<DEST> = typeof<MOLD>
6132 and:
6133 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
6134 sizeof (DEST(0) * SIZE). */
6135 static void
6136 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
6138 tree tmp;
6139 tree tmpdecl;
6140 tree ptr;
6141 tree extent;
6142 tree source;
6143 tree source_type;
6144 tree source_bytes;
6145 tree mold_type;
6146 tree dest_word_len;
6147 tree size_words;
6148 tree size_bytes;
6149 tree upper;
6150 tree lower;
6151 tree stmt;
6152 gfc_actual_arglist *arg;
6153 gfc_se argse;
6154 gfc_array_info *info;
6155 stmtblock_t block;
6156 int n;
6157 bool scalar_mold;
6158 gfc_expr *source_expr, *mold_expr;
6160 info = NULL;
6161 if (se->loop)
6162 info = &se->ss->info->data.array;
6164 /* Convert SOURCE. The output from this stage is:-
6165 source_bytes = length of the source in bytes
6166 source = pointer to the source data. */
6167 arg = expr->value.function.actual;
6168 source_expr = arg->expr;
6170 /* Ensure double transfer through LOGICAL preserves all
6171 the needed bits. */
6172 if (arg->expr->expr_type == EXPR_FUNCTION
6173 && arg->expr->value.function.esym == NULL
6174 && arg->expr->value.function.isym != NULL
6175 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
6176 && arg->expr->ts.type == BT_LOGICAL
6177 && expr->ts.type != arg->expr->ts.type)
6178 arg->expr->value.function.name = "__transfer_in_transfer";
6180 gfc_init_se (&argse, NULL);
6182 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
6184 /* Obtain the pointer to source and the length of source in bytes. */
6185 if (arg->expr->rank == 0)
6187 gfc_conv_expr_reference (&argse, arg->expr);
6188 if (arg->expr->ts.type == BT_CLASS)
6189 source = gfc_class_data_get (argse.expr);
6190 else
6191 source = argse.expr;
6193 /* Obtain the source word length. */
6194 switch (arg->expr->ts.type)
6196 case BT_CHARACTER:
6197 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
6198 argse.string_length);
6199 break;
6200 case BT_CLASS:
6201 tmp = gfc_class_vtab_size_get (argse.expr);
6202 break;
6203 default:
6204 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
6205 source));
6206 tmp = fold_convert (gfc_array_index_type,
6207 size_in_bytes (source_type));
6208 break;
6211 else
6213 argse.want_pointer = 0;
6214 gfc_conv_expr_descriptor (&argse, arg->expr);
6215 source = gfc_conv_descriptor_data_get (argse.expr);
6216 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
6218 /* Repack the source if not simply contiguous. */
6219 if (!gfc_is_simply_contiguous (arg->expr, false))
6221 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
6223 if (warn_array_temporaries)
6224 gfc_warning (OPT_Warray_temporaries,
6225 "Creating array temporary at %L", &expr->where);
6227 source = build_call_expr_loc (input_location,
6228 gfor_fndecl_in_pack, 1, tmp);
6229 source = gfc_evaluate_now (source, &argse.pre);
6231 /* Free the temporary. */
6232 gfc_start_block (&block);
6233 tmp = gfc_call_free (convert (pvoid_type_node, source));
6234 gfc_add_expr_to_block (&block, tmp);
6235 stmt = gfc_finish_block (&block);
6237 /* Clean up if it was repacked. */
6238 gfc_init_block (&block);
6239 tmp = gfc_conv_array_data (argse.expr);
6240 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6241 source, tmp);
6242 tmp = build3_v (COND_EXPR, tmp, stmt,
6243 build_empty_stmt (input_location));
6244 gfc_add_expr_to_block (&block, tmp);
6245 gfc_add_block_to_block (&block, &se->post);
6246 gfc_init_block (&se->post);
6247 gfc_add_block_to_block (&se->post, &block);
6250 /* Obtain the source word length. */
6251 if (arg->expr->ts.type == BT_CHARACTER)
6252 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
6253 argse.string_length);
6254 else
6255 tmp = fold_convert (gfc_array_index_type,
6256 size_in_bytes (source_type));
6258 /* Obtain the size of the array in bytes. */
6259 extent = gfc_create_var (gfc_array_index_type, NULL);
6260 for (n = 0; n < arg->expr->rank; n++)
6262 tree idx;
6263 idx = gfc_rank_cst[n];
6264 gfc_add_modify (&argse.pre, source_bytes, tmp);
6265 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
6266 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
6267 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6268 gfc_array_index_type, upper, lower);
6269 gfc_add_modify (&argse.pre, extent, tmp);
6270 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6271 gfc_array_index_type, extent,
6272 gfc_index_one_node);
6273 tmp = fold_build2_loc (input_location, MULT_EXPR,
6274 gfc_array_index_type, tmp, source_bytes);
6278 gfc_add_modify (&argse.pre, source_bytes, tmp);
6279 gfc_add_block_to_block (&se->pre, &argse.pre);
6280 gfc_add_block_to_block (&se->post, &argse.post);
6282 /* Now convert MOLD. The outputs are:
6283 mold_type = the TREE type of MOLD
6284 dest_word_len = destination word length in bytes. */
6285 arg = arg->next;
6286 mold_expr = arg->expr;
6288 gfc_init_se (&argse, NULL);
6290 scalar_mold = arg->expr->rank == 0;
6292 if (arg->expr->rank == 0)
6294 gfc_conv_expr_reference (&argse, arg->expr);
6295 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
6296 argse.expr));
6298 else
6300 gfc_init_se (&argse, NULL);
6301 argse.want_pointer = 0;
6302 gfc_conv_expr_descriptor (&argse, arg->expr);
6303 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
6306 gfc_add_block_to_block (&se->pre, &argse.pre);
6307 gfc_add_block_to_block (&se->post, &argse.post);
6309 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
6311 /* If this TRANSFER is nested in another TRANSFER, use a type
6312 that preserves all bits. */
6313 if (arg->expr->ts.type == BT_LOGICAL)
6314 mold_type = gfc_get_int_type (arg->expr->ts.kind);
6317 /* Obtain the destination word length. */
6318 switch (arg->expr->ts.type)
6320 case BT_CHARACTER:
6321 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
6322 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
6323 break;
6324 case BT_CLASS:
6325 tmp = gfc_class_vtab_size_get (argse.expr);
6326 break;
6327 default:
6328 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
6329 break;
6331 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
6332 gfc_add_modify (&se->pre, dest_word_len, tmp);
6334 /* Finally convert SIZE, if it is present. */
6335 arg = arg->next;
6336 size_words = gfc_create_var (gfc_array_index_type, NULL);
6338 if (arg->expr)
6340 gfc_init_se (&argse, NULL);
6341 gfc_conv_expr_reference (&argse, arg->expr);
6342 tmp = convert (gfc_array_index_type,
6343 build_fold_indirect_ref_loc (input_location,
6344 argse.expr));
6345 gfc_add_block_to_block (&se->pre, &argse.pre);
6346 gfc_add_block_to_block (&se->post, &argse.post);
6348 else
6349 tmp = NULL_TREE;
6351 /* Separate array and scalar results. */
6352 if (scalar_mold && tmp == NULL_TREE)
6353 goto scalar_transfer;
6355 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
6356 if (tmp != NULL_TREE)
6357 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6358 tmp, dest_word_len);
6359 else
6360 tmp = source_bytes;
6362 gfc_add_modify (&se->pre, size_bytes, tmp);
6363 gfc_add_modify (&se->pre, size_words,
6364 fold_build2_loc (input_location, CEIL_DIV_EXPR,
6365 gfc_array_index_type,
6366 size_bytes, dest_word_len));
6368 /* Evaluate the bounds of the result. If the loop range exists, we have
6369 to check if it is too large. If so, we modify loop->to be consistent
6370 with min(size, size(source)). Otherwise, size is made consistent with
6371 the loop range, so that the right number of bytes is transferred.*/
6372 n = se->loop->order[0];
6373 if (se->loop->to[n] != NULL_TREE)
6375 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6376 se->loop->to[n], se->loop->from[n]);
6377 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
6378 tmp, gfc_index_one_node);
6379 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
6380 tmp, size_words);
6381 gfc_add_modify (&se->pre, size_words, tmp);
6382 gfc_add_modify (&se->pre, size_bytes,
6383 fold_build2_loc (input_location, MULT_EXPR,
6384 gfc_array_index_type,
6385 size_words, dest_word_len));
6386 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
6387 size_words, se->loop->from[n]);
6388 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6389 upper, gfc_index_one_node);
6391 else
6393 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6394 size_words, gfc_index_one_node);
6395 se->loop->from[n] = gfc_index_zero_node;
6398 se->loop->to[n] = upper;
6400 /* Build a destination descriptor, using the pointer, source, as the
6401 data field. */
6402 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
6403 NULL_TREE, false, true, false, &expr->where);
6405 /* Cast the pointer to the result. */
6406 tmp = gfc_conv_descriptor_data_get (info->descriptor);
6407 tmp = fold_convert (pvoid_type_node, tmp);
6409 /* Use memcpy to do the transfer. */
6411 = build_call_expr_loc (input_location,
6412 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
6413 fold_convert (pvoid_type_node, source),
6414 fold_convert (size_type_node,
6415 fold_build2_loc (input_location,
6416 MIN_EXPR,
6417 gfc_array_index_type,
6418 size_bytes,
6419 source_bytes)));
6420 gfc_add_expr_to_block (&se->pre, tmp);
6422 se->expr = info->descriptor;
6423 if (expr->ts.type == BT_CHARACTER)
6424 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
6426 return;
6428 /* Deal with scalar results. */
6429 scalar_transfer:
6430 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
6431 dest_word_len, source_bytes);
6432 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
6433 extent, gfc_index_zero_node);
6435 if (expr->ts.type == BT_CHARACTER)
6437 tree direct, indirect, free;
6439 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
6440 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
6441 "transfer");
6443 /* If source is longer than the destination, use a pointer to
6444 the source directly. */
6445 gfc_init_block (&block);
6446 gfc_add_modify (&block, tmpdecl, ptr);
6447 direct = gfc_finish_block (&block);
6449 /* Otherwise, allocate a string with the length of the destination
6450 and copy the source into it. */
6451 gfc_init_block (&block);
6452 tmp = gfc_get_pchar_type (expr->ts.kind);
6453 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
6454 gfc_add_modify (&block, tmpdecl,
6455 fold_convert (TREE_TYPE (ptr), tmp));
6456 tmp = build_call_expr_loc (input_location,
6457 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
6458 fold_convert (pvoid_type_node, tmpdecl),
6459 fold_convert (pvoid_type_node, ptr),
6460 fold_convert (size_type_node, extent));
6461 gfc_add_expr_to_block (&block, tmp);
6462 indirect = gfc_finish_block (&block);
6464 /* Wrap it up with the condition. */
6465 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
6466 dest_word_len, source_bytes);
6467 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
6468 gfc_add_expr_to_block (&se->pre, tmp);
6470 /* Free the temporary string, if necessary. */
6471 free = gfc_call_free (tmpdecl);
6472 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6473 dest_word_len, source_bytes);
6474 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
6475 gfc_add_expr_to_block (&se->post, tmp);
6477 se->expr = tmpdecl;
6478 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
6480 else
6482 tmpdecl = gfc_create_var (mold_type, "transfer");
6484 ptr = convert (build_pointer_type (mold_type), source);
6486 /* For CLASS results, allocate the needed memory first. */
6487 if (mold_expr->ts.type == BT_CLASS)
6489 tree cdata;
6490 cdata = gfc_class_data_get (tmpdecl);
6491 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
6492 gfc_add_modify (&se->pre, cdata, tmp);
6495 /* Use memcpy to do the transfer. */
6496 if (mold_expr->ts.type == BT_CLASS)
6497 tmp = gfc_class_data_get (tmpdecl);
6498 else
6499 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
6501 tmp = build_call_expr_loc (input_location,
6502 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
6503 fold_convert (pvoid_type_node, tmp),
6504 fold_convert (pvoid_type_node, ptr),
6505 fold_convert (size_type_node, extent));
6506 gfc_add_expr_to_block (&se->pre, tmp);
6508 /* For CLASS results, set the _vptr. */
6509 if (mold_expr->ts.type == BT_CLASS)
6511 tree vptr;
6512 gfc_symbol *vtab;
6513 vptr = gfc_class_vptr_get (tmpdecl);
6514 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
6515 gcc_assert (vtab);
6516 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
6517 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
6520 se->expr = tmpdecl;
6525 /* Generate code for the ALLOCATED intrinsic.
6526 Generate inline code that directly check the address of the argument. */
6528 static void
6529 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
6531 gfc_actual_arglist *arg1;
6532 gfc_se arg1se;
6533 tree tmp;
6535 gfc_init_se (&arg1se, NULL);
6536 arg1 = expr->value.function.actual;
6538 if (arg1->expr->ts.type == BT_CLASS)
6540 /* Make sure that class array expressions have both a _data
6541 component reference and an array reference.... */
6542 if (CLASS_DATA (arg1->expr)->attr.dimension)
6543 gfc_add_class_array_ref (arg1->expr);
6544 /* .... whilst scalars only need the _data component. */
6545 else
6546 gfc_add_data_component (arg1->expr);
6549 if (arg1->expr->rank == 0)
6551 /* Allocatable scalar. */
6552 arg1se.want_pointer = 1;
6553 gfc_conv_expr (&arg1se, arg1->expr);
6554 tmp = arg1se.expr;
6556 else
6558 /* Allocatable array. */
6559 arg1se.descriptor_only = 1;
6560 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
6561 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
6564 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
6565 fold_convert (TREE_TYPE (tmp), null_pointer_node));
6566 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
6570 /* Generate code for the ASSOCIATED intrinsic.
6571 If both POINTER and TARGET are arrays, generate a call to library function
6572 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
6573 In other cases, generate inline code that directly compare the address of
6574 POINTER with the address of TARGET. */
6576 static void
6577 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
6579 gfc_actual_arglist *arg1;
6580 gfc_actual_arglist *arg2;
6581 gfc_se arg1se;
6582 gfc_se arg2se;
6583 tree tmp2;
6584 tree tmp;
6585 tree nonzero_charlen;
6586 tree nonzero_arraylen;
6587 gfc_ss *ss;
6588 bool scalar;
6590 gfc_init_se (&arg1se, NULL);
6591 gfc_init_se (&arg2se, NULL);
6592 arg1 = expr->value.function.actual;
6593 arg2 = arg1->next;
6595 /* Check whether the expression is a scalar or not; we cannot use
6596 arg1->expr->rank as it can be nonzero for proc pointers. */
6597 ss = gfc_walk_expr (arg1->expr);
6598 scalar = ss == gfc_ss_terminator;
6599 if (!scalar)
6600 gfc_free_ss_chain (ss);
6602 if (!arg2->expr)
6604 /* No optional target. */
6605 if (scalar)
6607 /* A pointer to a scalar. */
6608 arg1se.want_pointer = 1;
6609 gfc_conv_expr (&arg1se, arg1->expr);
6610 if (arg1->expr->symtree->n.sym->attr.proc_pointer
6611 && arg1->expr->symtree->n.sym->attr.dummy)
6612 arg1se.expr = build_fold_indirect_ref_loc (input_location,
6613 arg1se.expr);
6614 if (arg1->expr->ts.type == BT_CLASS)
6616 tmp2 = gfc_class_data_get (arg1se.expr);
6617 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
6618 tmp2 = gfc_conv_descriptor_data_get (tmp2);
6620 else
6621 tmp2 = arg1se.expr;
6623 else
6625 /* A pointer to an array. */
6626 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
6627 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
6629 gfc_add_block_to_block (&se->pre, &arg1se.pre);
6630 gfc_add_block_to_block (&se->post, &arg1se.post);
6631 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp2,
6632 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
6633 se->expr = tmp;
6635 else
6637 /* An optional target. */
6638 if (arg2->expr->ts.type == BT_CLASS)
6639 gfc_add_data_component (arg2->expr);
6641 nonzero_charlen = NULL_TREE;
6642 if (arg1->expr->ts.type == BT_CHARACTER)
6643 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
6644 boolean_type_node,
6645 arg1->expr->ts.u.cl->backend_decl,
6646 integer_zero_node);
6647 if (scalar)
6649 /* A pointer to a scalar. */
6650 arg1se.want_pointer = 1;
6651 gfc_conv_expr (&arg1se, arg1->expr);
6652 if (arg1->expr->symtree->n.sym->attr.proc_pointer
6653 && arg1->expr->symtree->n.sym->attr.dummy)
6654 arg1se.expr = build_fold_indirect_ref_loc (input_location,
6655 arg1se.expr);
6656 if (arg1->expr->ts.type == BT_CLASS)
6657 arg1se.expr = gfc_class_data_get (arg1se.expr);
6659 arg2se.want_pointer = 1;
6660 gfc_conv_expr (&arg2se, arg2->expr);
6661 if (arg2->expr->symtree->n.sym->attr.proc_pointer
6662 && arg2->expr->symtree->n.sym->attr.dummy)
6663 arg2se.expr = build_fold_indirect_ref_loc (input_location,
6664 arg2se.expr);
6665 gfc_add_block_to_block (&se->pre, &arg1se.pre);
6666 gfc_add_block_to_block (&se->post, &arg1se.post);
6667 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
6668 arg1se.expr, arg2se.expr);
6669 tmp2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6670 arg1se.expr, null_pointer_node);
6671 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6672 boolean_type_node, tmp, tmp2);
6674 else
6676 /* An array pointer of zero length is not associated if target is
6677 present. */
6678 arg1se.descriptor_only = 1;
6679 gfc_conv_expr_lhs (&arg1se, arg1->expr);
6680 if (arg1->expr->rank == -1)
6682 tmp = gfc_conv_descriptor_rank (arg1se.expr);
6683 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6684 TREE_TYPE (tmp), tmp, gfc_index_one_node);
6686 else
6687 tmp = gfc_rank_cst[arg1->expr->rank - 1];
6688 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
6689 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
6690 boolean_type_node, tmp,
6691 build_int_cst (TREE_TYPE (tmp), 0));
6693 /* A pointer to an array, call library function _gfor_associated. */
6694 arg1se.want_pointer = 1;
6695 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
6697 arg2se.want_pointer = 1;
6698 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
6699 gfc_add_block_to_block (&se->pre, &arg2se.pre);
6700 gfc_add_block_to_block (&se->post, &arg2se.post);
6701 se->expr = build_call_expr_loc (input_location,
6702 gfor_fndecl_associated, 2,
6703 arg1se.expr, arg2se.expr);
6704 se->expr = convert (boolean_type_node, se->expr);
6705 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6706 boolean_type_node, se->expr,
6707 nonzero_arraylen);
6710 /* If target is present zero character length pointers cannot
6711 be associated. */
6712 if (nonzero_charlen != NULL_TREE)
6713 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6714 boolean_type_node,
6715 se->expr, nonzero_charlen);
6718 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6722 /* Generate code for the SAME_TYPE_AS intrinsic.
6723 Generate inline code that directly checks the vindices. */
6725 static void
6726 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
6728 gfc_expr *a, *b;
6729 gfc_se se1, se2;
6730 tree tmp;
6731 tree conda = NULL_TREE, condb = NULL_TREE;
6733 gfc_init_se (&se1, NULL);
6734 gfc_init_se (&se2, NULL);
6736 a = expr->value.function.actual->expr;
6737 b = expr->value.function.actual->next->expr;
6739 if (UNLIMITED_POLY (a))
6741 tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
6742 conda = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6743 tmp, build_int_cst (TREE_TYPE (tmp), 0));
6746 if (UNLIMITED_POLY (b))
6748 tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
6749 condb = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6750 tmp, build_int_cst (TREE_TYPE (tmp), 0));
6753 if (a->ts.type == BT_CLASS)
6755 gfc_add_vptr_component (a);
6756 gfc_add_hash_component (a);
6758 else if (a->ts.type == BT_DERIVED)
6759 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
6760 a->ts.u.derived->hash_value);
6762 if (b->ts.type == BT_CLASS)
6764 gfc_add_vptr_component (b);
6765 gfc_add_hash_component (b);
6767 else if (b->ts.type == BT_DERIVED)
6768 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
6769 b->ts.u.derived->hash_value);
6771 gfc_conv_expr (&se1, a);
6772 gfc_conv_expr (&se2, b);
6774 tmp = fold_build2_loc (input_location, EQ_EXPR,
6775 boolean_type_node, se1.expr,
6776 fold_convert (TREE_TYPE (se1.expr), se2.expr));
6778 if (conda)
6779 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
6780 boolean_type_node, conda, tmp);
6782 if (condb)
6783 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
6784 boolean_type_node, condb, tmp);
6786 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
6790 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
6792 static void
6793 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
6795 tree args[2];
6797 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6798 se->expr = build_call_expr_loc (input_location,
6799 gfor_fndecl_sc_kind, 2, args[0], args[1]);
6800 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6804 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
6806 static void
6807 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
6809 tree arg, type;
6811 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6813 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
6814 type = gfc_get_int_type (4);
6815 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
6817 /* Convert it to the required type. */
6818 type = gfc_typenode_for_spec (&expr->ts);
6819 se->expr = build_call_expr_loc (input_location,
6820 gfor_fndecl_si_kind, 1, arg);
6821 se->expr = fold_convert (type, se->expr);
6825 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
6827 static void
6828 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
6830 gfc_actual_arglist *actual;
6831 tree type;
6832 gfc_se argse;
6833 vec<tree, va_gc> *args = NULL;
6835 for (actual = expr->value.function.actual; actual; actual = actual->next)
6837 gfc_init_se (&argse, se);
6839 /* Pass a NULL pointer for an absent arg. */
6840 if (actual->expr == NULL)
6841 argse.expr = null_pointer_node;
6842 else
6844 gfc_typespec ts;
6845 gfc_clear_ts (&ts);
6847 if (actual->expr->ts.kind != gfc_c_int_kind)
6849 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
6850 ts.type = BT_INTEGER;
6851 ts.kind = gfc_c_int_kind;
6852 gfc_convert_type (actual->expr, &ts, 2);
6854 gfc_conv_expr_reference (&argse, actual->expr);
6857 gfc_add_block_to_block (&se->pre, &argse.pre);
6858 gfc_add_block_to_block (&se->post, &argse.post);
6859 vec_safe_push (args, argse.expr);
6862 /* Convert it to the required type. */
6863 type = gfc_typenode_for_spec (&expr->ts);
6864 se->expr = build_call_expr_loc_vec (input_location,
6865 gfor_fndecl_sr_kind, args);
6866 se->expr = fold_convert (type, se->expr);
6870 /* Generate code for TRIM (A) intrinsic function. */
6872 static void
6873 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
6875 tree var;
6876 tree len;
6877 tree addr;
6878 tree tmp;
6879 tree cond;
6880 tree fndecl;
6881 tree function;
6882 tree *args;
6883 unsigned int num_args;
6885 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
6886 args = XALLOCAVEC (tree, num_args);
6888 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
6889 addr = gfc_build_addr_expr (ppvoid_type_node, var);
6890 len = gfc_create_var (gfc_charlen_type_node, "len");
6892 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
6893 args[0] = gfc_build_addr_expr (NULL_TREE, len);
6894 args[1] = addr;
6896 if (expr->ts.kind == 1)
6897 function = gfor_fndecl_string_trim;
6898 else if (expr->ts.kind == 4)
6899 function = gfor_fndecl_string_trim_char4;
6900 else
6901 gcc_unreachable ();
6903 fndecl = build_addr (function, current_function_decl);
6904 tmp = build_call_array_loc (input_location,
6905 TREE_TYPE (TREE_TYPE (function)), fndecl,
6906 num_args, args);
6907 gfc_add_expr_to_block (&se->pre, tmp);
6909 /* Free the temporary afterwards, if necessary. */
6910 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6911 len, build_int_cst (TREE_TYPE (len), 0));
6912 tmp = gfc_call_free (var);
6913 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
6914 gfc_add_expr_to_block (&se->post, tmp);
6916 se->expr = var;
6917 se->string_length = len;
6921 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
6923 static void
6924 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
6926 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
6927 tree type, cond, tmp, count, exit_label, n, max, largest;
6928 tree size;
6929 stmtblock_t block, body;
6930 int i;
6932 /* We store in charsize the size of a character. */
6933 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
6934 size = build_int_cst (size_type_node, gfc_character_kinds[i].bit_size / 8);
6936 /* Get the arguments. */
6937 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6938 slen = fold_convert (size_type_node, gfc_evaluate_now (args[0], &se->pre));
6939 src = args[1];
6940 ncopies = gfc_evaluate_now (args[2], &se->pre);
6941 ncopies_type = TREE_TYPE (ncopies);
6943 /* Check that NCOPIES is not negative. */
6944 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, ncopies,
6945 build_int_cst (ncopies_type, 0));
6946 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
6947 "Argument NCOPIES of REPEAT intrinsic is negative "
6948 "(its value is %ld)",
6949 fold_convert (long_integer_type_node, ncopies));
6951 /* If the source length is zero, any non negative value of NCOPIES
6952 is valid, and nothing happens. */
6953 n = gfc_create_var (ncopies_type, "ncopies");
6954 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
6955 build_int_cst (size_type_node, 0));
6956 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
6957 build_int_cst (ncopies_type, 0), ncopies);
6958 gfc_add_modify (&se->pre, n, tmp);
6959 ncopies = n;
6961 /* Check that ncopies is not too large: ncopies should be less than
6962 (or equal to) MAX / slen, where MAX is the maximal integer of
6963 the gfc_charlen_type_node type. If slen == 0, we need a special
6964 case to avoid the division by zero. */
6965 i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
6966 max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_charlen_int_kind);
6967 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node,
6968 fold_convert (size_type_node, max), slen);
6969 largest = TYPE_PRECISION (size_type_node) > TYPE_PRECISION (ncopies_type)
6970 ? size_type_node : ncopies_type;
6971 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6972 fold_convert (largest, ncopies),
6973 fold_convert (largest, max));
6974 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
6975 build_int_cst (size_type_node, 0));
6976 cond = fold_build3_loc (input_location, COND_EXPR, boolean_type_node, tmp,
6977 boolean_false_node, cond);
6978 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
6979 "Argument NCOPIES of REPEAT intrinsic is too large");
6981 /* Compute the destination length. */
6982 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6983 fold_convert (gfc_charlen_type_node, slen),
6984 fold_convert (gfc_charlen_type_node, ncopies));
6985 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
6986 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
6988 /* Generate the code to do the repeat operation:
6989 for (i = 0; i < ncopies; i++)
6990 memmove (dest + (i * slen * size), src, slen*size); */
6991 gfc_start_block (&block);
6992 count = gfc_create_var (ncopies_type, "count");
6993 gfc_add_modify (&block, count, build_int_cst (ncopies_type, 0));
6994 exit_label = gfc_build_label_decl (NULL_TREE);
6996 /* Start the loop body. */
6997 gfc_start_block (&body);
6999 /* Exit the loop if count >= ncopies. */
7000 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, count,
7001 ncopies);
7002 tmp = build1_v (GOTO_EXPR, exit_label);
7003 TREE_USED (exit_label) = 1;
7004 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
7005 build_empty_stmt (input_location));
7006 gfc_add_expr_to_block (&body, tmp);
7008 /* Call memmove (dest + (i*slen*size), src, slen*size). */
7009 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
7010 fold_convert (gfc_charlen_type_node, slen),
7011 fold_convert (gfc_charlen_type_node, count));
7012 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
7013 tmp, fold_convert (gfc_charlen_type_node, size));
7014 tmp = fold_build_pointer_plus_loc (input_location,
7015 fold_convert (pvoid_type_node, dest), tmp);
7016 tmp = build_call_expr_loc (input_location,
7017 builtin_decl_explicit (BUILT_IN_MEMMOVE),
7018 3, tmp, src,
7019 fold_build2_loc (input_location, MULT_EXPR,
7020 size_type_node, slen,
7021 fold_convert (size_type_node,
7022 size)));
7023 gfc_add_expr_to_block (&body, tmp);
7025 /* Increment count. */
7026 tmp = fold_build2_loc (input_location, PLUS_EXPR, ncopies_type,
7027 count, build_int_cst (TREE_TYPE (count), 1));
7028 gfc_add_modify (&body, count, tmp);
7030 /* Build the loop. */
7031 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
7032 gfc_add_expr_to_block (&block, tmp);
7034 /* Add the exit label. */
7035 tmp = build1_v (LABEL_EXPR, exit_label);
7036 gfc_add_expr_to_block (&block, tmp);
7038 /* Finish the block. */
7039 tmp = gfc_finish_block (&block);
7040 gfc_add_expr_to_block (&se->pre, tmp);
7042 /* Set the result value. */
7043 se->expr = dest;
7044 se->string_length = dlen;
7048 /* Generate code for the IARGC intrinsic. */
7050 static void
7051 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
7053 tree tmp;
7054 tree fndecl;
7055 tree type;
7057 /* Call the library function. This always returns an INTEGER(4). */
7058 fndecl = gfor_fndecl_iargc;
7059 tmp = build_call_expr_loc (input_location,
7060 fndecl, 0);
7062 /* Convert it to the required type. */
7063 type = gfc_typenode_for_spec (&expr->ts);
7064 tmp = fold_convert (type, tmp);
7066 se->expr = tmp;
7070 /* The loc intrinsic returns the address of its argument as
7071 gfc_index_integer_kind integer. */
7073 static void
7074 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
7076 tree temp_var;
7077 gfc_expr *arg_expr;
7079 gcc_assert (!se->ss);
7081 arg_expr = expr->value.function.actual->expr;
7082 if (arg_expr->rank == 0)
7083 gfc_conv_expr_reference (se, arg_expr);
7084 else
7085 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
7086 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
7088 /* Create a temporary variable for loc return value. Without this,
7089 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
7090 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
7091 gfc_add_modify (&se->pre, temp_var, se->expr);
7092 se->expr = temp_var;
7096 /* The following routine generates code for the intrinsic
7097 functions from the ISO_C_BINDING module:
7098 * C_LOC
7099 * C_FUNLOC
7100 * C_ASSOCIATED */
7102 static void
7103 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
7105 gfc_actual_arglist *arg = expr->value.function.actual;
7107 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
7109 if (arg->expr->rank == 0)
7110 gfc_conv_expr_reference (se, arg->expr);
7111 else if (gfc_is_simply_contiguous (arg->expr, false))
7112 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
7113 else
7115 gfc_conv_expr_descriptor (se, arg->expr);
7116 se->expr = gfc_conv_descriptor_data_get (se->expr);
7119 /* TODO -- the following two lines shouldn't be necessary, but if
7120 they're removed, a bug is exposed later in the code path.
7121 This workaround was thus introduced, but will have to be
7122 removed; please see PR 35150 for details about the issue. */
7123 se->expr = convert (pvoid_type_node, se->expr);
7124 se->expr = gfc_evaluate_now (se->expr, &se->pre);
7126 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
7127 gfc_conv_expr_reference (se, arg->expr);
7128 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
7130 gfc_se arg1se;
7131 gfc_se arg2se;
7133 /* Build the addr_expr for the first argument. The argument is
7134 already an *address* so we don't need to set want_pointer in
7135 the gfc_se. */
7136 gfc_init_se (&arg1se, NULL);
7137 gfc_conv_expr (&arg1se, arg->expr);
7138 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7139 gfc_add_block_to_block (&se->post, &arg1se.post);
7141 /* See if we were given two arguments. */
7142 if (arg->next->expr == NULL)
7143 /* Only given one arg so generate a null and do a
7144 not-equal comparison against the first arg. */
7145 se->expr = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7146 arg1se.expr,
7147 fold_convert (TREE_TYPE (arg1se.expr),
7148 null_pointer_node));
7149 else
7151 tree eq_expr;
7152 tree not_null_expr;
7154 /* Given two arguments so build the arg2se from second arg. */
7155 gfc_init_se (&arg2se, NULL);
7156 gfc_conv_expr (&arg2se, arg->next->expr);
7157 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7158 gfc_add_block_to_block (&se->post, &arg2se.post);
7160 /* Generate test to compare that the two args are equal. */
7161 eq_expr = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
7162 arg1se.expr, arg2se.expr);
7163 /* Generate test to ensure that the first arg is not null. */
7164 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
7165 boolean_type_node,
7166 arg1se.expr, null_pointer_node);
7168 /* Finally, the generated test must check that both arg1 is not
7169 NULL and that it is equal to the second arg. */
7170 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7171 boolean_type_node,
7172 not_null_expr, eq_expr);
7175 else
7176 gcc_unreachable ();
7180 /* The following routine generates code for the intrinsic
7181 subroutines from the ISO_C_BINDING module:
7182 * C_F_POINTER
7183 * C_F_PROCPOINTER. */
7185 static tree
7186 conv_isocbinding_subroutine (gfc_code *code)
7188 gfc_se se;
7189 gfc_se cptrse;
7190 gfc_se fptrse;
7191 gfc_se shapese;
7192 gfc_ss *shape_ss;
7193 tree desc, dim, tmp, stride, offset;
7194 stmtblock_t body, block;
7195 gfc_loopinfo loop;
7196 gfc_actual_arglist *arg = code->ext.actual;
7198 gfc_init_se (&se, NULL);
7199 gfc_init_se (&cptrse, NULL);
7200 gfc_conv_expr (&cptrse, arg->expr);
7201 gfc_add_block_to_block (&se.pre, &cptrse.pre);
7202 gfc_add_block_to_block (&se.post, &cptrse.post);
7204 gfc_init_se (&fptrse, NULL);
7205 if (arg->next->expr->rank == 0)
7207 fptrse.want_pointer = 1;
7208 gfc_conv_expr (&fptrse, arg->next->expr);
7209 gfc_add_block_to_block (&se.pre, &fptrse.pre);
7210 gfc_add_block_to_block (&se.post, &fptrse.post);
7211 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
7212 && arg->next->expr->symtree->n.sym->attr.dummy)
7213 fptrse.expr = build_fold_indirect_ref_loc (input_location,
7214 fptrse.expr);
7215 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
7216 TREE_TYPE (fptrse.expr),
7217 fptrse.expr,
7218 fold_convert (TREE_TYPE (fptrse.expr),
7219 cptrse.expr));
7220 gfc_add_expr_to_block (&se.pre, se.expr);
7221 gfc_add_block_to_block (&se.pre, &se.post);
7222 return gfc_finish_block (&se.pre);
7225 gfc_start_block (&block);
7227 /* Get the descriptor of the Fortran pointer. */
7228 fptrse.descriptor_only = 1;
7229 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
7230 gfc_add_block_to_block (&block, &fptrse.pre);
7231 desc = fptrse.expr;
7233 /* Set data value, dtype, and offset. */
7234 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
7235 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
7236 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
7237 gfc_get_dtype (TREE_TYPE (desc)));
7239 /* Start scalarization of the bounds, using the shape argument. */
7241 shape_ss = gfc_walk_expr (arg->next->next->expr);
7242 gcc_assert (shape_ss != gfc_ss_terminator);
7243 gfc_init_se (&shapese, NULL);
7245 gfc_init_loopinfo (&loop);
7246 gfc_add_ss_to_loop (&loop, shape_ss);
7247 gfc_conv_ss_startstride (&loop);
7248 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
7249 gfc_mark_ss_chain_used (shape_ss, 1);
7251 gfc_copy_loopinfo_to_se (&shapese, &loop);
7252 shapese.ss = shape_ss;
7254 stride = gfc_create_var (gfc_array_index_type, "stride");
7255 offset = gfc_create_var (gfc_array_index_type, "offset");
7256 gfc_add_modify (&block, stride, gfc_index_one_node);
7257 gfc_add_modify (&block, offset, gfc_index_zero_node);
7259 /* Loop body. */
7260 gfc_start_scalarized_body (&loop, &body);
7262 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7263 loop.loopvar[0], loop.from[0]);
7265 /* Set bounds and stride. */
7266 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
7267 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
7269 gfc_conv_expr (&shapese, arg->next->next->expr);
7270 gfc_add_block_to_block (&body, &shapese.pre);
7271 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
7272 gfc_add_block_to_block (&body, &shapese.post);
7274 /* Calculate offset. */
7275 gfc_add_modify (&body, offset,
7276 fold_build2_loc (input_location, PLUS_EXPR,
7277 gfc_array_index_type, offset, stride));
7278 /* Update stride. */
7279 gfc_add_modify (&body, stride,
7280 fold_build2_loc (input_location, MULT_EXPR,
7281 gfc_array_index_type, stride,
7282 fold_convert (gfc_array_index_type,
7283 shapese.expr)));
7284 /* Finish scalarization loop. */
7285 gfc_trans_scalarizing_loops (&loop, &body);
7286 gfc_add_block_to_block (&block, &loop.pre);
7287 gfc_add_block_to_block (&block, &loop.post);
7288 gfc_add_block_to_block (&block, &fptrse.post);
7289 gfc_cleanup_loop (&loop);
7291 gfc_add_modify (&block, offset,
7292 fold_build1_loc (input_location, NEGATE_EXPR,
7293 gfc_array_index_type, offset));
7294 gfc_conv_descriptor_offset_set (&block, desc, offset);
7296 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
7297 gfc_add_block_to_block (&se.pre, &se.post);
7298 return gfc_finish_block (&se.pre);
7302 /* Save and restore floating-point state. */
7304 tree
7305 gfc_save_fp_state (stmtblock_t *block)
7307 tree type, fpstate, tmp;
7309 type = build_array_type (char_type_node,
7310 build_range_type (size_type_node, size_zero_node,
7311 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
7312 fpstate = gfc_create_var (type, "fpstate");
7313 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
7315 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
7316 1, fpstate);
7317 gfc_add_expr_to_block (block, tmp);
7319 return fpstate;
7323 void
7324 gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
7326 tree tmp;
7328 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
7329 1, fpstate);
7330 gfc_add_expr_to_block (block, tmp);
7334 /* Generate code for arguments of IEEE functions. */
7336 static void
7337 conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
7338 int nargs)
7340 gfc_actual_arglist *actual;
7341 gfc_expr *e;
7342 gfc_se argse;
7343 int arg;
7345 actual = expr->value.function.actual;
7346 for (arg = 0; arg < nargs; arg++, actual = actual->next)
7348 gcc_assert (actual);
7349 e = actual->expr;
7351 gfc_init_se (&argse, se);
7352 gfc_conv_expr_val (&argse, e);
7354 gfc_add_block_to_block (&se->pre, &argse.pre);
7355 gfc_add_block_to_block (&se->post, &argse.post);
7356 argarray[arg] = argse.expr;
7361 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
7362 and IEEE_UNORDERED, which translate directly to GCC type-generic
7363 built-ins. */
7365 static void
7366 conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
7367 enum built_in_function code, int nargs)
7369 tree args[2];
7370 gcc_assert ((unsigned) nargs <= sizeof(args)/sizeof(args[0]));
7372 conv_ieee_function_args (se, expr, args, nargs);
7373 se->expr = build_call_expr_loc_array (input_location,
7374 builtin_decl_explicit (code),
7375 nargs, args);
7376 STRIP_TYPE_NOPS (se->expr);
7377 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7381 /* Generate code for IEEE_IS_NORMAL intrinsic:
7382 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
7384 static void
7385 conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
7387 tree arg, isnormal, iszero;
7389 /* Convert arg, evaluate it only once. */
7390 conv_ieee_function_args (se, expr, &arg, 1);
7391 arg = gfc_evaluate_now (arg, &se->pre);
7393 isnormal = build_call_expr_loc (input_location,
7394 builtin_decl_explicit (BUILT_IN_ISNORMAL),
7395 1, arg);
7396 iszero = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
7397 build_real_from_int_cst (TREE_TYPE (arg),
7398 integer_zero_node));
7399 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
7400 boolean_type_node, isnormal, iszero);
7401 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7405 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
7406 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
7408 static void
7409 conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
7411 tree arg, signbit, isnan, decl;
7412 int argprec;
7414 /* Convert arg, evaluate it only once. */
7415 conv_ieee_function_args (se, expr, &arg, 1);
7416 arg = gfc_evaluate_now (arg, &se->pre);
7418 isnan = build_call_expr_loc (input_location,
7419 builtin_decl_explicit (BUILT_IN_ISNAN),
7420 1, arg);
7421 STRIP_TYPE_NOPS (isnan);
7423 argprec = TYPE_PRECISION (TREE_TYPE (arg));
7424 decl = builtin_decl_for_precision (BUILT_IN_SIGNBIT, argprec);
7425 signbit = build_call_expr_loc (input_location, decl, 1, arg);
7426 signbit = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7427 signbit, integer_zero_node);
7429 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7430 boolean_type_node, signbit,
7431 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
7432 TREE_TYPE(isnan), isnan));
7434 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7438 /* Generate code for IEEE_LOGB and IEEE_RINT. */
7440 static void
7441 conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
7442 enum built_in_function code)
7444 tree arg, decl, call, fpstate;
7445 int argprec;
7447 conv_ieee_function_args (se, expr, &arg, 1);
7448 argprec = TYPE_PRECISION (TREE_TYPE (arg));
7449 decl = builtin_decl_for_precision (code, argprec);
7451 /* Save floating-point state. */
7452 fpstate = gfc_save_fp_state (&se->pre);
7454 /* Make the function call. */
7455 call = build_call_expr_loc (input_location, decl, 1, arg);
7456 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
7458 /* Restore floating-point state. */
7459 gfc_restore_fp_state (&se->post, fpstate);
7463 /* Generate code for IEEE_REM. */
7465 static void
7466 conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
7468 tree args[2], decl, call, fpstate;
7469 int argprec;
7471 conv_ieee_function_args (se, expr, args, 2);
7473 /* If arguments have unequal size, convert them to the larger. */
7474 if (TYPE_PRECISION (TREE_TYPE (args[0]))
7475 > TYPE_PRECISION (TREE_TYPE (args[1])))
7476 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
7477 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
7478 > TYPE_PRECISION (TREE_TYPE (args[0])))
7479 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
7481 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
7482 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
7484 /* Save floating-point state. */
7485 fpstate = gfc_save_fp_state (&se->pre);
7487 /* Make the function call. */
7488 call = build_call_expr_loc_array (input_location, decl, 2, args);
7489 se->expr = fold_convert (TREE_TYPE (args[0]), call);
7491 /* Restore floating-point state. */
7492 gfc_restore_fp_state (&se->post, fpstate);
7496 /* Generate code for IEEE_NEXT_AFTER. */
7498 static void
7499 conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
7501 tree args[2], decl, call, fpstate;
7502 int argprec;
7504 conv_ieee_function_args (se, expr, args, 2);
7506 /* Result has the characteristics of first argument. */
7507 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
7508 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
7509 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
7511 /* Save floating-point state. */
7512 fpstate = gfc_save_fp_state (&se->pre);
7514 /* Make the function call. */
7515 call = build_call_expr_loc_array (input_location, decl, 2, args);
7516 se->expr = fold_convert (TREE_TYPE (args[0]), call);
7518 /* Restore floating-point state. */
7519 gfc_restore_fp_state (&se->post, fpstate);
7523 /* Generate code for IEEE_SCALB. */
7525 static void
7526 conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
7528 tree args[2], decl, call, huge, type;
7529 int argprec, n;
7531 conv_ieee_function_args (se, expr, args, 2);
7533 /* Result has the characteristics of first argument. */
7534 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
7535 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
7537 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
7539 /* We need to fold the integer into the range of a C int. */
7540 args[1] = gfc_evaluate_now (args[1], &se->pre);
7541 type = TREE_TYPE (args[1]);
7543 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
7544 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
7545 gfc_c_int_kind);
7546 huge = fold_convert (type, huge);
7547 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
7548 huge);
7549 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
7550 fold_build1_loc (input_location, NEGATE_EXPR,
7551 type, huge));
7554 args[1] = fold_convert (integer_type_node, args[1]);
7556 /* Make the function call. */
7557 call = build_call_expr_loc_array (input_location, decl, 2, args);
7558 se->expr = fold_convert (TREE_TYPE (args[0]), call);
7562 /* Generate code for IEEE_COPY_SIGN. */
7564 static void
7565 conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
7567 tree args[2], decl, sign;
7568 int argprec;
7570 conv_ieee_function_args (se, expr, args, 2);
7572 /* Get the sign of the second argument. */
7573 argprec = TYPE_PRECISION (TREE_TYPE (args[1]));
7574 decl = builtin_decl_for_precision (BUILT_IN_SIGNBIT, argprec);
7575 sign = build_call_expr_loc (input_location, decl, 1, args[1]);
7576 sign = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7577 sign, integer_zero_node);
7579 /* Create a value of one, with the right sign. */
7580 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
7581 sign,
7582 fold_build1_loc (input_location, NEGATE_EXPR,
7583 integer_type_node,
7584 integer_one_node),
7585 integer_one_node);
7586 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
7588 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
7589 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
7591 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
7595 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
7596 module. */
7598 bool
7599 gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
7601 const char *name = expr->value.function.name;
7603 #define STARTS_WITH(A,B) (strncmp((A), (B), strlen(B)) == 0)
7605 if (STARTS_WITH (name, "_gfortran_ieee_is_nan"))
7606 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
7607 else if (STARTS_WITH (name, "_gfortran_ieee_is_finite"))
7608 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
7609 else if (STARTS_WITH (name, "_gfortran_ieee_unordered"))
7610 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
7611 else if (STARTS_WITH (name, "_gfortran_ieee_is_normal"))
7612 conv_intrinsic_ieee_is_normal (se, expr);
7613 else if (STARTS_WITH (name, "_gfortran_ieee_is_negative"))
7614 conv_intrinsic_ieee_is_negative (se, expr);
7615 else if (STARTS_WITH (name, "_gfortran_ieee_copy_sign"))
7616 conv_intrinsic_ieee_copy_sign (se, expr);
7617 else if (STARTS_WITH (name, "_gfortran_ieee_scalb"))
7618 conv_intrinsic_ieee_scalb (se, expr);
7619 else if (STARTS_WITH (name, "_gfortran_ieee_next_after"))
7620 conv_intrinsic_ieee_next_after (se, expr);
7621 else if (STARTS_WITH (name, "_gfortran_ieee_rem"))
7622 conv_intrinsic_ieee_rem (se, expr);
7623 else if (STARTS_WITH (name, "_gfortran_ieee_logb"))
7624 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
7625 else if (STARTS_WITH (name, "_gfortran_ieee_rint"))
7626 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
7627 else
7628 /* It is not among the functions we translate directly. We return
7629 false, so a library function call is emitted. */
7630 return false;
7632 #undef STARTS_WITH
7634 return true;
7638 /* Generate code for an intrinsic function. Some map directly to library
7639 calls, others get special handling. In some cases the name of the function
7640 used depends on the type specifiers. */
7642 void
7643 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
7645 const char *name;
7646 int lib, kind;
7647 tree fndecl;
7649 name = &expr->value.function.name[2];
7651 if (expr->rank > 0)
7653 lib = gfc_is_intrinsic_libcall (expr);
7654 if (lib != 0)
7656 if (lib == 1)
7657 se->ignore_optional = 1;
7659 switch (expr->value.function.isym->id)
7661 case GFC_ISYM_EOSHIFT:
7662 case GFC_ISYM_PACK:
7663 case GFC_ISYM_RESHAPE:
7664 /* For all of those the first argument specifies the type and the
7665 third is optional. */
7666 conv_generic_with_optional_char_arg (se, expr, 1, 3);
7667 break;
7669 default:
7670 gfc_conv_intrinsic_funcall (se, expr);
7671 break;
7674 return;
7678 switch (expr->value.function.isym->id)
7680 case GFC_ISYM_NONE:
7681 gcc_unreachable ();
7683 case GFC_ISYM_REPEAT:
7684 gfc_conv_intrinsic_repeat (se, expr);
7685 break;
7687 case GFC_ISYM_TRIM:
7688 gfc_conv_intrinsic_trim (se, expr);
7689 break;
7691 case GFC_ISYM_SC_KIND:
7692 gfc_conv_intrinsic_sc_kind (se, expr);
7693 break;
7695 case GFC_ISYM_SI_KIND:
7696 gfc_conv_intrinsic_si_kind (se, expr);
7697 break;
7699 case GFC_ISYM_SR_KIND:
7700 gfc_conv_intrinsic_sr_kind (se, expr);
7701 break;
7703 case GFC_ISYM_EXPONENT:
7704 gfc_conv_intrinsic_exponent (se, expr);
7705 break;
7707 case GFC_ISYM_SCAN:
7708 kind = expr->value.function.actual->expr->ts.kind;
7709 if (kind == 1)
7710 fndecl = gfor_fndecl_string_scan;
7711 else if (kind == 4)
7712 fndecl = gfor_fndecl_string_scan_char4;
7713 else
7714 gcc_unreachable ();
7716 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
7717 break;
7719 case GFC_ISYM_VERIFY:
7720 kind = expr->value.function.actual->expr->ts.kind;
7721 if (kind == 1)
7722 fndecl = gfor_fndecl_string_verify;
7723 else if (kind == 4)
7724 fndecl = gfor_fndecl_string_verify_char4;
7725 else
7726 gcc_unreachable ();
7728 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
7729 break;
7731 case GFC_ISYM_ALLOCATED:
7732 gfc_conv_allocated (se, expr);
7733 break;
7735 case GFC_ISYM_ASSOCIATED:
7736 gfc_conv_associated(se, expr);
7737 break;
7739 case GFC_ISYM_SAME_TYPE_AS:
7740 gfc_conv_same_type_as (se, expr);
7741 break;
7743 case GFC_ISYM_ABS:
7744 gfc_conv_intrinsic_abs (se, expr);
7745 break;
7747 case GFC_ISYM_ADJUSTL:
7748 if (expr->ts.kind == 1)
7749 fndecl = gfor_fndecl_adjustl;
7750 else if (expr->ts.kind == 4)
7751 fndecl = gfor_fndecl_adjustl_char4;
7752 else
7753 gcc_unreachable ();
7755 gfc_conv_intrinsic_adjust (se, expr, fndecl);
7756 break;
7758 case GFC_ISYM_ADJUSTR:
7759 if (expr->ts.kind == 1)
7760 fndecl = gfor_fndecl_adjustr;
7761 else if (expr->ts.kind == 4)
7762 fndecl = gfor_fndecl_adjustr_char4;
7763 else
7764 gcc_unreachable ();
7766 gfc_conv_intrinsic_adjust (se, expr, fndecl);
7767 break;
7769 case GFC_ISYM_AIMAG:
7770 gfc_conv_intrinsic_imagpart (se, expr);
7771 break;
7773 case GFC_ISYM_AINT:
7774 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
7775 break;
7777 case GFC_ISYM_ALL:
7778 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
7779 break;
7781 case GFC_ISYM_ANINT:
7782 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
7783 break;
7785 case GFC_ISYM_AND:
7786 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
7787 break;
7789 case GFC_ISYM_ANY:
7790 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
7791 break;
7793 case GFC_ISYM_BTEST:
7794 gfc_conv_intrinsic_btest (se, expr);
7795 break;
7797 case GFC_ISYM_BGE:
7798 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
7799 break;
7801 case GFC_ISYM_BGT:
7802 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
7803 break;
7805 case GFC_ISYM_BLE:
7806 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
7807 break;
7809 case GFC_ISYM_BLT:
7810 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
7811 break;
7813 case GFC_ISYM_C_ASSOCIATED:
7814 case GFC_ISYM_C_FUNLOC:
7815 case GFC_ISYM_C_LOC:
7816 conv_isocbinding_function (se, expr);
7817 break;
7819 case GFC_ISYM_ACHAR:
7820 case GFC_ISYM_CHAR:
7821 gfc_conv_intrinsic_char (se, expr);
7822 break;
7824 case GFC_ISYM_CONVERSION:
7825 case GFC_ISYM_REAL:
7826 case GFC_ISYM_LOGICAL:
7827 case GFC_ISYM_DBLE:
7828 gfc_conv_intrinsic_conversion (se, expr);
7829 break;
7831 /* Integer conversions are handled separately to make sure we get the
7832 correct rounding mode. */
7833 case GFC_ISYM_INT:
7834 case GFC_ISYM_INT2:
7835 case GFC_ISYM_INT8:
7836 case GFC_ISYM_LONG:
7837 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
7838 break;
7840 case GFC_ISYM_NINT:
7841 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
7842 break;
7844 case GFC_ISYM_CEILING:
7845 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
7846 break;
7848 case GFC_ISYM_FLOOR:
7849 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
7850 break;
7852 case GFC_ISYM_MOD:
7853 gfc_conv_intrinsic_mod (se, expr, 0);
7854 break;
7856 case GFC_ISYM_MODULO:
7857 gfc_conv_intrinsic_mod (se, expr, 1);
7858 break;
7860 case GFC_ISYM_CAF_GET:
7861 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE);
7862 break;
7864 case GFC_ISYM_CMPLX:
7865 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
7866 break;
7868 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
7869 gfc_conv_intrinsic_iargc (se, expr);
7870 break;
7872 case GFC_ISYM_COMPLEX:
7873 gfc_conv_intrinsic_cmplx (se, expr, 1);
7874 break;
7876 case GFC_ISYM_CONJG:
7877 gfc_conv_intrinsic_conjg (se, expr);
7878 break;
7880 case GFC_ISYM_COUNT:
7881 gfc_conv_intrinsic_count (se, expr);
7882 break;
7884 case GFC_ISYM_CTIME:
7885 gfc_conv_intrinsic_ctime (se, expr);
7886 break;
7888 case GFC_ISYM_DIM:
7889 gfc_conv_intrinsic_dim (se, expr);
7890 break;
7892 case GFC_ISYM_DOT_PRODUCT:
7893 gfc_conv_intrinsic_dot_product (se, expr);
7894 break;
7896 case GFC_ISYM_DPROD:
7897 gfc_conv_intrinsic_dprod (se, expr);
7898 break;
7900 case GFC_ISYM_DSHIFTL:
7901 gfc_conv_intrinsic_dshift (se, expr, true);
7902 break;
7904 case GFC_ISYM_DSHIFTR:
7905 gfc_conv_intrinsic_dshift (se, expr, false);
7906 break;
7908 case GFC_ISYM_FDATE:
7909 gfc_conv_intrinsic_fdate (se, expr);
7910 break;
7912 case GFC_ISYM_FRACTION:
7913 gfc_conv_intrinsic_fraction (se, expr);
7914 break;
7916 case GFC_ISYM_IALL:
7917 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
7918 break;
7920 case GFC_ISYM_IAND:
7921 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
7922 break;
7924 case GFC_ISYM_IANY:
7925 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
7926 break;
7928 case GFC_ISYM_IBCLR:
7929 gfc_conv_intrinsic_singlebitop (se, expr, 0);
7930 break;
7932 case GFC_ISYM_IBITS:
7933 gfc_conv_intrinsic_ibits (se, expr);
7934 break;
7936 case GFC_ISYM_IBSET:
7937 gfc_conv_intrinsic_singlebitop (se, expr, 1);
7938 break;
7940 case GFC_ISYM_IACHAR:
7941 case GFC_ISYM_ICHAR:
7942 /* We assume ASCII character sequence. */
7943 gfc_conv_intrinsic_ichar (se, expr);
7944 break;
7946 case GFC_ISYM_IARGC:
7947 gfc_conv_intrinsic_iargc (se, expr);
7948 break;
7950 case GFC_ISYM_IEOR:
7951 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
7952 break;
7954 case GFC_ISYM_INDEX:
7955 kind = expr->value.function.actual->expr->ts.kind;
7956 if (kind == 1)
7957 fndecl = gfor_fndecl_string_index;
7958 else if (kind == 4)
7959 fndecl = gfor_fndecl_string_index_char4;
7960 else
7961 gcc_unreachable ();
7963 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
7964 break;
7966 case GFC_ISYM_IOR:
7967 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
7968 break;
7970 case GFC_ISYM_IPARITY:
7971 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
7972 break;
7974 case GFC_ISYM_IS_IOSTAT_END:
7975 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
7976 break;
7978 case GFC_ISYM_IS_IOSTAT_EOR:
7979 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
7980 break;
7982 case GFC_ISYM_ISNAN:
7983 gfc_conv_intrinsic_isnan (se, expr);
7984 break;
7986 case GFC_ISYM_LSHIFT:
7987 gfc_conv_intrinsic_shift (se, expr, false, false);
7988 break;
7990 case GFC_ISYM_RSHIFT:
7991 gfc_conv_intrinsic_shift (se, expr, true, true);
7992 break;
7994 case GFC_ISYM_SHIFTA:
7995 gfc_conv_intrinsic_shift (se, expr, true, true);
7996 break;
7998 case GFC_ISYM_SHIFTL:
7999 gfc_conv_intrinsic_shift (se, expr, false, false);
8000 break;
8002 case GFC_ISYM_SHIFTR:
8003 gfc_conv_intrinsic_shift (se, expr, true, false);
8004 break;
8006 case GFC_ISYM_ISHFT:
8007 gfc_conv_intrinsic_ishft (se, expr);
8008 break;
8010 case GFC_ISYM_ISHFTC:
8011 gfc_conv_intrinsic_ishftc (se, expr);
8012 break;
8014 case GFC_ISYM_LEADZ:
8015 gfc_conv_intrinsic_leadz (se, expr);
8016 break;
8018 case GFC_ISYM_TRAILZ:
8019 gfc_conv_intrinsic_trailz (se, expr);
8020 break;
8022 case GFC_ISYM_POPCNT:
8023 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
8024 break;
8026 case GFC_ISYM_POPPAR:
8027 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
8028 break;
8030 case GFC_ISYM_LBOUND:
8031 gfc_conv_intrinsic_bound (se, expr, 0);
8032 break;
8034 case GFC_ISYM_LCOBOUND:
8035 conv_intrinsic_cobound (se, expr);
8036 break;
8038 case GFC_ISYM_TRANSPOSE:
8039 /* The scalarizer has already been set up for reversed dimension access
8040 order ; now we just get the argument value normally. */
8041 gfc_conv_expr (se, expr->value.function.actual->expr);
8042 break;
8044 case GFC_ISYM_LEN:
8045 gfc_conv_intrinsic_len (se, expr);
8046 break;
8048 case GFC_ISYM_LEN_TRIM:
8049 gfc_conv_intrinsic_len_trim (se, expr);
8050 break;
8052 case GFC_ISYM_LGE:
8053 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
8054 break;
8056 case GFC_ISYM_LGT:
8057 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
8058 break;
8060 case GFC_ISYM_LLE:
8061 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
8062 break;
8064 case GFC_ISYM_LLT:
8065 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
8066 break;
8068 case GFC_ISYM_MASKL:
8069 gfc_conv_intrinsic_mask (se, expr, 1);
8070 break;
8072 case GFC_ISYM_MASKR:
8073 gfc_conv_intrinsic_mask (se, expr, 0);
8074 break;
8076 case GFC_ISYM_MAX:
8077 if (expr->ts.type == BT_CHARACTER)
8078 gfc_conv_intrinsic_minmax_char (se, expr, 1);
8079 else
8080 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
8081 break;
8083 case GFC_ISYM_MAXLOC:
8084 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
8085 break;
8087 case GFC_ISYM_MAXVAL:
8088 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
8089 break;
8091 case GFC_ISYM_MERGE:
8092 gfc_conv_intrinsic_merge (se, expr);
8093 break;
8095 case GFC_ISYM_MERGE_BITS:
8096 gfc_conv_intrinsic_merge_bits (se, expr);
8097 break;
8099 case GFC_ISYM_MIN:
8100 if (expr->ts.type == BT_CHARACTER)
8101 gfc_conv_intrinsic_minmax_char (se, expr, -1);
8102 else
8103 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
8104 break;
8106 case GFC_ISYM_MINLOC:
8107 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
8108 break;
8110 case GFC_ISYM_MINVAL:
8111 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
8112 break;
8114 case GFC_ISYM_NEAREST:
8115 gfc_conv_intrinsic_nearest (se, expr);
8116 break;
8118 case GFC_ISYM_NORM2:
8119 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
8120 break;
8122 case GFC_ISYM_NOT:
8123 gfc_conv_intrinsic_not (se, expr);
8124 break;
8126 case GFC_ISYM_OR:
8127 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
8128 break;
8130 case GFC_ISYM_PARITY:
8131 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
8132 break;
8134 case GFC_ISYM_PRESENT:
8135 gfc_conv_intrinsic_present (se, expr);
8136 break;
8138 case GFC_ISYM_PRODUCT:
8139 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
8140 break;
8142 case GFC_ISYM_RANK:
8143 gfc_conv_intrinsic_rank (se, expr);
8144 break;
8146 case GFC_ISYM_RRSPACING:
8147 gfc_conv_intrinsic_rrspacing (se, expr);
8148 break;
8150 case GFC_ISYM_SET_EXPONENT:
8151 gfc_conv_intrinsic_set_exponent (se, expr);
8152 break;
8154 case GFC_ISYM_SCALE:
8155 gfc_conv_intrinsic_scale (se, expr);
8156 break;
8158 case GFC_ISYM_SIGN:
8159 gfc_conv_intrinsic_sign (se, expr);
8160 break;
8162 case GFC_ISYM_SIZE:
8163 gfc_conv_intrinsic_size (se, expr);
8164 break;
8166 case GFC_ISYM_SIZEOF:
8167 case GFC_ISYM_C_SIZEOF:
8168 gfc_conv_intrinsic_sizeof (se, expr);
8169 break;
8171 case GFC_ISYM_STORAGE_SIZE:
8172 gfc_conv_intrinsic_storage_size (se, expr);
8173 break;
8175 case GFC_ISYM_SPACING:
8176 gfc_conv_intrinsic_spacing (se, expr);
8177 break;
8179 case GFC_ISYM_STRIDE:
8180 conv_intrinsic_stride (se, expr);
8181 break;
8183 case GFC_ISYM_SUM:
8184 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
8185 break;
8187 case GFC_ISYM_TRANSFER:
8188 if (se->ss && se->ss->info->useflags)
8189 /* Access the previously obtained result. */
8190 gfc_conv_tmp_array_ref (se);
8191 else
8192 gfc_conv_intrinsic_transfer (se, expr);
8193 break;
8195 case GFC_ISYM_TTYNAM:
8196 gfc_conv_intrinsic_ttynam (se, expr);
8197 break;
8199 case GFC_ISYM_UBOUND:
8200 gfc_conv_intrinsic_bound (se, expr, 1);
8201 break;
8203 case GFC_ISYM_UCOBOUND:
8204 conv_intrinsic_cobound (se, expr);
8205 break;
8207 case GFC_ISYM_XOR:
8208 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
8209 break;
8211 case GFC_ISYM_LOC:
8212 gfc_conv_intrinsic_loc (se, expr);
8213 break;
8215 case GFC_ISYM_THIS_IMAGE:
8216 /* For num_images() == 1, handle as LCOBOUND. */
8217 if (expr->value.function.actual->expr
8218 && flag_coarray == GFC_FCOARRAY_SINGLE)
8219 conv_intrinsic_cobound (se, expr);
8220 else
8221 trans_this_image (se, expr);
8222 break;
8224 case GFC_ISYM_IMAGE_INDEX:
8225 trans_image_index (se, expr);
8226 break;
8228 case GFC_ISYM_NUM_IMAGES:
8229 trans_num_images (se, expr);
8230 break;
8232 case GFC_ISYM_ACCESS:
8233 case GFC_ISYM_CHDIR:
8234 case GFC_ISYM_CHMOD:
8235 case GFC_ISYM_DTIME:
8236 case GFC_ISYM_ETIME:
8237 case GFC_ISYM_EXTENDS_TYPE_OF:
8238 case GFC_ISYM_FGET:
8239 case GFC_ISYM_FGETC:
8240 case GFC_ISYM_FNUM:
8241 case GFC_ISYM_FPUT:
8242 case GFC_ISYM_FPUTC:
8243 case GFC_ISYM_FSTAT:
8244 case GFC_ISYM_FTELL:
8245 case GFC_ISYM_GETCWD:
8246 case GFC_ISYM_GETGID:
8247 case GFC_ISYM_GETPID:
8248 case GFC_ISYM_GETUID:
8249 case GFC_ISYM_HOSTNM:
8250 case GFC_ISYM_KILL:
8251 case GFC_ISYM_IERRNO:
8252 case GFC_ISYM_IRAND:
8253 case GFC_ISYM_ISATTY:
8254 case GFC_ISYM_JN2:
8255 case GFC_ISYM_LINK:
8256 case GFC_ISYM_LSTAT:
8257 case GFC_ISYM_MALLOC:
8258 case GFC_ISYM_MATMUL:
8259 case GFC_ISYM_MCLOCK:
8260 case GFC_ISYM_MCLOCK8:
8261 case GFC_ISYM_RAND:
8262 case GFC_ISYM_RENAME:
8263 case GFC_ISYM_SECOND:
8264 case GFC_ISYM_SECNDS:
8265 case GFC_ISYM_SIGNAL:
8266 case GFC_ISYM_STAT:
8267 case GFC_ISYM_SYMLNK:
8268 case GFC_ISYM_SYSTEM:
8269 case GFC_ISYM_TIME:
8270 case GFC_ISYM_TIME8:
8271 case GFC_ISYM_UMASK:
8272 case GFC_ISYM_UNLINK:
8273 case GFC_ISYM_YN2:
8274 gfc_conv_intrinsic_funcall (se, expr);
8275 break;
8277 case GFC_ISYM_EOSHIFT:
8278 case GFC_ISYM_PACK:
8279 case GFC_ISYM_RESHAPE:
8280 /* For those, expr->rank should always be >0 and thus the if above the
8281 switch should have matched. */
8282 gcc_unreachable ();
8283 break;
8285 default:
8286 gfc_conv_intrinsic_lib_function (se, expr);
8287 break;
8292 static gfc_ss *
8293 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
8295 gfc_ss *arg_ss, *tmp_ss;
8296 gfc_actual_arglist *arg;
8298 arg = expr->value.function.actual;
8300 gcc_assert (arg->expr);
8302 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
8303 gcc_assert (arg_ss != gfc_ss_terminator);
8305 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
8307 if (tmp_ss->info->type != GFC_SS_SCALAR
8308 && tmp_ss->info->type != GFC_SS_REFERENCE)
8310 int tmp_dim;
8312 gcc_assert (tmp_ss->dimen == 2);
8314 /* We just invert dimensions. */
8315 tmp_dim = tmp_ss->dim[0];
8316 tmp_ss->dim[0] = tmp_ss->dim[1];
8317 tmp_ss->dim[1] = tmp_dim;
8320 /* Stop when tmp_ss points to the last valid element of the chain... */
8321 if (tmp_ss->next == gfc_ss_terminator)
8322 break;
8325 /* ... so that we can attach the rest of the chain to it. */
8326 tmp_ss->next = ss;
8328 return arg_ss;
8332 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
8333 This has the side effect of reversing the nested list, so there is no
8334 need to call gfc_reverse_ss on it (the given list is assumed not to be
8335 reversed yet). */
8337 static gfc_ss *
8338 nest_loop_dimension (gfc_ss *ss, int dim)
8340 int ss_dim, i;
8341 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
8342 gfc_loopinfo *new_loop;
8344 gcc_assert (ss != gfc_ss_terminator);
8346 for (; ss != gfc_ss_terminator; ss = ss->next)
8348 new_ss = gfc_get_ss ();
8349 new_ss->next = prev_ss;
8350 new_ss->parent = ss;
8351 new_ss->info = ss->info;
8352 new_ss->info->refcount++;
8353 if (ss->dimen != 0)
8355 gcc_assert (ss->info->type != GFC_SS_SCALAR
8356 && ss->info->type != GFC_SS_REFERENCE);
8358 new_ss->dimen = 1;
8359 new_ss->dim[0] = ss->dim[dim];
8361 gcc_assert (dim < ss->dimen);
8363 ss_dim = --ss->dimen;
8364 for (i = dim; i < ss_dim; i++)
8365 ss->dim[i] = ss->dim[i + 1];
8367 ss->dim[ss_dim] = 0;
8369 prev_ss = new_ss;
8371 if (ss->nested_ss)
8373 ss->nested_ss->parent = new_ss;
8374 new_ss->nested_ss = ss->nested_ss;
8376 ss->nested_ss = new_ss;
8379 new_loop = gfc_get_loopinfo ();
8380 gfc_init_loopinfo (new_loop);
8382 gcc_assert (prev_ss != NULL);
8383 gcc_assert (prev_ss != gfc_ss_terminator);
8384 gfc_add_ss_to_loop (new_loop, prev_ss);
8385 return new_ss->parent;
8389 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
8390 is to be inlined. */
8392 static gfc_ss *
8393 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
8395 gfc_ss *tmp_ss, *tail, *array_ss;
8396 gfc_actual_arglist *arg1, *arg2, *arg3;
8397 int sum_dim;
8398 bool scalar_mask = false;
8400 /* The rank of the result will be determined later. */
8401 arg1 = expr->value.function.actual;
8402 arg2 = arg1->next;
8403 arg3 = arg2->next;
8404 gcc_assert (arg3 != NULL);
8406 if (expr->rank == 0)
8407 return ss;
8409 tmp_ss = gfc_ss_terminator;
8411 if (arg3->expr)
8413 gfc_ss *mask_ss;
8415 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
8416 if (mask_ss == tmp_ss)
8417 scalar_mask = 1;
8419 tmp_ss = mask_ss;
8422 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
8423 gcc_assert (array_ss != tmp_ss);
8425 /* Odd thing: If the mask is scalar, it is used by the frontend after
8426 the array (to make an if around the nested loop). Thus it shall
8427 be after array_ss once the gfc_ss list is reversed. */
8428 if (scalar_mask)
8429 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
8430 else
8431 tmp_ss = array_ss;
8433 /* "Hide" the dimension on which we will sum in the first arg's scalarization
8434 chain. */
8435 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
8436 tail = nest_loop_dimension (tmp_ss, sum_dim);
8437 tail->next = ss;
8439 return tmp_ss;
8443 static gfc_ss *
8444 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
8447 switch (expr->value.function.isym->id)
8449 case GFC_ISYM_PRODUCT:
8450 case GFC_ISYM_SUM:
8451 return walk_inline_intrinsic_arith (ss, expr);
8453 case GFC_ISYM_TRANSPOSE:
8454 return walk_inline_intrinsic_transpose (ss, expr);
8456 default:
8457 gcc_unreachable ();
8459 gcc_unreachable ();
8463 /* This generates code to execute before entering the scalarization loop.
8464 Currently does nothing. */
8466 void
8467 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
8469 switch (ss->info->expr->value.function.isym->id)
8471 case GFC_ISYM_UBOUND:
8472 case GFC_ISYM_LBOUND:
8473 case GFC_ISYM_UCOBOUND:
8474 case GFC_ISYM_LCOBOUND:
8475 case GFC_ISYM_THIS_IMAGE:
8476 break;
8478 default:
8479 gcc_unreachable ();
8484 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
8485 are expanded into code inside the scalarization loop. */
8487 static gfc_ss *
8488 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
8490 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
8491 gfc_add_class_array_ref (expr->value.function.actual->expr);
8493 /* The two argument version returns a scalar. */
8494 if (expr->value.function.actual->next->expr)
8495 return ss;
8497 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
8501 /* Walk an intrinsic array libcall. */
8503 static gfc_ss *
8504 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
8506 gcc_assert (expr->rank > 0);
8507 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
8511 /* Return whether the function call expression EXPR will be expanded
8512 inline by gfc_conv_intrinsic_function. */
8514 bool
8515 gfc_inline_intrinsic_function_p (gfc_expr *expr)
8517 gfc_actual_arglist *args;
8519 if (!expr->value.function.isym)
8520 return false;
8522 switch (expr->value.function.isym->id)
8524 case GFC_ISYM_PRODUCT:
8525 case GFC_ISYM_SUM:
8526 /* Disable inline expansion if code size matters. */
8527 if (optimize_size)
8528 return false;
8530 args = expr->value.function.actual;
8531 /* We need to be able to subset the SUM argument at compile-time. */
8532 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
8533 return false;
8535 return true;
8537 case GFC_ISYM_TRANSPOSE:
8538 return true;
8540 default:
8541 return false;
8546 /* Returns nonzero if the specified intrinsic function call maps directly to
8547 an external library call. Should only be used for functions that return
8548 arrays. */
8551 gfc_is_intrinsic_libcall (gfc_expr * expr)
8553 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
8554 gcc_assert (expr->rank > 0);
8556 if (gfc_inline_intrinsic_function_p (expr))
8557 return 0;
8559 switch (expr->value.function.isym->id)
8561 case GFC_ISYM_ALL:
8562 case GFC_ISYM_ANY:
8563 case GFC_ISYM_COUNT:
8564 case GFC_ISYM_JN2:
8565 case GFC_ISYM_IANY:
8566 case GFC_ISYM_IALL:
8567 case GFC_ISYM_IPARITY:
8568 case GFC_ISYM_MATMUL:
8569 case GFC_ISYM_MAXLOC:
8570 case GFC_ISYM_MAXVAL:
8571 case GFC_ISYM_MINLOC:
8572 case GFC_ISYM_MINVAL:
8573 case GFC_ISYM_NORM2:
8574 case GFC_ISYM_PARITY:
8575 case GFC_ISYM_PRODUCT:
8576 case GFC_ISYM_SUM:
8577 case GFC_ISYM_SHAPE:
8578 case GFC_ISYM_SPREAD:
8579 case GFC_ISYM_YN2:
8580 /* Ignore absent optional parameters. */
8581 return 1;
8583 case GFC_ISYM_RESHAPE:
8584 case GFC_ISYM_CSHIFT:
8585 case GFC_ISYM_EOSHIFT:
8586 case GFC_ISYM_PACK:
8587 case GFC_ISYM_UNPACK:
8588 /* Pass absent optional parameters. */
8589 return 2;
8591 default:
8592 return 0;
8596 /* Walk an intrinsic function. */
8597 gfc_ss *
8598 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
8599 gfc_intrinsic_sym * isym)
8601 gcc_assert (isym);
8603 if (isym->elemental)
8604 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
8605 NULL, GFC_SS_SCALAR);
8607 if (expr->rank == 0)
8608 return ss;
8610 if (gfc_inline_intrinsic_function_p (expr))
8611 return walk_inline_intrinsic_function (ss, expr);
8613 if (gfc_is_intrinsic_libcall (expr))
8614 return gfc_walk_intrinsic_libfunc (ss, expr);
8616 /* Special cases. */
8617 switch (isym->id)
8619 case GFC_ISYM_LBOUND:
8620 case GFC_ISYM_LCOBOUND:
8621 case GFC_ISYM_UBOUND:
8622 case GFC_ISYM_UCOBOUND:
8623 case GFC_ISYM_THIS_IMAGE:
8624 return gfc_walk_intrinsic_bound (ss, expr);
8626 case GFC_ISYM_TRANSFER:
8627 case GFC_ISYM_CAF_GET:
8628 return gfc_walk_intrinsic_libfunc (ss, expr);
8630 default:
8631 /* This probably meant someone forgot to add an intrinsic to the above
8632 list(s) when they implemented it, or something's gone horribly
8633 wrong. */
8634 gcc_unreachable ();
8639 static tree
8640 conv_co_collective (gfc_code *code)
8642 gfc_se argse;
8643 stmtblock_t block, post_block;
8644 tree fndecl, array, strlen, image_index, stat, errmsg, errmsg_len;
8645 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
8647 gfc_start_block (&block);
8648 gfc_init_block (&post_block);
8650 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
8652 opr_expr = code->ext.actual->next->expr;
8653 image_idx_expr = code->ext.actual->next->next->expr;
8654 stat_expr = code->ext.actual->next->next->next->expr;
8655 errmsg_expr = code->ext.actual->next->next->next->next->expr;
8657 else
8659 opr_expr = NULL;
8660 image_idx_expr = code->ext.actual->next->expr;
8661 stat_expr = code->ext.actual->next->next->expr;
8662 errmsg_expr = code->ext.actual->next->next->next->expr;
8665 /* stat. */
8666 if (stat_expr)
8668 gfc_init_se (&argse, NULL);
8669 gfc_conv_expr (&argse, stat_expr);
8670 gfc_add_block_to_block (&block, &argse.pre);
8671 gfc_add_block_to_block (&post_block, &argse.post);
8672 stat = argse.expr;
8673 if (flag_coarray != GFC_FCOARRAY_SINGLE)
8674 stat = gfc_build_addr_expr (NULL_TREE, stat);
8676 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
8677 stat = NULL_TREE;
8678 else
8679 stat = null_pointer_node;
8681 /* Early exit for GFC_FCOARRAY_SINGLE. */
8682 if (flag_coarray == GFC_FCOARRAY_SINGLE)
8684 if (stat != NULL_TREE)
8685 gfc_add_modify (&block, stat,
8686 fold_convert (TREE_TYPE (stat), integer_zero_node));
8687 return gfc_finish_block (&block);
8690 /* Handle the array. */
8691 gfc_init_se (&argse, NULL);
8692 if (code->ext.actual->expr->rank == 0)
8694 symbol_attribute attr;
8695 gfc_clear_attr (&attr);
8696 gfc_init_se (&argse, NULL);
8697 gfc_conv_expr (&argse, code->ext.actual->expr);
8698 gfc_add_block_to_block (&block, &argse.pre);
8699 gfc_add_block_to_block (&post_block, &argse.post);
8700 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
8701 array = gfc_build_addr_expr (NULL_TREE, array);
8703 else
8705 argse.want_pointer = 1;
8706 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
8707 array = argse.expr;
8709 gfc_add_block_to_block (&block, &argse.pre);
8710 gfc_add_block_to_block (&post_block, &argse.post);
8712 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
8713 strlen = argse.string_length;
8714 else
8715 strlen = integer_zero_node;
8717 /* image_index. */
8718 if (image_idx_expr)
8720 gfc_init_se (&argse, NULL);
8721 gfc_conv_expr (&argse, image_idx_expr);
8722 gfc_add_block_to_block (&block, &argse.pre);
8723 gfc_add_block_to_block (&post_block, &argse.post);
8724 image_index = fold_convert (integer_type_node, argse.expr);
8726 else
8727 image_index = integer_zero_node;
8729 /* errmsg. */
8730 if (errmsg_expr)
8732 gfc_init_se (&argse, NULL);
8733 gfc_conv_expr (&argse, errmsg_expr);
8734 gfc_add_block_to_block (&block, &argse.pre);
8735 gfc_add_block_to_block (&post_block, &argse.post);
8736 errmsg = argse.expr;
8737 errmsg_len = fold_convert (integer_type_node, argse.string_length);
8739 else
8741 errmsg = null_pointer_node;
8742 errmsg_len = integer_zero_node;
8745 /* Generate the function call. */
8746 switch (code->resolved_isym->id)
8748 case GFC_ISYM_CO_BROADCAST:
8749 fndecl = gfor_fndecl_co_broadcast;
8750 break;
8751 case GFC_ISYM_CO_MAX:
8752 fndecl = gfor_fndecl_co_max;
8753 break;
8754 case GFC_ISYM_CO_MIN:
8755 fndecl = gfor_fndecl_co_min;
8756 break;
8757 case GFC_ISYM_CO_REDUCE:
8758 fndecl = gfor_fndecl_co_reduce;
8759 break;
8760 case GFC_ISYM_CO_SUM:
8761 fndecl = gfor_fndecl_co_sum;
8762 break;
8763 default:
8764 gcc_unreachable ();
8767 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
8768 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
8769 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
8770 image_index, stat, errmsg, errmsg_len);
8771 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
8772 fndecl = build_call_expr_loc (input_location, fndecl, 6, array, image_index,
8773 stat, errmsg, strlen, errmsg_len);
8774 else
8776 tree opr, opr_flags;
8778 // FIXME: Handle TS29113's bind(C) strings with descriptor.
8779 int opr_flag_int;
8780 if (gfc_is_proc_ptr_comp (opr_expr))
8782 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
8783 opr_flag_int = sym->attr.dimension
8784 || (sym->ts.type == BT_CHARACTER
8785 && !sym->attr.is_bind_c)
8786 ? GFC_CAF_BYREF : 0;
8787 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
8788 && !sym->attr.is_bind_c
8789 ? GFC_CAF_HIDDENLEN : 0;
8790 opr_flag_int |= sym->formal->sym->attr.value ? GFC_CAF_ARG_VALUE : 0;
8792 else
8794 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
8795 ? GFC_CAF_BYREF : 0;
8796 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
8797 && !opr_expr->symtree->n.sym->attr.is_bind_c
8798 ? GFC_CAF_HIDDENLEN : 0;
8799 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
8800 ? GFC_CAF_ARG_VALUE : 0;
8802 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
8803 gfc_conv_expr (&argse, opr_expr);
8804 opr = gfc_build_addr_expr (NULL_TREE, argse.expr);
8805 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr, opr_flags,
8806 image_index, stat, errmsg, strlen, errmsg_len);
8809 gfc_add_expr_to_block (&block, fndecl);
8810 gfc_add_block_to_block (&block, &post_block);
8812 return gfc_finish_block (&block);
8816 static tree
8817 conv_intrinsic_atomic_op (gfc_code *code)
8819 gfc_se argse;
8820 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
8821 stmtblock_t block, post_block;
8822 gfc_expr *atom_expr = code->ext.actual->expr;
8823 gfc_expr *stat_expr;
8824 built_in_function fn;
8826 if (atom_expr->expr_type == EXPR_FUNCTION
8827 && atom_expr->value.function.isym
8828 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
8829 atom_expr = atom_expr->value.function.actual->expr;
8831 gfc_start_block (&block);
8832 gfc_init_block (&post_block);
8834 gfc_init_se (&argse, NULL);
8835 argse.want_pointer = 1;
8836 gfc_conv_expr (&argse, atom_expr);
8837 gfc_add_block_to_block (&block, &argse.pre);
8838 gfc_add_block_to_block (&post_block, &argse.post);
8839 atom = argse.expr;
8841 gfc_init_se (&argse, NULL);
8842 if (flag_coarray == GFC_FCOARRAY_LIB
8843 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
8844 argse.want_pointer = 1;
8845 gfc_conv_expr (&argse, code->ext.actual->next->expr);
8846 gfc_add_block_to_block (&block, &argse.pre);
8847 gfc_add_block_to_block (&post_block, &argse.post);
8848 value = argse.expr;
8850 switch (code->resolved_isym->id)
8852 case GFC_ISYM_ATOMIC_ADD:
8853 case GFC_ISYM_ATOMIC_AND:
8854 case GFC_ISYM_ATOMIC_DEF:
8855 case GFC_ISYM_ATOMIC_OR:
8856 case GFC_ISYM_ATOMIC_XOR:
8857 stat_expr = code->ext.actual->next->next->expr;
8858 if (flag_coarray == GFC_FCOARRAY_LIB)
8859 old = null_pointer_node;
8860 break;
8861 default:
8862 gfc_init_se (&argse, NULL);
8863 if (flag_coarray == GFC_FCOARRAY_LIB)
8864 argse.want_pointer = 1;
8865 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
8866 gfc_add_block_to_block (&block, &argse.pre);
8867 gfc_add_block_to_block (&post_block, &argse.post);
8868 old = argse.expr;
8869 stat_expr = code->ext.actual->next->next->next->expr;
8872 /* STAT= */
8873 if (stat_expr != NULL)
8875 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
8876 gfc_init_se (&argse, NULL);
8877 if (flag_coarray == GFC_FCOARRAY_LIB)
8878 argse.want_pointer = 1;
8879 gfc_conv_expr_val (&argse, stat_expr);
8880 gfc_add_block_to_block (&block, &argse.pre);
8881 gfc_add_block_to_block (&post_block, &argse.post);
8882 stat = argse.expr;
8884 else if (flag_coarray == GFC_FCOARRAY_LIB)
8885 stat = null_pointer_node;
8887 if (flag_coarray == GFC_FCOARRAY_LIB)
8889 tree image_index, caf_decl, offset, token;
8890 int op;
8892 switch (code->resolved_isym->id)
8894 case GFC_ISYM_ATOMIC_ADD:
8895 case GFC_ISYM_ATOMIC_FETCH_ADD:
8896 op = (int) GFC_CAF_ATOMIC_ADD;
8897 break;
8898 case GFC_ISYM_ATOMIC_AND:
8899 case GFC_ISYM_ATOMIC_FETCH_AND:
8900 op = (int) GFC_CAF_ATOMIC_AND;
8901 break;
8902 case GFC_ISYM_ATOMIC_OR:
8903 case GFC_ISYM_ATOMIC_FETCH_OR:
8904 op = (int) GFC_CAF_ATOMIC_OR;
8905 break;
8906 case GFC_ISYM_ATOMIC_XOR:
8907 case GFC_ISYM_ATOMIC_FETCH_XOR:
8908 op = (int) GFC_CAF_ATOMIC_XOR;
8909 break;
8910 case GFC_ISYM_ATOMIC_DEF:
8911 op = 0; /* Unused. */
8912 break;
8913 default:
8914 gcc_unreachable ();
8917 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
8918 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
8919 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
8921 if (gfc_is_coindexed (atom_expr))
8922 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
8923 else
8924 image_index = integer_zero_node;
8926 if (!POINTER_TYPE_P (TREE_TYPE (value)))
8928 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
8929 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
8930 value = gfc_build_addr_expr (NULL_TREE, tmp);
8933 gfc_get_caf_token_offset (&token, &offset, caf_decl, atom, atom_expr);
8935 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
8936 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
8937 token, offset, image_index, value, stat,
8938 build_int_cst (integer_type_node,
8939 (int) atom_expr->ts.type),
8940 build_int_cst (integer_type_node,
8941 (int) atom_expr->ts.kind));
8942 else
8943 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
8944 build_int_cst (integer_type_node, op),
8945 token, offset, image_index, value, old, stat,
8946 build_int_cst (integer_type_node,
8947 (int) atom_expr->ts.type),
8948 build_int_cst (integer_type_node,
8949 (int) atom_expr->ts.kind));
8951 gfc_add_expr_to_block (&block, tmp);
8952 gfc_add_block_to_block (&block, &post_block);
8953 return gfc_finish_block (&block);
8957 switch (code->resolved_isym->id)
8959 case GFC_ISYM_ATOMIC_ADD:
8960 case GFC_ISYM_ATOMIC_FETCH_ADD:
8961 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
8962 break;
8963 case GFC_ISYM_ATOMIC_AND:
8964 case GFC_ISYM_ATOMIC_FETCH_AND:
8965 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
8966 break;
8967 case GFC_ISYM_ATOMIC_DEF:
8968 fn = BUILT_IN_ATOMIC_STORE_N;
8969 break;
8970 case GFC_ISYM_ATOMIC_OR:
8971 case GFC_ISYM_ATOMIC_FETCH_OR:
8972 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
8973 break;
8974 case GFC_ISYM_ATOMIC_XOR:
8975 case GFC_ISYM_ATOMIC_FETCH_XOR:
8976 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
8977 break;
8978 default:
8979 gcc_unreachable ();
8982 tmp = TREE_TYPE (TREE_TYPE (atom));
8983 fn = (built_in_function) ((int) fn
8984 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
8985 + 1);
8986 tmp = builtin_decl_explicit (fn);
8987 tree itype = TREE_TYPE (TREE_TYPE (atom));
8988 tmp = builtin_decl_explicit (fn);
8990 switch (code->resolved_isym->id)
8992 case GFC_ISYM_ATOMIC_ADD:
8993 case GFC_ISYM_ATOMIC_AND:
8994 case GFC_ISYM_ATOMIC_DEF:
8995 case GFC_ISYM_ATOMIC_OR:
8996 case GFC_ISYM_ATOMIC_XOR:
8997 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
8998 fold_convert (itype, value),
8999 build_int_cst (NULL, MEMMODEL_RELAXED));
9000 gfc_add_expr_to_block (&block, tmp);
9001 break;
9002 default:
9003 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
9004 fold_convert (itype, value),
9005 build_int_cst (NULL, MEMMODEL_RELAXED));
9006 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
9007 break;
9010 if (stat != NULL_TREE)
9011 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
9012 gfc_add_block_to_block (&block, &post_block);
9013 return gfc_finish_block (&block);
9017 static tree
9018 conv_intrinsic_atomic_ref (gfc_code *code)
9020 gfc_se argse;
9021 tree tmp, atom, value, stat = NULL_TREE;
9022 stmtblock_t block, post_block;
9023 built_in_function fn;
9024 gfc_expr *atom_expr = code->ext.actual->next->expr;
9026 if (atom_expr->expr_type == EXPR_FUNCTION
9027 && atom_expr->value.function.isym
9028 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
9029 atom_expr = atom_expr->value.function.actual->expr;
9031 gfc_start_block (&block);
9032 gfc_init_block (&post_block);
9033 gfc_init_se (&argse, NULL);
9034 argse.want_pointer = 1;
9035 gfc_conv_expr (&argse, atom_expr);
9036 gfc_add_block_to_block (&block, &argse.pre);
9037 gfc_add_block_to_block (&post_block, &argse.post);
9038 atom = argse.expr;
9040 gfc_init_se (&argse, NULL);
9041 if (flag_coarray == GFC_FCOARRAY_LIB
9042 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
9043 argse.want_pointer = 1;
9044 gfc_conv_expr (&argse, code->ext.actual->expr);
9045 gfc_add_block_to_block (&block, &argse.pre);
9046 gfc_add_block_to_block (&post_block, &argse.post);
9047 value = argse.expr;
9049 /* STAT= */
9050 if (code->ext.actual->next->next->expr != NULL)
9052 gcc_assert (code->ext.actual->next->next->expr->expr_type
9053 == EXPR_VARIABLE);
9054 gfc_init_se (&argse, NULL);
9055 if (flag_coarray == GFC_FCOARRAY_LIB)
9056 argse.want_pointer = 1;
9057 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
9058 gfc_add_block_to_block (&block, &argse.pre);
9059 gfc_add_block_to_block (&post_block, &argse.post);
9060 stat = argse.expr;
9062 else if (flag_coarray == GFC_FCOARRAY_LIB)
9063 stat = null_pointer_node;
9065 if (flag_coarray == GFC_FCOARRAY_LIB)
9067 tree image_index, caf_decl, offset, token;
9068 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
9070 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
9071 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
9072 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
9074 if (gfc_is_coindexed (atom_expr))
9075 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
9076 else
9077 image_index = integer_zero_node;
9079 gfc_get_caf_token_offset (&token, &offset, caf_decl, atom, atom_expr);
9081 /* Different type, need type conversion. */
9082 if (!POINTER_TYPE_P (TREE_TYPE (value)))
9084 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
9085 orig_value = value;
9086 value = gfc_build_addr_expr (NULL_TREE, vardecl);
9089 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
9090 token, offset, image_index, value, stat,
9091 build_int_cst (integer_type_node,
9092 (int) atom_expr->ts.type),
9093 build_int_cst (integer_type_node,
9094 (int) atom_expr->ts.kind));
9095 gfc_add_expr_to_block (&block, tmp);
9096 if (vardecl != NULL_TREE)
9097 gfc_add_modify (&block, orig_value,
9098 fold_convert (TREE_TYPE (orig_value), vardecl));
9099 gfc_add_block_to_block (&block, &post_block);
9100 return gfc_finish_block (&block);
9103 tmp = TREE_TYPE (TREE_TYPE (atom));
9104 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
9105 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
9106 + 1);
9107 tmp = builtin_decl_explicit (fn);
9108 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
9109 build_int_cst (integer_type_node,
9110 MEMMODEL_RELAXED));
9111 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
9113 if (stat != NULL_TREE)
9114 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
9115 gfc_add_block_to_block (&block, &post_block);
9116 return gfc_finish_block (&block);
9120 static tree
9121 conv_intrinsic_atomic_cas (gfc_code *code)
9123 gfc_se argse;
9124 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
9125 stmtblock_t block, post_block;
9126 built_in_function fn;
9127 gfc_expr *atom_expr = code->ext.actual->expr;
9129 if (atom_expr->expr_type == EXPR_FUNCTION
9130 && atom_expr->value.function.isym
9131 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
9132 atom_expr = atom_expr->value.function.actual->expr;
9134 gfc_init_block (&block);
9135 gfc_init_block (&post_block);
9136 gfc_init_se (&argse, NULL);
9137 argse.want_pointer = 1;
9138 gfc_conv_expr (&argse, atom_expr);
9139 atom = argse.expr;
9141 gfc_init_se (&argse, NULL);
9142 if (flag_coarray == GFC_FCOARRAY_LIB)
9143 argse.want_pointer = 1;
9144 gfc_conv_expr (&argse, code->ext.actual->next->expr);
9145 gfc_add_block_to_block (&block, &argse.pre);
9146 gfc_add_block_to_block (&post_block, &argse.post);
9147 old = argse.expr;
9149 gfc_init_se (&argse, NULL);
9150 if (flag_coarray == GFC_FCOARRAY_LIB)
9151 argse.want_pointer = 1;
9152 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
9153 gfc_add_block_to_block (&block, &argse.pre);
9154 gfc_add_block_to_block (&post_block, &argse.post);
9155 comp = argse.expr;
9157 gfc_init_se (&argse, NULL);
9158 if (flag_coarray == GFC_FCOARRAY_LIB
9159 && code->ext.actual->next->next->next->expr->ts.kind
9160 == atom_expr->ts.kind)
9161 argse.want_pointer = 1;
9162 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
9163 gfc_add_block_to_block (&block, &argse.pre);
9164 gfc_add_block_to_block (&post_block, &argse.post);
9165 new_val = argse.expr;
9167 /* STAT= */
9168 if (code->ext.actual->next->next->next->next->expr != NULL)
9170 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
9171 == EXPR_VARIABLE);
9172 gfc_init_se (&argse, NULL);
9173 if (flag_coarray == GFC_FCOARRAY_LIB)
9174 argse.want_pointer = 1;
9175 gfc_conv_expr_val (&argse,
9176 code->ext.actual->next->next->next->next->expr);
9177 gfc_add_block_to_block (&block, &argse.pre);
9178 gfc_add_block_to_block (&post_block, &argse.post);
9179 stat = argse.expr;
9181 else if (flag_coarray == GFC_FCOARRAY_LIB)
9182 stat = null_pointer_node;
9184 if (flag_coarray == GFC_FCOARRAY_LIB)
9186 tree image_index, caf_decl, offset, token;
9188 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
9189 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
9190 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
9192 if (gfc_is_coindexed (atom_expr))
9193 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
9194 else
9195 image_index = integer_zero_node;
9197 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
9199 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
9200 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
9201 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
9204 /* Convert a constant to a pointer. */
9205 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
9207 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
9208 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
9209 comp = gfc_build_addr_expr (NULL_TREE, tmp);
9212 gfc_get_caf_token_offset (&token, &offset, caf_decl, atom, atom_expr);
9214 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
9215 token, offset, image_index, old, comp, new_val,
9216 stat, build_int_cst (integer_type_node,
9217 (int) atom_expr->ts.type),
9218 build_int_cst (integer_type_node,
9219 (int) atom_expr->ts.kind));
9220 gfc_add_expr_to_block (&block, tmp);
9221 gfc_add_block_to_block (&block, &post_block);
9222 return gfc_finish_block (&block);
9225 tmp = TREE_TYPE (TREE_TYPE (atom));
9226 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
9227 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
9228 + 1);
9229 tmp = builtin_decl_explicit (fn);
9231 gfc_add_modify (&block, old, comp);
9232 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
9233 gfc_build_addr_expr (NULL, old),
9234 fold_convert (TREE_TYPE (old), new_val),
9235 boolean_false_node,
9236 build_int_cst (NULL, MEMMODEL_RELAXED),
9237 build_int_cst (NULL, MEMMODEL_RELAXED));
9238 gfc_add_expr_to_block (&block, tmp);
9240 if (stat != NULL_TREE)
9241 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
9242 gfc_add_block_to_block (&block, &post_block);
9243 return gfc_finish_block (&block);
9247 static tree
9248 conv_intrinsic_move_alloc (gfc_code *code)
9250 stmtblock_t block;
9251 gfc_expr *from_expr, *to_expr;
9252 gfc_expr *to_expr2, *from_expr2 = NULL;
9253 gfc_se from_se, to_se;
9254 tree tmp;
9255 bool coarray;
9257 gfc_start_block (&block);
9259 from_expr = code->ext.actual->expr;
9260 to_expr = code->ext.actual->next->expr;
9262 gfc_init_se (&from_se, NULL);
9263 gfc_init_se (&to_se, NULL);
9265 gcc_assert (from_expr->ts.type != BT_CLASS
9266 || to_expr->ts.type == BT_CLASS);
9267 coarray = gfc_get_corank (from_expr) != 0;
9269 if (from_expr->rank == 0 && !coarray)
9271 if (from_expr->ts.type != BT_CLASS)
9272 from_expr2 = from_expr;
9273 else
9275 from_expr2 = gfc_copy_expr (from_expr);
9276 gfc_add_data_component (from_expr2);
9279 if (to_expr->ts.type != BT_CLASS)
9280 to_expr2 = to_expr;
9281 else
9283 to_expr2 = gfc_copy_expr (to_expr);
9284 gfc_add_data_component (to_expr2);
9287 from_se.want_pointer = 1;
9288 to_se.want_pointer = 1;
9289 gfc_conv_expr (&from_se, from_expr2);
9290 gfc_conv_expr (&to_se, to_expr2);
9291 gfc_add_block_to_block (&block, &from_se.pre);
9292 gfc_add_block_to_block (&block, &to_se.pre);
9294 /* Deallocate "to". */
9295 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, true,
9296 to_expr, to_expr->ts);
9297 gfc_add_expr_to_block (&block, tmp);
9299 /* Assign (_data) pointers. */
9300 gfc_add_modify_loc (input_location, &block, to_se.expr,
9301 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
9303 /* Set "from" to NULL. */
9304 gfc_add_modify_loc (input_location, &block, from_se.expr,
9305 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
9307 gfc_add_block_to_block (&block, &from_se.post);
9308 gfc_add_block_to_block (&block, &to_se.post);
9310 /* Set _vptr. */
9311 if (to_expr->ts.type == BT_CLASS)
9313 gfc_symbol *vtab;
9315 gfc_free_expr (to_expr2);
9316 gfc_init_se (&to_se, NULL);
9317 to_se.want_pointer = 1;
9318 gfc_add_vptr_component (to_expr);
9319 gfc_conv_expr (&to_se, to_expr);
9321 if (from_expr->ts.type == BT_CLASS)
9323 if (UNLIMITED_POLY (from_expr))
9324 vtab = NULL;
9325 else
9327 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
9328 gcc_assert (vtab);
9331 gfc_free_expr (from_expr2);
9332 gfc_init_se (&from_se, NULL);
9333 from_se.want_pointer = 1;
9334 gfc_add_vptr_component (from_expr);
9335 gfc_conv_expr (&from_se, from_expr);
9336 gfc_add_modify_loc (input_location, &block, to_se.expr,
9337 fold_convert (TREE_TYPE (to_se.expr),
9338 from_se.expr));
9340 /* Reset _vptr component to declared type. */
9341 if (vtab == NULL)
9342 /* Unlimited polymorphic. */
9343 gfc_add_modify_loc (input_location, &block, from_se.expr,
9344 fold_convert (TREE_TYPE (from_se.expr),
9345 null_pointer_node));
9346 else
9348 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
9349 gfc_add_modify_loc (input_location, &block, from_se.expr,
9350 fold_convert (TREE_TYPE (from_se.expr), tmp));
9353 else
9355 vtab = gfc_find_vtab (&from_expr->ts);
9356 gcc_assert (vtab);
9357 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
9358 gfc_add_modify_loc (input_location, &block, to_se.expr,
9359 fold_convert (TREE_TYPE (to_se.expr), tmp));
9363 return gfc_finish_block (&block);
9366 /* Update _vptr component. */
9367 if (to_expr->ts.type == BT_CLASS)
9369 gfc_symbol *vtab;
9371 to_se.want_pointer = 1;
9372 to_expr2 = gfc_copy_expr (to_expr);
9373 gfc_add_vptr_component (to_expr2);
9374 gfc_conv_expr (&to_se, to_expr2);
9376 if (from_expr->ts.type == BT_CLASS)
9378 if (UNLIMITED_POLY (from_expr))
9379 vtab = NULL;
9380 else
9382 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
9383 gcc_assert (vtab);
9386 from_se.want_pointer = 1;
9387 from_expr2 = gfc_copy_expr (from_expr);
9388 gfc_add_vptr_component (from_expr2);
9389 gfc_conv_expr (&from_se, from_expr2);
9390 gfc_add_modify_loc (input_location, &block, to_se.expr,
9391 fold_convert (TREE_TYPE (to_se.expr),
9392 from_se.expr));
9394 /* Reset _vptr component to declared type. */
9395 if (vtab == NULL)
9396 /* Unlimited polymorphic. */
9397 gfc_add_modify_loc (input_location, &block, from_se.expr,
9398 fold_convert (TREE_TYPE (from_se.expr),
9399 null_pointer_node));
9400 else
9402 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
9403 gfc_add_modify_loc (input_location, &block, from_se.expr,
9404 fold_convert (TREE_TYPE (from_se.expr), tmp));
9407 else
9409 vtab = gfc_find_vtab (&from_expr->ts);
9410 gcc_assert (vtab);
9411 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
9412 gfc_add_modify_loc (input_location, &block, to_se.expr,
9413 fold_convert (TREE_TYPE (to_se.expr), tmp));
9416 gfc_free_expr (to_expr2);
9417 gfc_init_se (&to_se, NULL);
9419 if (from_expr->ts.type == BT_CLASS)
9421 gfc_free_expr (from_expr2);
9422 gfc_init_se (&from_se, NULL);
9427 /* Deallocate "to". */
9428 if (from_expr->rank == 0)
9430 to_se.want_coarray = 1;
9431 from_se.want_coarray = 1;
9433 gfc_conv_expr_descriptor (&to_se, to_expr);
9434 gfc_conv_expr_descriptor (&from_se, from_expr);
9436 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
9437 is an image control "statement", cf. IR F08/0040 in 12-006A. */
9438 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
9440 tree cond;
9442 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
9443 NULL_TREE, NULL_TREE, true, to_expr,
9444 true);
9445 gfc_add_expr_to_block (&block, tmp);
9447 tmp = gfc_conv_descriptor_data_get (to_se.expr);
9448 cond = fold_build2_loc (input_location, EQ_EXPR,
9449 boolean_type_node, tmp,
9450 fold_convert (TREE_TYPE (tmp),
9451 null_pointer_node));
9452 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
9453 3, null_pointer_node, null_pointer_node,
9454 build_int_cst (integer_type_node, 0));
9456 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
9457 tmp, build_empty_stmt (input_location));
9458 gfc_add_expr_to_block (&block, tmp);
9460 else
9462 tmp = gfc_conv_descriptor_data_get (to_se.expr);
9463 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
9464 NULL_TREE, true, to_expr, false);
9465 gfc_add_expr_to_block (&block, tmp);
9468 /* Move the pointer and update the array descriptor data. */
9469 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
9471 /* Set "from" to NULL. */
9472 tmp = gfc_conv_descriptor_data_get (from_se.expr);
9473 gfc_add_modify_loc (input_location, &block, tmp,
9474 fold_convert (TREE_TYPE (tmp), null_pointer_node));
9476 return gfc_finish_block (&block);
9480 tree
9481 gfc_conv_intrinsic_subroutine (gfc_code *code)
9483 tree res;
9485 gcc_assert (code->resolved_isym);
9487 switch (code->resolved_isym->id)
9489 case GFC_ISYM_MOVE_ALLOC:
9490 res = conv_intrinsic_move_alloc (code);
9491 break;
9493 case GFC_ISYM_ATOMIC_CAS:
9494 res = conv_intrinsic_atomic_cas (code);
9495 break;
9497 case GFC_ISYM_ATOMIC_ADD:
9498 case GFC_ISYM_ATOMIC_AND:
9499 case GFC_ISYM_ATOMIC_DEF:
9500 case GFC_ISYM_ATOMIC_OR:
9501 case GFC_ISYM_ATOMIC_XOR:
9502 case GFC_ISYM_ATOMIC_FETCH_ADD:
9503 case GFC_ISYM_ATOMIC_FETCH_AND:
9504 case GFC_ISYM_ATOMIC_FETCH_OR:
9505 case GFC_ISYM_ATOMIC_FETCH_XOR:
9506 res = conv_intrinsic_atomic_op (code);
9507 break;
9509 case GFC_ISYM_ATOMIC_REF:
9510 res = conv_intrinsic_atomic_ref (code);
9511 break;
9513 case GFC_ISYM_C_F_POINTER:
9514 case GFC_ISYM_C_F_PROCPOINTER:
9515 res = conv_isocbinding_subroutine (code);
9516 break;
9518 case GFC_ISYM_CAF_SEND:
9519 res = conv_caf_send (code);
9520 break;
9522 case GFC_ISYM_CO_BROADCAST:
9523 case GFC_ISYM_CO_MIN:
9524 case GFC_ISYM_CO_MAX:
9525 case GFC_ISYM_CO_REDUCE:
9526 case GFC_ISYM_CO_SUM:
9527 res = conv_co_collective (code);
9528 break;
9530 case GFC_ISYM_SYSTEM_CLOCK:
9531 res = conv_intrinsic_system_clock (code);
9532 break;
9534 default:
9535 res = NULL_TREE;
9536 break;
9539 return res;
9542 #include "gt-fortran-trans-intrinsic.h"