error.c (gfc_internal_error): Convert to common diagnostics.
[official-gcc.git] / gcc / fortran / trans-intrinsic.c
blob6bf1f7439c59ce89c5b2b0d9a46a4437fd321da1
1 /* Intrinsic translation
2 Copyright (C) 2002-2014 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 "tree.h"
29 #include "stringpool.h"
30 #include "tree-nested.h"
31 #include "stor-layout.h"
32 #include "ggc.h"
33 #include "gfortran.h"
34 #include "diagnostic-core.h" /* For internal_error. */
35 #include "toplev.h" /* For rest_of_decl_compilation. */
36 #include "flags.h"
37 #include "arith.h"
38 #include "intrinsic.h"
39 #include "trans.h"
40 #include "trans-const.h"
41 #include "trans-types.h"
42 #include "trans-array.h"
43 #include "dependency.h" /* For CAF array alias analysis. */
44 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
45 #include "trans-stmt.h"
46 #include "tree-nested.h"
47 #include "wide-int.h"
49 /* This maps Fortran intrinsic math functions to external library or GCC
50 builtin functions. */
51 typedef struct GTY(()) gfc_intrinsic_map_t {
52 /* The explicit enum is required to work around inadequacies in the
53 garbage collection/gengtype parsing mechanism. */
54 enum gfc_isym_id id;
56 /* Enum value from the "language-independent", aka C-centric, part
57 of gcc, or END_BUILTINS of no such value set. */
58 enum built_in_function float_built_in;
59 enum built_in_function double_built_in;
60 enum built_in_function long_double_built_in;
61 enum built_in_function complex_float_built_in;
62 enum built_in_function complex_double_built_in;
63 enum built_in_function complex_long_double_built_in;
65 /* True if the naming pattern is to prepend "c" for complex and
66 append "f" for kind=4. False if the naming pattern is to
67 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
68 bool libm_name;
70 /* True if a complex version of the function exists. */
71 bool complex_available;
73 /* True if the function should be marked const. */
74 bool is_constant;
76 /* The base library name of this function. */
77 const char *name;
79 /* Cache decls created for the various operand types. */
80 tree real4_decl;
81 tree real8_decl;
82 tree real10_decl;
83 tree real16_decl;
84 tree complex4_decl;
85 tree complex8_decl;
86 tree complex10_decl;
87 tree complex16_decl;
89 gfc_intrinsic_map_t;
91 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
92 defines complex variants of all of the entries in mathbuiltins.def
93 except for atan2. */
94 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
95 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
96 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
97 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
98 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
100 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
101 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
102 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
103 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
104 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
106 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
107 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
108 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
109 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
110 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
112 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
113 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
114 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
115 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
116 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
118 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
120 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
121 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
122 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
123 #include "mathbuiltins.def"
125 /* Functions in libgfortran. */
126 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
128 /* End the list. */
129 LIB_FUNCTION (NONE, NULL, false)
132 #undef OTHER_BUILTIN
133 #undef LIB_FUNCTION
134 #undef DEFINE_MATH_BUILTIN
135 #undef DEFINE_MATH_BUILTIN_C
138 enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
141 /* Find the correct variant of a given builtin from its argument. */
142 static tree
143 builtin_decl_for_precision (enum built_in_function base_built_in,
144 int precision)
146 enum built_in_function i = END_BUILTINS;
148 gfc_intrinsic_map_t *m;
149 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
152 if (precision == TYPE_PRECISION (float_type_node))
153 i = m->float_built_in;
154 else if (precision == TYPE_PRECISION (double_type_node))
155 i = m->double_built_in;
156 else if (precision == TYPE_PRECISION (long_double_type_node))
157 i = m->long_double_built_in;
158 else if (precision == TYPE_PRECISION (float128_type_node))
160 /* Special treatment, because it is not exactly a built-in, but
161 a library function. */
162 return m->real16_decl;
165 return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
169 tree
170 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
171 int kind)
173 int i = gfc_validate_kind (BT_REAL, kind, false);
175 if (gfc_real_kinds[i].c_float128)
177 /* For __float128, the story is a bit different, because we return
178 a decl to a library function rather than a built-in. */
179 gfc_intrinsic_map_t *m;
180 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
183 return m->real16_decl;
186 return builtin_decl_for_precision (double_built_in,
187 gfc_real_kinds[i].mode_precision);
191 /* Evaluate the arguments to an intrinsic function. The value
192 of NARGS may be less than the actual number of arguments in EXPR
193 to allow optional "KIND" arguments that are not included in the
194 generated code to be ignored. */
196 static void
197 gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
198 tree *argarray, int nargs)
200 gfc_actual_arglist *actual;
201 gfc_expr *e;
202 gfc_intrinsic_arg *formal;
203 gfc_se argse;
204 int curr_arg;
206 formal = expr->value.function.isym->formal;
207 actual = expr->value.function.actual;
209 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
210 actual = actual->next,
211 formal = formal ? formal->next : NULL)
213 gcc_assert (actual);
214 e = actual->expr;
215 /* Skip omitted optional arguments. */
216 if (!e)
218 --curr_arg;
219 continue;
222 /* Evaluate the parameter. This will substitute scalarized
223 references automatically. */
224 gfc_init_se (&argse, se);
226 if (e->ts.type == BT_CHARACTER)
228 gfc_conv_expr (&argse, e);
229 gfc_conv_string_parameter (&argse);
230 argarray[curr_arg++] = argse.string_length;
231 gcc_assert (curr_arg < nargs);
233 else
234 gfc_conv_expr_val (&argse, e);
236 /* If an optional argument is itself an optional dummy argument,
237 check its presence and substitute a null if absent. */
238 if (e->expr_type == EXPR_VARIABLE
239 && e->symtree->n.sym->attr.optional
240 && formal
241 && formal->optional)
242 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
244 gfc_add_block_to_block (&se->pre, &argse.pre);
245 gfc_add_block_to_block (&se->post, &argse.post);
246 argarray[curr_arg] = argse.expr;
250 /* Count the number of actual arguments to the intrinsic function EXPR
251 including any "hidden" string length arguments. */
253 static unsigned int
254 gfc_intrinsic_argument_list_length (gfc_expr *expr)
256 int n = 0;
257 gfc_actual_arglist *actual;
259 for (actual = expr->value.function.actual; actual; actual = actual->next)
261 if (!actual->expr)
262 continue;
264 if (actual->expr->ts.type == BT_CHARACTER)
265 n += 2;
266 else
267 n++;
270 return n;
274 /* Conversions between different types are output by the frontend as
275 intrinsic functions. We implement these directly with inline code. */
277 static void
278 gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
280 tree type;
281 tree *args;
282 int nargs;
284 nargs = gfc_intrinsic_argument_list_length (expr);
285 args = XALLOCAVEC (tree, nargs);
287 /* Evaluate all the arguments passed. Whilst we're only interested in the
288 first one here, there are other parts of the front-end that assume this
289 and will trigger an ICE if it's not the case. */
290 type = gfc_typenode_for_spec (&expr->ts);
291 gcc_assert (expr->value.function.actual->expr);
292 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
294 /* Conversion between character kinds involves a call to a library
295 function. */
296 if (expr->ts.type == BT_CHARACTER)
298 tree fndecl, var, addr, tmp;
300 if (expr->ts.kind == 1
301 && expr->value.function.actual->expr->ts.kind == 4)
302 fndecl = gfor_fndecl_convert_char4_to_char1;
303 else if (expr->ts.kind == 4
304 && expr->value.function.actual->expr->ts.kind == 1)
305 fndecl = gfor_fndecl_convert_char1_to_char4;
306 else
307 gcc_unreachable ();
309 /* Create the variable storing the converted value. */
310 type = gfc_get_pchar_type (expr->ts.kind);
311 var = gfc_create_var (type, "str");
312 addr = gfc_build_addr_expr (build_pointer_type (type), var);
314 /* Call the library function that will perform the conversion. */
315 gcc_assert (nargs >= 2);
316 tmp = build_call_expr_loc (input_location,
317 fndecl, 3, addr, args[0], args[1]);
318 gfc_add_expr_to_block (&se->pre, tmp);
320 /* Free the temporary afterwards. */
321 tmp = gfc_call_free (var);
322 gfc_add_expr_to_block (&se->post, tmp);
324 se->expr = var;
325 se->string_length = args[0];
327 return;
330 /* Conversion from complex to non-complex involves taking the real
331 component of the value. */
332 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
333 && expr->ts.type != BT_COMPLEX)
335 tree artype;
337 artype = TREE_TYPE (TREE_TYPE (args[0]));
338 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
339 args[0]);
342 se->expr = convert (type, args[0]);
345 /* This is needed because the gcc backend only implements
346 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
347 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
348 Similarly for CEILING. */
350 static tree
351 build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
353 tree tmp;
354 tree cond;
355 tree argtype;
356 tree intval;
358 argtype = TREE_TYPE (arg);
359 arg = gfc_evaluate_now (arg, pblock);
361 intval = convert (type, arg);
362 intval = gfc_evaluate_now (intval, pblock);
364 tmp = convert (argtype, intval);
365 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
366 boolean_type_node, tmp, arg);
368 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
369 intval, build_int_cst (type, 1));
370 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
371 return tmp;
375 /* Round to nearest integer, away from zero. */
377 static tree
378 build_round_expr (tree arg, tree restype)
380 tree argtype;
381 tree fn;
382 int argprec, resprec;
384 argtype = TREE_TYPE (arg);
385 argprec = TYPE_PRECISION (argtype);
386 resprec = TYPE_PRECISION (restype);
388 /* Depending on the type of the result, choose the int intrinsic
389 (iround, available only as a builtin, therefore cannot use it for
390 __float128), long int intrinsic (lround family) or long long
391 intrinsic (llround). We might also need to convert the result
392 afterwards. */
393 if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
394 fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
395 else if (resprec <= LONG_TYPE_SIZE)
396 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
397 else if (resprec <= LONG_LONG_TYPE_SIZE)
398 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
399 else
400 gcc_unreachable ();
402 return fold_convert (restype, build_call_expr_loc (input_location,
403 fn, 1, arg));
407 /* Convert a real to an integer using a specific rounding mode.
408 Ideally we would just build the corresponding GENERIC node,
409 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
411 static tree
412 build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
413 enum rounding_mode op)
415 switch (op)
417 case RND_FLOOR:
418 return build_fixbound_expr (pblock, arg, type, 0);
419 break;
421 case RND_CEIL:
422 return build_fixbound_expr (pblock, arg, type, 1);
423 break;
425 case RND_ROUND:
426 return build_round_expr (arg, type);
427 break;
429 case RND_TRUNC:
430 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
431 break;
433 default:
434 gcc_unreachable ();
439 /* Round a real value using the specified rounding mode.
440 We use a temporary integer of that same kind size as the result.
441 Values larger than those that can be represented by this kind are
442 unchanged, as they will not be accurate enough to represent the
443 rounding.
444 huge = HUGE (KIND (a))
445 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
448 static void
449 gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
451 tree type;
452 tree itype;
453 tree arg[2];
454 tree tmp;
455 tree cond;
456 tree decl;
457 mpfr_t huge;
458 int n, nargs;
459 int kind;
461 kind = expr->ts.kind;
462 nargs = gfc_intrinsic_argument_list_length (expr);
464 decl = NULL_TREE;
465 /* We have builtin functions for some cases. */
466 switch (op)
468 case RND_ROUND:
469 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
470 break;
472 case RND_TRUNC:
473 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
474 break;
476 default:
477 gcc_unreachable ();
480 /* Evaluate the argument. */
481 gcc_assert (expr->value.function.actual->expr);
482 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
484 /* Use a builtin function if one exists. */
485 if (decl != NULL_TREE)
487 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
488 return;
491 /* This code is probably redundant, but we'll keep it lying around just
492 in case. */
493 type = gfc_typenode_for_spec (&expr->ts);
494 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
496 /* Test if the value is too large to handle sensibly. */
497 gfc_set_model_kind (kind);
498 mpfr_init (huge);
499 n = gfc_validate_kind (BT_INTEGER, kind, false);
500 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
501 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
502 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, arg[0],
503 tmp);
505 mpfr_neg (huge, huge, GFC_RND_MODE);
506 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
507 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, arg[0],
508 tmp);
509 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
510 cond, tmp);
511 itype = gfc_get_int_type (kind);
513 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
514 tmp = convert (type, tmp);
515 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
516 arg[0]);
517 mpfr_clear (huge);
521 /* Convert to an integer using the specified rounding mode. */
523 static void
524 gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
526 tree type;
527 tree *args;
528 int nargs;
530 nargs = gfc_intrinsic_argument_list_length (expr);
531 args = XALLOCAVEC (tree, nargs);
533 /* Evaluate the argument, we process all arguments even though we only
534 use the first one for code generation purposes. */
535 type = gfc_typenode_for_spec (&expr->ts);
536 gcc_assert (expr->value.function.actual->expr);
537 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
539 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
541 /* Conversion to a different integer kind. */
542 se->expr = convert (type, args[0]);
544 else
546 /* Conversion from complex to non-complex involves taking the real
547 component of the value. */
548 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
549 && expr->ts.type != BT_COMPLEX)
551 tree artype;
553 artype = TREE_TYPE (TREE_TYPE (args[0]));
554 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
555 args[0]);
558 se->expr = build_fix_expr (&se->pre, args[0], type, op);
563 /* Get the imaginary component of a value. */
565 static void
566 gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
568 tree arg;
570 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
571 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
572 TREE_TYPE (TREE_TYPE (arg)), arg);
576 /* Get the complex conjugate of a value. */
578 static void
579 gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
581 tree arg;
583 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
584 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
589 static tree
590 define_quad_builtin (const char *name, tree type, bool is_const)
592 tree fndecl;
593 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
594 type);
596 /* Mark the decl as external. */
597 DECL_EXTERNAL (fndecl) = 1;
598 TREE_PUBLIC (fndecl) = 1;
600 /* Mark it __attribute__((const)). */
601 TREE_READONLY (fndecl) = is_const;
603 rest_of_decl_compilation (fndecl, 1, 0);
605 return fndecl;
610 /* Initialize function decls for library functions. The external functions
611 are created as required. Builtin functions are added here. */
613 void
614 gfc_build_intrinsic_lib_fndecls (void)
616 gfc_intrinsic_map_t *m;
617 tree quad_decls[END_BUILTINS + 1];
619 if (gfc_real16_is_float128)
621 /* If we have soft-float types, we create the decls for their
622 C99-like library functions. For now, we only handle __float128
623 q-suffixed functions. */
625 tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
626 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
628 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
630 type = float128_type_node;
631 complex_type = complex_float128_type_node;
632 /* type (*) (type) */
633 func_1 = build_function_type_list (type, type, NULL_TREE);
634 /* int (*) (type) */
635 func_iround = build_function_type_list (integer_type_node,
636 type, NULL_TREE);
637 /* long (*) (type) */
638 func_lround = build_function_type_list (long_integer_type_node,
639 type, NULL_TREE);
640 /* long long (*) (type) */
641 func_llround = build_function_type_list (long_long_integer_type_node,
642 type, NULL_TREE);
643 /* type (*) (type, type) */
644 func_2 = build_function_type_list (type, type, type, NULL_TREE);
645 /* type (*) (type, &int) */
646 func_frexp
647 = build_function_type_list (type,
648 type,
649 build_pointer_type (integer_type_node),
650 NULL_TREE);
651 /* type (*) (type, int) */
652 func_scalbn = build_function_type_list (type,
653 type, integer_type_node, NULL_TREE);
654 /* type (*) (complex type) */
655 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
656 /* complex type (*) (complex type, complex type) */
657 func_cpow
658 = build_function_type_list (complex_type,
659 complex_type, complex_type, NULL_TREE);
661 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
662 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
663 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
665 /* Only these built-ins are actually needed here. These are used directly
666 from the code, when calling builtin_decl_for_precision() or
667 builtin_decl_for_float_type(). The others are all constructed by
668 gfc_get_intrinsic_lib_fndecl(). */
669 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
670 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
672 #include "mathbuiltins.def"
674 #undef OTHER_BUILTIN
675 #undef LIB_FUNCTION
676 #undef DEFINE_MATH_BUILTIN
677 #undef DEFINE_MATH_BUILTIN_C
681 /* Add GCC builtin functions. */
682 for (m = gfc_intrinsic_map;
683 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
685 if (m->float_built_in != END_BUILTINS)
686 m->real4_decl = builtin_decl_explicit (m->float_built_in);
687 if (m->complex_float_built_in != END_BUILTINS)
688 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
689 if (m->double_built_in != END_BUILTINS)
690 m->real8_decl = builtin_decl_explicit (m->double_built_in);
691 if (m->complex_double_built_in != END_BUILTINS)
692 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
694 /* If real(kind=10) exists, it is always long double. */
695 if (m->long_double_built_in != END_BUILTINS)
696 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
697 if (m->complex_long_double_built_in != END_BUILTINS)
698 m->complex10_decl
699 = builtin_decl_explicit (m->complex_long_double_built_in);
701 if (!gfc_real16_is_float128)
703 if (m->long_double_built_in != END_BUILTINS)
704 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
705 if (m->complex_long_double_built_in != END_BUILTINS)
706 m->complex16_decl
707 = builtin_decl_explicit (m->complex_long_double_built_in);
709 else if (quad_decls[m->double_built_in] != NULL_TREE)
711 /* Quad-precision function calls are constructed when first
712 needed by builtin_decl_for_precision(), except for those
713 that will be used directly (define by OTHER_BUILTIN). */
714 m->real16_decl = quad_decls[m->double_built_in];
716 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
718 /* Same thing for the complex ones. */
719 m->complex16_decl = quad_decls[m->double_built_in];
725 /* Create a fndecl for a simple intrinsic library function. */
727 static tree
728 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
730 tree type;
731 vec<tree, va_gc> *argtypes;
732 tree fndecl;
733 gfc_actual_arglist *actual;
734 tree *pdecl;
735 gfc_typespec *ts;
736 char name[GFC_MAX_SYMBOL_LEN + 3];
738 ts = &expr->ts;
739 if (ts->type == BT_REAL)
741 switch (ts->kind)
743 case 4:
744 pdecl = &m->real4_decl;
745 break;
746 case 8:
747 pdecl = &m->real8_decl;
748 break;
749 case 10:
750 pdecl = &m->real10_decl;
751 break;
752 case 16:
753 pdecl = &m->real16_decl;
754 break;
755 default:
756 gcc_unreachable ();
759 else if (ts->type == BT_COMPLEX)
761 gcc_assert (m->complex_available);
763 switch (ts->kind)
765 case 4:
766 pdecl = &m->complex4_decl;
767 break;
768 case 8:
769 pdecl = &m->complex8_decl;
770 break;
771 case 10:
772 pdecl = &m->complex10_decl;
773 break;
774 case 16:
775 pdecl = &m->complex16_decl;
776 break;
777 default:
778 gcc_unreachable ();
781 else
782 gcc_unreachable ();
784 if (*pdecl)
785 return *pdecl;
787 if (m->libm_name)
789 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
790 if (gfc_real_kinds[n].c_float)
791 snprintf (name, sizeof (name), "%s%s%s",
792 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
793 else if (gfc_real_kinds[n].c_double)
794 snprintf (name, sizeof (name), "%s%s",
795 ts->type == BT_COMPLEX ? "c" : "", m->name);
796 else if (gfc_real_kinds[n].c_long_double)
797 snprintf (name, sizeof (name), "%s%s%s",
798 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
799 else if (gfc_real_kinds[n].c_float128)
800 snprintf (name, sizeof (name), "%s%s%s",
801 ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
802 else
803 gcc_unreachable ();
805 else
807 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
808 ts->type == BT_COMPLEX ? 'c' : 'r',
809 ts->kind);
812 argtypes = NULL;
813 for (actual = expr->value.function.actual; actual; actual = actual->next)
815 type = gfc_typenode_for_spec (&actual->expr->ts);
816 vec_safe_push (argtypes, type);
818 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
819 fndecl = build_decl (input_location,
820 FUNCTION_DECL, get_identifier (name), type);
822 /* Mark the decl as external. */
823 DECL_EXTERNAL (fndecl) = 1;
824 TREE_PUBLIC (fndecl) = 1;
826 /* Mark it __attribute__((const)), if possible. */
827 TREE_READONLY (fndecl) = m->is_constant;
829 rest_of_decl_compilation (fndecl, 1, 0);
831 (*pdecl) = fndecl;
832 return fndecl;
836 /* Convert an intrinsic function into an external or builtin call. */
838 static void
839 gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
841 gfc_intrinsic_map_t *m;
842 tree fndecl;
843 tree rettype;
844 tree *args;
845 unsigned int num_args;
846 gfc_isym_id id;
848 id = expr->value.function.isym->id;
849 /* Find the entry for this function. */
850 for (m = gfc_intrinsic_map;
851 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
853 if (id == m->id)
854 break;
857 if (m->id == GFC_ISYM_NONE)
859 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
860 expr->value.function.name, id);
863 /* Get the decl and generate the call. */
864 num_args = gfc_intrinsic_argument_list_length (expr);
865 args = XALLOCAVEC (tree, num_args);
867 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
868 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
869 rettype = TREE_TYPE (TREE_TYPE (fndecl));
871 fndecl = build_addr (fndecl, current_function_decl);
872 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
876 /* If bounds-checking is enabled, create code to verify at runtime that the
877 string lengths for both expressions are the same (needed for e.g. MERGE).
878 If bounds-checking is not enabled, does nothing. */
880 void
881 gfc_trans_same_strlen_check (const char* intr_name, locus* where,
882 tree a, tree b, stmtblock_t* target)
884 tree cond;
885 tree name;
887 /* If bounds-checking is disabled, do nothing. */
888 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
889 return;
891 /* Compare the two string lengths. */
892 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, a, b);
894 /* Output the runtime-check. */
895 name = gfc_build_cstring_const (intr_name);
896 name = gfc_build_addr_expr (pchar_type_node, name);
897 gfc_trans_runtime_check (true, false, cond, target, where,
898 "Unequal character lengths (%ld/%ld) in %s",
899 fold_convert (long_integer_type_node, a),
900 fold_convert (long_integer_type_node, b), name);
904 /* The EXPONENT(X) intrinsic function is translated into
905 int ret;
906 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
907 so that if X is a NaN or infinity, the result is HUGE(0).
910 static void
911 gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
913 tree arg, type, res, tmp, frexp, cond, huge;
914 int i;
916 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
917 expr->value.function.actual->expr->ts.kind);
919 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
920 arg = gfc_evaluate_now (arg, &se->pre);
922 i = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
923 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_c_int_kind);
924 cond = build_call_expr_loc (input_location,
925 builtin_decl_explicit (BUILT_IN_ISFINITE),
926 1, arg);
928 res = gfc_create_var (integer_type_node, NULL);
929 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
930 gfc_build_addr_expr (NULL_TREE, res));
931 tmp = fold_build2_loc (input_location, COMPOUND_EXPR, integer_type_node,
932 tmp, res);
933 se->expr = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
934 cond, tmp, huge);
936 type = gfc_typenode_for_spec (&expr->ts);
937 se->expr = fold_convert (type, se->expr);
941 /* Fill in the following structure
942 struct caf_vector_t {
943 size_t nvec; // size of the vector
944 union {
945 struct {
946 void *vector;
947 int kind;
948 } v;
949 struct {
950 ptrdiff_t lower_bound;
951 ptrdiff_t upper_bound;
952 ptrdiff_t stride;
953 } triplet;
954 } u;
955 } */
957 static void
958 conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
959 tree lower, tree upper, tree stride,
960 tree vector, int kind, tree nvec)
962 tree field, type, tmp;
964 desc = gfc_build_array_ref (desc, gfc_rank_cst[i], NULL_TREE);
965 type = TREE_TYPE (desc);
967 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
968 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
969 desc, field, NULL_TREE);
970 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), nvec));
972 /* Access union. */
973 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
974 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
975 desc, field, NULL_TREE);
976 type = TREE_TYPE (desc);
978 /* Access the inner struct. */
979 field = gfc_advance_chain (TYPE_FIELDS (type), vector != NULL_TREE ? 0 : 1);
980 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
981 desc, field, NULL_TREE);
982 type = TREE_TYPE (desc);
984 if (vector != NULL_TREE)
986 /* Set dim.lower/upper/stride. */
987 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
988 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
989 desc, field, NULL_TREE);
990 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), vector));
991 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
992 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
993 desc, field, NULL_TREE);
994 gfc_add_modify (block, tmp, build_int_cst (integer_type_node, kind));
996 else
998 /* Set vector and kind. */
999 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1000 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1001 desc, field, NULL_TREE);
1002 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), lower));
1004 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1005 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1006 desc, field, NULL_TREE);
1007 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), upper));
1009 field = gfc_advance_chain (TYPE_FIELDS (type), 2);
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), stride));
1017 static tree
1018 conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
1020 gfc_se argse;
1021 tree var, lower, upper = NULL_TREE, stride = NULL_TREE, vector, nvec;
1022 tree lbound, ubound, tmp;
1023 int i;
1025 var = gfc_create_var (gfc_get_caf_vector_type (ar->dimen), "vector");
1027 for (i = 0; i < ar->dimen; i++)
1028 switch (ar->dimen_type[i])
1030 case DIMEN_RANGE:
1031 if (ar->end[i])
1033 gfc_init_se (&argse, NULL);
1034 gfc_conv_expr (&argse, ar->end[i]);
1035 gfc_add_block_to_block (block, &argse.pre);
1036 upper = gfc_evaluate_now (argse.expr, block);
1038 else
1039 upper = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1040 if (ar->stride[i])
1042 gfc_init_se (&argse, NULL);
1043 gfc_conv_expr (&argse, ar->stride[i]);
1044 gfc_add_block_to_block (block, &argse.pre);
1045 stride = gfc_evaluate_now (argse.expr, block);
1047 else
1048 stride = gfc_index_one_node;
1050 /* Fall through. */
1051 case DIMEN_ELEMENT:
1052 if (ar->start[i])
1054 gfc_init_se (&argse, NULL);
1055 gfc_conv_expr (&argse, ar->start[i]);
1056 gfc_add_block_to_block (block, &argse.pre);
1057 lower = gfc_evaluate_now (argse.expr, block);
1059 else
1060 lower = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1061 if (ar->dimen_type[i] == DIMEN_ELEMENT)
1063 upper = lower;
1064 stride = gfc_index_one_node;
1066 vector = NULL_TREE;
1067 nvec = size_zero_node;
1068 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1069 vector, 0, nvec);
1070 break;
1072 case DIMEN_VECTOR:
1073 gfc_init_se (&argse, NULL);
1074 argse.descriptor_only = 1;
1075 gfc_conv_expr_descriptor (&argse, ar->start[i]);
1076 gfc_add_block_to_block (block, &argse.pre);
1077 vector = argse.expr;
1078 lbound = gfc_conv_descriptor_lbound_get (vector, gfc_rank_cst[0]);
1079 ubound = gfc_conv_descriptor_ubound_get (vector, gfc_rank_cst[0]);
1080 nvec = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1081 tmp = gfc_conv_descriptor_stride_get (vector, gfc_rank_cst[0]);
1082 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1083 TREE_TYPE (nvec), nvec, tmp);
1084 lower = gfc_index_zero_node;
1085 upper = gfc_index_zero_node;
1086 stride = gfc_index_zero_node;
1087 vector = gfc_conv_descriptor_data_get (vector);
1088 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1089 vector, ar->start[i]->ts.kind, nvec);
1090 break;
1091 default:
1092 gcc_unreachable();
1094 return gfc_build_addr_expr (NULL_TREE, var);
1098 /* Get data from a remote coarray. */
1100 static void
1101 gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
1102 tree may_require_tmp)
1104 gfc_expr *array_expr;
1105 gfc_se argse;
1106 tree caf_decl, token, offset, image_index, tmp;
1107 tree res_var, dst_var, type, kind, vec;
1109 gcc_assert (gfc_option.coarray == GFC_FCOARRAY_LIB);
1111 if (se->ss && se->ss->info->useflags)
1113 /* Access the previously obtained result. */
1114 gfc_conv_tmp_array_ref (se);
1115 return;
1118 /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1119 array_expr = (lhs == NULL_TREE) ? expr->value.function.actual->expr : expr;
1120 type = gfc_typenode_for_spec (&array_expr->ts);
1122 res_var = lhs;
1123 dst_var = lhs;
1125 gfc_init_se (&argse, NULL);
1126 if (array_expr->rank == 0)
1128 symbol_attribute attr;
1130 gfc_clear_attr (&attr);
1131 gfc_conv_expr (&argse, array_expr);
1133 if (lhs == NULL_TREE)
1135 gfc_clear_attr (&attr);
1136 if (array_expr->ts.type == BT_CHARACTER)
1137 res_var = gfc_conv_string_tmp (se, build_pointer_type (type),
1138 argse.string_length);
1139 else
1140 res_var = gfc_create_var (type, "caf_res");
1141 dst_var = gfc_conv_scalar_to_descriptor (&argse, res_var, attr);
1142 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1144 argse.expr = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
1145 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1147 else
1149 /* If has_vector, pass descriptor for whole array and the
1150 vector bounds separately. */
1151 gfc_array_ref *ar, ar2;
1152 bool has_vector = false;
1154 if (gfc_is_coindexed (expr) && gfc_has_vector_subscript (expr))
1156 has_vector = true;
1157 ar = gfc_find_array_ref (expr);
1158 ar2 = *ar;
1159 memset (ar, '\0', sizeof (*ar));
1160 ar->as = ar2.as;
1161 ar->type = AR_FULL;
1163 gfc_conv_expr_descriptor (&argse, array_expr);
1164 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1165 has the wrong type if component references are done. */
1166 gfc_add_modify (&argse.pre, gfc_conv_descriptor_dtype (argse.expr),
1167 gfc_get_dtype_rank_type (array_expr->rank, type));
1168 if (has_vector)
1170 vec = conv_caf_vector_subscript (&argse.pre, argse.expr, ar);
1171 *ar = ar2;
1174 if (lhs == NULL_TREE)
1176 /* Create temporary. */
1177 for (int n = 0; n < se->ss->loop->dimen; n++)
1178 if (se->loop->to[n] == NULL_TREE)
1180 se->loop->from[n] =
1181 gfc_conv_descriptor_lbound_get (argse.expr, gfc_rank_cst[n]);
1182 se->loop->to[n] =
1183 gfc_conv_descriptor_ubound_get (argse.expr, gfc_rank_cst[n]);
1185 gfc_trans_create_temp_array (&argse.pre, &argse.post, se->ss, type,
1186 NULL_TREE, false, true, false,
1187 &array_expr->where);
1188 res_var = se->ss->info->data.array.descriptor;
1189 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1191 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1194 kind = build_int_cst (integer_type_node, expr->ts.kind);
1195 if (lhs_kind == NULL_TREE)
1196 lhs_kind = kind;
1198 vec = null_pointer_node;
1200 gfc_add_block_to_block (&se->pre, &argse.pre);
1201 gfc_add_block_to_block (&se->post, &argse.post);
1203 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1204 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1205 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1206 image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
1207 gfc_get_caf_token_offset (&token, &offset, caf_decl, argse.expr, array_expr);
1209 /* No overlap possible as we have generated a temporary. */
1210 if (lhs == NULL_TREE)
1211 may_require_tmp = boolean_false_node;
1213 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 9,
1214 token, offset, image_index, argse.expr, vec,
1215 dst_var, kind, lhs_kind, may_require_tmp);
1216 gfc_add_expr_to_block (&se->pre, tmp);
1218 if (se->ss)
1219 gfc_advance_se_ss_chain (se);
1221 se->expr = res_var;
1222 if (array_expr->ts.type == BT_CHARACTER)
1223 se->string_length = argse.string_length;
1227 /* Send data to a remove coarray. */
1229 static tree
1230 conv_caf_send (gfc_code *code) {
1231 gfc_expr *lhs_expr, *rhs_expr;
1232 gfc_se lhs_se, rhs_se;
1233 stmtblock_t block;
1234 tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
1235 tree may_require_tmp;
1236 tree lhs_type = NULL_TREE;
1237 tree vec = null_pointer_node, rhs_vec = null_pointer_node;
1239 gcc_assert (gfc_option.coarray == GFC_FCOARRAY_LIB);
1241 lhs_expr = code->ext.actual->expr;
1242 rhs_expr = code->ext.actual->next->expr;
1243 may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, false) == 0
1244 ? boolean_false_node : boolean_true_node;
1245 gfc_init_block (&block);
1247 /* LHS. */
1248 gfc_init_se (&lhs_se, NULL);
1249 if (lhs_expr->rank == 0)
1251 symbol_attribute attr;
1252 gfc_clear_attr (&attr);
1253 gfc_conv_expr (&lhs_se, lhs_expr);
1254 lhs_type = TREE_TYPE (lhs_se.expr);
1255 lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr, attr);
1256 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1258 else
1260 /* If has_vector, pass descriptor for whole array and the
1261 vector bounds separately. */
1262 gfc_array_ref *ar, ar2;
1263 bool has_vector = false;
1265 if (gfc_is_coindexed (lhs_expr) && gfc_has_vector_subscript (lhs_expr))
1267 has_vector = true;
1268 ar = gfc_find_array_ref (lhs_expr);
1269 ar2 = *ar;
1270 memset (ar, '\0', sizeof (*ar));
1271 ar->as = ar2.as;
1272 ar->type = AR_FULL;
1274 lhs_se.want_pointer = 1;
1275 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1276 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1277 has the wrong type if component references are done. */
1278 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1279 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1280 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1281 gfc_get_dtype_rank_type (lhs_expr->rank, lhs_type));
1282 if (has_vector)
1284 vec = conv_caf_vector_subscript (&block, lhs_se.expr, ar);
1285 *ar = ar2;
1289 lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
1290 gfc_add_block_to_block (&block, &lhs_se.pre);
1292 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
1293 temporary and a loop. */
1294 if (!gfc_is_coindexed (lhs_expr))
1296 gcc_assert (gfc_is_coindexed (rhs_expr));
1297 gfc_init_se (&rhs_se, NULL);
1298 gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
1299 may_require_tmp);
1300 gfc_add_block_to_block (&block, &rhs_se.pre);
1301 gfc_add_block_to_block (&block, &rhs_se.post);
1302 gfc_add_block_to_block (&block, &lhs_se.post);
1303 return gfc_finish_block (&block);
1306 /* Obtain token, offset and image index for the LHS. */
1308 caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
1309 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1310 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1311 image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
1312 gfc_get_caf_token_offset (&token, &offset, caf_decl, lhs_se.expr, lhs_expr);
1314 /* RHS. */
1315 gfc_init_se (&rhs_se, NULL);
1316 if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
1317 && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
1318 rhs_expr = rhs_expr->value.function.actual->expr;
1319 if (rhs_expr->rank == 0)
1321 symbol_attribute attr;
1322 gfc_clear_attr (&attr);
1323 gfc_conv_expr (&rhs_se, rhs_expr);
1324 if (!gfc_is_coindexed (rhs_expr) && rhs_expr->ts.type != BT_CHARACTER)
1325 rhs_se.expr = fold_convert (lhs_type , rhs_se.expr);
1326 rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
1327 rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
1329 else
1331 /* If has_vector, pass descriptor for whole array and the
1332 vector bounds separately. */
1333 gfc_array_ref *ar, ar2;
1334 bool has_vector = false;
1335 tree tmp2;
1337 if (gfc_is_coindexed (rhs_expr) && gfc_has_vector_subscript (rhs_expr))
1339 has_vector = true;
1340 ar = gfc_find_array_ref (rhs_expr);
1341 ar2 = *ar;
1342 memset (ar, '\0', sizeof (*ar));
1343 ar->as = ar2.as;
1344 ar->type = AR_FULL;
1346 rhs_se.want_pointer = 1;
1347 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
1348 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1349 has the wrong type if component references are done. */
1350 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
1351 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
1352 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1353 gfc_get_dtype_rank_type (rhs_expr->rank, tmp2));
1354 if (has_vector)
1356 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, ar);
1357 *ar = ar2;
1361 gfc_add_block_to_block (&block, &rhs_se.pre);
1363 rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
1365 if (!gfc_is_coindexed (rhs_expr))
1366 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 9, token,
1367 offset, image_index, lhs_se.expr, vec,
1368 rhs_se.expr, lhs_kind, rhs_kind, may_require_tmp);
1369 else
1371 tree rhs_token, rhs_offset, rhs_image_index;
1373 caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
1374 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1375 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1376 rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
1377 gfc_get_caf_token_offset (&rhs_token, &rhs_offset, caf_decl, rhs_se.expr,
1378 rhs_expr);
1379 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget, 13,
1380 token, offset, image_index, lhs_se.expr, vec,
1381 rhs_token, rhs_offset, rhs_image_index,
1382 rhs_se.expr, rhs_vec, lhs_kind, rhs_kind,
1383 may_require_tmp);
1385 gfc_add_expr_to_block (&block, tmp);
1386 gfc_add_block_to_block (&block, &lhs_se.post);
1387 gfc_add_block_to_block (&block, &rhs_se.post);
1388 return gfc_finish_block (&block);
1392 static void
1393 trans_this_image (gfc_se * se, gfc_expr *expr)
1395 stmtblock_t loop;
1396 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
1397 lbound, ubound, extent, ml;
1398 gfc_se argse;
1399 int rank, corank;
1400 gfc_expr *distance = expr->value.function.actual->next->next->expr;
1402 if (expr->value.function.actual->expr
1403 && !gfc_is_coarray (expr->value.function.actual->expr))
1404 distance = expr->value.function.actual->expr;
1406 /* The case -fcoarray=single is handled elsewhere. */
1407 gcc_assert (gfc_option.coarray != GFC_FCOARRAY_SINGLE);
1409 /* Argument-free version: THIS_IMAGE(). */
1410 if (distance || expr->value.function.actual->expr == NULL)
1412 if (distance)
1414 gfc_init_se (&argse, NULL);
1415 gfc_conv_expr_val (&argse, distance);
1416 gfc_add_block_to_block (&se->pre, &argse.pre);
1417 gfc_add_block_to_block (&se->post, &argse.post);
1418 tmp = fold_convert (integer_type_node, argse.expr);
1420 else
1421 tmp = integer_zero_node;
1422 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
1423 tmp);
1424 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
1425 tmp);
1426 return;
1429 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
1431 type = gfc_get_int_type (gfc_default_integer_kind);
1432 corank = gfc_get_corank (expr->value.function.actual->expr);
1433 rank = expr->value.function.actual->expr->rank;
1435 /* Obtain the descriptor of the COARRAY. */
1436 gfc_init_se (&argse, NULL);
1437 argse.want_coarray = 1;
1438 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
1439 gfc_add_block_to_block (&se->pre, &argse.pre);
1440 gfc_add_block_to_block (&se->post, &argse.post);
1441 desc = argse.expr;
1443 if (se->ss)
1445 /* Create an implicit second parameter from the loop variable. */
1446 gcc_assert (!expr->value.function.actual->next->expr);
1447 gcc_assert (corank > 0);
1448 gcc_assert (se->loop->dimen == 1);
1449 gcc_assert (se->ss->info->expr == expr);
1451 dim_arg = se->loop->loopvar[0];
1452 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
1453 gfc_array_index_type, dim_arg,
1454 build_int_cst (TREE_TYPE (dim_arg), 1));
1455 gfc_advance_se_ss_chain (se);
1457 else
1459 /* Use the passed DIM= argument. */
1460 gcc_assert (expr->value.function.actual->next->expr);
1461 gfc_init_se (&argse, NULL);
1462 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
1463 gfc_array_index_type);
1464 gfc_add_block_to_block (&se->pre, &argse.pre);
1465 dim_arg = argse.expr;
1467 if (INTEGER_CST_P (dim_arg))
1469 if (wi::ltu_p (dim_arg, 1)
1470 || wi::gtu_p (dim_arg, GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
1471 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
1472 "dimension index", expr->value.function.isym->name,
1473 &expr->where);
1475 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1477 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
1478 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1479 dim_arg,
1480 build_int_cst (TREE_TYPE (dim_arg), 1));
1481 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
1482 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1483 dim_arg, tmp);
1484 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1485 boolean_type_node, cond, tmp);
1486 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1487 gfc_msg_fault);
1491 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
1492 one always has a dim_arg argument.
1494 m = this_image() - 1
1495 if (corank == 1)
1497 sub(1) = m + lcobound(corank)
1498 return;
1500 i = rank
1501 min_var = min (rank + corank - 2, rank + dim_arg - 1)
1502 for (;;)
1504 extent = gfc_extent(i)
1505 ml = m
1506 m = m/extent
1507 if (i >= min_var)
1508 goto exit_label
1511 exit_label:
1512 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
1513 : m + lcobound(corank)
1516 /* this_image () - 1. */
1517 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
1518 integer_zero_node);
1519 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
1520 fold_convert (type, tmp), build_int_cst (type, 1));
1521 if (corank == 1)
1523 /* sub(1) = m + lcobound(corank). */
1524 lbound = gfc_conv_descriptor_lbound_get (desc,
1525 build_int_cst (TREE_TYPE (gfc_array_index_type),
1526 corank+rank-1));
1527 lbound = fold_convert (type, lbound);
1528 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
1530 se->expr = tmp;
1531 return;
1534 m = gfc_create_var (type, NULL);
1535 ml = gfc_create_var (type, NULL);
1536 loop_var = gfc_create_var (integer_type_node, NULL);
1537 min_var = gfc_create_var (integer_type_node, NULL);
1539 /* m = this_image () - 1. */
1540 gfc_add_modify (&se->pre, m, tmp);
1542 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
1543 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
1544 fold_convert (integer_type_node, dim_arg),
1545 build_int_cst (integer_type_node, rank - 1));
1546 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
1547 build_int_cst (integer_type_node, rank + corank - 2),
1548 tmp);
1549 gfc_add_modify (&se->pre, min_var, tmp);
1551 /* i = rank. */
1552 tmp = build_int_cst (integer_type_node, rank);
1553 gfc_add_modify (&se->pre, loop_var, tmp);
1555 exit_label = gfc_build_label_decl (NULL_TREE);
1556 TREE_USED (exit_label) = 1;
1558 /* Loop body. */
1559 gfc_init_block (&loop);
1561 /* ml = m. */
1562 gfc_add_modify (&loop, ml, m);
1564 /* extent = ... */
1565 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
1566 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
1567 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1568 extent = fold_convert (type, extent);
1570 /* m = m/extent. */
1571 gfc_add_modify (&loop, m,
1572 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
1573 m, extent));
1575 /* Exit condition: if (i >= min_var) goto exit_label. */
1576 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, loop_var,
1577 min_var);
1578 tmp = build1_v (GOTO_EXPR, exit_label);
1579 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
1580 build_empty_stmt (input_location));
1581 gfc_add_expr_to_block (&loop, tmp);
1583 /* Increment loop variable: i++. */
1584 gfc_add_modify (&loop, loop_var,
1585 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
1586 loop_var,
1587 build_int_cst (integer_type_node, 1)));
1589 /* Making the loop... actually loop! */
1590 tmp = gfc_finish_block (&loop);
1591 tmp = build1_v (LOOP_EXPR, tmp);
1592 gfc_add_expr_to_block (&se->pre, tmp);
1594 /* The exit label. */
1595 tmp = build1_v (LABEL_EXPR, exit_label);
1596 gfc_add_expr_to_block (&se->pre, tmp);
1598 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
1599 : m + lcobound(corank) */
1601 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, dim_arg,
1602 build_int_cst (TREE_TYPE (dim_arg), corank));
1604 lbound = gfc_conv_descriptor_lbound_get (desc,
1605 fold_build2_loc (input_location, PLUS_EXPR,
1606 gfc_array_index_type, dim_arg,
1607 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
1608 lbound = fold_convert (type, lbound);
1610 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
1611 fold_build2_loc (input_location, MULT_EXPR, type,
1612 m, extent));
1613 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
1615 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
1616 fold_build2_loc (input_location, PLUS_EXPR, type,
1617 m, lbound));
1621 static void
1622 trans_image_index (gfc_se * se, gfc_expr *expr)
1624 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
1625 tmp, invalid_bound;
1626 gfc_se argse, subse;
1627 int rank, corank, codim;
1629 type = gfc_get_int_type (gfc_default_integer_kind);
1630 corank = gfc_get_corank (expr->value.function.actual->expr);
1631 rank = expr->value.function.actual->expr->rank;
1633 /* Obtain the descriptor of the COARRAY. */
1634 gfc_init_se (&argse, NULL);
1635 argse.want_coarray = 1;
1636 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
1637 gfc_add_block_to_block (&se->pre, &argse.pre);
1638 gfc_add_block_to_block (&se->post, &argse.post);
1639 desc = argse.expr;
1641 /* Obtain a handle to the SUB argument. */
1642 gfc_init_se (&subse, NULL);
1643 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
1644 gfc_add_block_to_block (&se->pre, &subse.pre);
1645 gfc_add_block_to_block (&se->post, &subse.post);
1646 subdesc = build_fold_indirect_ref_loc (input_location,
1647 gfc_conv_descriptor_data_get (subse.expr));
1649 /* Fortran 2008 does not require that the values remain in the cobounds,
1650 thus we need explicitly check this - and return 0 if they are exceeded. */
1652 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
1653 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
1654 invalid_bound = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1655 fold_convert (gfc_array_index_type, tmp),
1656 lbound);
1658 for (codim = corank + rank - 2; codim >= rank; codim--)
1660 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1661 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
1662 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
1663 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1664 fold_convert (gfc_array_index_type, tmp),
1665 lbound);
1666 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1667 boolean_type_node, invalid_bound, cond);
1668 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1669 fold_convert (gfc_array_index_type, tmp),
1670 ubound);
1671 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1672 boolean_type_node, invalid_bound, cond);
1675 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
1677 /* See Fortran 2008, C.10 for the following algorithm. */
1679 /* coindex = sub(corank) - lcobound(n). */
1680 coindex = fold_convert (gfc_array_index_type,
1681 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
1682 NULL));
1683 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
1684 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1685 fold_convert (gfc_array_index_type, coindex),
1686 lbound);
1688 for (codim = corank + rank - 2; codim >= rank; codim--)
1690 tree extent, ubound;
1692 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
1693 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1694 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
1695 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1697 /* coindex *= extent. */
1698 coindex = fold_build2_loc (input_location, MULT_EXPR,
1699 gfc_array_index_type, coindex, extent);
1701 /* coindex += sub(codim). */
1702 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
1703 coindex = fold_build2_loc (input_location, PLUS_EXPR,
1704 gfc_array_index_type, coindex,
1705 fold_convert (gfc_array_index_type, tmp));
1707 /* coindex -= lbound(codim). */
1708 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1709 coindex = fold_build2_loc (input_location, MINUS_EXPR,
1710 gfc_array_index_type, coindex, lbound);
1713 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
1714 fold_convert(type, coindex),
1715 build_int_cst (type, 1));
1717 /* Return 0 if "coindex" exceeds num_images(). */
1719 if (gfc_option.coarray == GFC_FCOARRAY_SINGLE)
1720 num_images = build_int_cst (type, 1);
1721 else
1723 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
1724 integer_zero_node,
1725 build_int_cst (integer_type_node, -1));
1726 num_images = fold_convert (type, tmp);
1729 tmp = gfc_create_var (type, NULL);
1730 gfc_add_modify (&se->pre, tmp, coindex);
1732 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, tmp,
1733 num_images);
1734 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
1735 cond,
1736 fold_convert (boolean_type_node, invalid_bound));
1737 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
1738 build_int_cst (type, 0), tmp);
1742 static void
1743 trans_num_images (gfc_se * se, gfc_expr *expr)
1745 tree tmp, distance, failed;
1746 gfc_se argse;
1748 if (expr->value.function.actual->expr)
1750 gfc_init_se (&argse, NULL);
1751 gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
1752 gfc_add_block_to_block (&se->pre, &argse.pre);
1753 gfc_add_block_to_block (&se->post, &argse.post);
1754 distance = fold_convert (integer_type_node, argse.expr);
1756 else
1757 distance = integer_zero_node;
1759 if (expr->value.function.actual->next->expr)
1761 gfc_init_se (&argse, NULL);
1762 gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
1763 gfc_add_block_to_block (&se->pre, &argse.pre);
1764 gfc_add_block_to_block (&se->post, &argse.post);
1765 failed = fold_convert (integer_type_node, argse.expr);
1767 else
1768 failed = build_int_cst (integer_type_node, -1);
1770 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
1771 distance, failed);
1772 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
1776 static void
1777 gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
1779 gfc_se argse;
1781 gfc_init_se (&argse, NULL);
1782 argse.data_not_needed = 1;
1783 argse.descriptor_only = 1;
1785 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
1786 gfc_add_block_to_block (&se->pre, &argse.pre);
1787 gfc_add_block_to_block (&se->post, &argse.post);
1789 se->expr = gfc_conv_descriptor_rank (argse.expr);
1793 /* Evaluate a single upper or lower bound. */
1794 /* TODO: bound intrinsic generates way too much unnecessary code. */
1796 static void
1797 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
1799 gfc_actual_arglist *arg;
1800 gfc_actual_arglist *arg2;
1801 tree desc;
1802 tree type;
1803 tree bound;
1804 tree tmp;
1805 tree cond, cond1, cond3, cond4, size;
1806 tree ubound;
1807 tree lbound;
1808 gfc_se argse;
1809 gfc_array_spec * as;
1810 bool assumed_rank_lb_one;
1812 arg = expr->value.function.actual;
1813 arg2 = arg->next;
1815 if (se->ss)
1817 /* Create an implicit second parameter from the loop variable. */
1818 gcc_assert (!arg2->expr);
1819 gcc_assert (se->loop->dimen == 1);
1820 gcc_assert (se->ss->info->expr == expr);
1821 gfc_advance_se_ss_chain (se);
1822 bound = se->loop->loopvar[0];
1823 bound = fold_build2_loc (input_location, MINUS_EXPR,
1824 gfc_array_index_type, bound,
1825 se->loop->from[0]);
1827 else
1829 /* use the passed argument. */
1830 gcc_assert (arg2->expr);
1831 gfc_init_se (&argse, NULL);
1832 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
1833 gfc_add_block_to_block (&se->pre, &argse.pre);
1834 bound = argse.expr;
1835 /* Convert from one based to zero based. */
1836 bound = fold_build2_loc (input_location, MINUS_EXPR,
1837 gfc_array_index_type, bound,
1838 gfc_index_one_node);
1841 /* TODO: don't re-evaluate the descriptor on each iteration. */
1842 /* Get a descriptor for the first parameter. */
1843 gfc_init_se (&argse, NULL);
1844 gfc_conv_expr_descriptor (&argse, arg->expr);
1845 gfc_add_block_to_block (&se->pre, &argse.pre);
1846 gfc_add_block_to_block (&se->post, &argse.post);
1848 desc = argse.expr;
1850 as = gfc_get_full_arrayspec_from_expr (arg->expr);
1852 if (INTEGER_CST_P (bound))
1854 if (((!as || as->type != AS_ASSUMED_RANK)
1855 && wi::geu_p (bound, GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
1856 || wi::gtu_p (bound, GFC_MAX_DIMENSIONS))
1857 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
1858 "dimension index", upper ? "UBOUND" : "LBOUND",
1859 &expr->where);
1862 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
1864 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1866 bound = gfc_evaluate_now (bound, &se->pre);
1867 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1868 bound, build_int_cst (TREE_TYPE (bound), 0));
1869 if (as && as->type == AS_ASSUMED_RANK)
1870 tmp = gfc_conv_descriptor_rank (desc);
1871 else
1872 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
1873 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1874 bound, fold_convert(TREE_TYPE (bound), tmp));
1875 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1876 boolean_type_node, cond, tmp);
1877 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1878 gfc_msg_fault);
1882 /* Take care of the lbound shift for assumed-rank arrays, which are
1883 nonallocatable and nonpointers. Those has a lbound of 1. */
1884 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
1885 && ((arg->expr->ts.type != BT_CLASS
1886 && !arg->expr->symtree->n.sym->attr.allocatable
1887 && !arg->expr->symtree->n.sym->attr.pointer)
1888 || (arg->expr->ts.type == BT_CLASS
1889 && !CLASS_DATA (arg->expr)->attr.allocatable
1890 && !CLASS_DATA (arg->expr)->attr.class_pointer));
1892 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
1893 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
1895 /* 13.14.53: Result value for LBOUND
1897 Case (i): For an array section or for an array expression other than a
1898 whole array or array structure component, LBOUND(ARRAY, DIM)
1899 has the value 1. For a whole array or array structure
1900 component, LBOUND(ARRAY, DIM) has the value:
1901 (a) equal to the lower bound for subscript DIM of ARRAY if
1902 dimension DIM of ARRAY does not have extent zero
1903 or if ARRAY is an assumed-size array of rank DIM,
1904 or (b) 1 otherwise.
1906 13.14.113: Result value for UBOUND
1908 Case (i): For an array section or for an array expression other than a
1909 whole array or array structure component, UBOUND(ARRAY, DIM)
1910 has the value equal to the number of elements in the given
1911 dimension; otherwise, it has a value equal to the upper bound
1912 for subscript DIM of ARRAY if dimension DIM of ARRAY does
1913 not have size zero and has value zero if dimension DIM has
1914 size zero. */
1916 if (!upper && assumed_rank_lb_one)
1917 se->expr = gfc_index_one_node;
1918 else if (as)
1920 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
1922 cond1 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1923 ubound, lbound);
1924 cond3 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1925 stride, gfc_index_zero_node);
1926 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1927 boolean_type_node, cond3, cond1);
1928 cond4 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1929 stride, gfc_index_zero_node);
1931 if (upper)
1933 tree cond5;
1934 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1935 boolean_type_node, cond3, cond4);
1936 cond5 = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1937 gfc_index_one_node, lbound);
1938 cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1939 boolean_type_node, cond4, cond5);
1941 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1942 boolean_type_node, cond, cond5);
1944 if (assumed_rank_lb_one)
1946 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1947 gfc_array_index_type, ubound, lbound);
1948 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1949 gfc_array_index_type, tmp, gfc_index_one_node);
1951 else
1952 tmp = ubound;
1954 se->expr = fold_build3_loc (input_location, COND_EXPR,
1955 gfc_array_index_type, cond,
1956 tmp, gfc_index_zero_node);
1958 else
1960 if (as->type == AS_ASSUMED_SIZE)
1961 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1962 bound, build_int_cst (TREE_TYPE (bound),
1963 arg->expr->rank - 1));
1964 else
1965 cond = boolean_false_node;
1967 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1968 boolean_type_node, cond3, cond4);
1969 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1970 boolean_type_node, cond, cond1);
1972 se->expr = fold_build3_loc (input_location, COND_EXPR,
1973 gfc_array_index_type, cond,
1974 lbound, gfc_index_one_node);
1977 else
1979 if (upper)
1981 size = fold_build2_loc (input_location, MINUS_EXPR,
1982 gfc_array_index_type, ubound, lbound);
1983 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
1984 gfc_array_index_type, size,
1985 gfc_index_one_node);
1986 se->expr = fold_build2_loc (input_location, MAX_EXPR,
1987 gfc_array_index_type, se->expr,
1988 gfc_index_zero_node);
1990 else
1991 se->expr = gfc_index_one_node;
1994 type = gfc_typenode_for_spec (&expr->ts);
1995 se->expr = convert (type, se->expr);
1999 static void
2000 conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
2002 gfc_actual_arglist *arg;
2003 gfc_actual_arglist *arg2;
2004 gfc_se argse;
2005 tree bound, resbound, resbound2, desc, cond, tmp;
2006 tree type;
2007 int corank;
2009 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
2010 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
2011 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
2013 arg = expr->value.function.actual;
2014 arg2 = arg->next;
2016 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
2017 corank = gfc_get_corank (arg->expr);
2019 gfc_init_se (&argse, NULL);
2020 argse.want_coarray = 1;
2022 gfc_conv_expr_descriptor (&argse, arg->expr);
2023 gfc_add_block_to_block (&se->pre, &argse.pre);
2024 gfc_add_block_to_block (&se->post, &argse.post);
2025 desc = argse.expr;
2027 if (se->ss)
2029 /* Create an implicit second parameter from the loop variable. */
2030 gcc_assert (!arg2->expr);
2031 gcc_assert (corank > 0);
2032 gcc_assert (se->loop->dimen == 1);
2033 gcc_assert (se->ss->info->expr == expr);
2035 bound = se->loop->loopvar[0];
2036 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2037 bound, gfc_rank_cst[arg->expr->rank]);
2038 gfc_advance_se_ss_chain (se);
2040 else
2042 /* use the passed argument. */
2043 gcc_assert (arg2->expr);
2044 gfc_init_se (&argse, NULL);
2045 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2046 gfc_add_block_to_block (&se->pre, &argse.pre);
2047 bound = argse.expr;
2049 if (INTEGER_CST_P (bound))
2051 if (wi::ltu_p (bound, 1)
2052 || wi::gtu_p (bound, GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2053 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
2054 "dimension index", expr->value.function.isym->name,
2055 &expr->where);
2057 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2059 bound = gfc_evaluate_now (bound, &se->pre);
2060 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2061 bound, build_int_cst (TREE_TYPE (bound), 1));
2062 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2063 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2064 bound, tmp);
2065 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2066 boolean_type_node, cond, tmp);
2067 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2068 gfc_msg_fault);
2072 /* Subtract 1 to get to zero based and add dimensions. */
2073 switch (arg->expr->rank)
2075 case 0:
2076 bound = fold_build2_loc (input_location, MINUS_EXPR,
2077 gfc_array_index_type, bound,
2078 gfc_index_one_node);
2079 case 1:
2080 break;
2081 default:
2082 bound = fold_build2_loc (input_location, PLUS_EXPR,
2083 gfc_array_index_type, bound,
2084 gfc_rank_cst[arg->expr->rank - 1]);
2088 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
2090 /* Handle UCOBOUND with special handling of the last codimension. */
2091 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
2093 /* Last codimension: For -fcoarray=single just return
2094 the lcobound - otherwise add
2095 ceiling (real (num_images ()) / real (size)) - 1
2096 = (num_images () + size - 1) / size - 1
2097 = (num_images - 1) / size(),
2098 where size is the product of the extent of all but the last
2099 codimension. */
2101 if (gfc_option.coarray != GFC_FCOARRAY_SINGLE && corank > 1)
2103 tree cosize;
2105 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
2106 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
2107 2, integer_zero_node,
2108 build_int_cst (integer_type_node, -1));
2109 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2110 gfc_array_index_type,
2111 fold_convert (gfc_array_index_type, tmp),
2112 build_int_cst (gfc_array_index_type, 1));
2113 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
2114 gfc_array_index_type, tmp,
2115 fold_convert (gfc_array_index_type, cosize));
2116 resbound = fold_build2_loc (input_location, PLUS_EXPR,
2117 gfc_array_index_type, resbound, tmp);
2119 else if (gfc_option.coarray != GFC_FCOARRAY_SINGLE)
2121 /* ubound = lbound + num_images() - 1. */
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 resbound = fold_build2_loc (input_location, PLUS_EXPR,
2130 gfc_array_index_type, resbound, tmp);
2133 if (corank > 1)
2135 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2136 bound,
2137 build_int_cst (TREE_TYPE (bound),
2138 arg->expr->rank + corank - 1));
2140 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
2141 se->expr = fold_build3_loc (input_location, COND_EXPR,
2142 gfc_array_index_type, cond,
2143 resbound, resbound2);
2145 else
2146 se->expr = resbound;
2148 else
2149 se->expr = resbound;
2151 type = gfc_typenode_for_spec (&expr->ts);
2152 se->expr = convert (type, se->expr);
2156 static void
2157 conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
2159 gfc_actual_arglist *array_arg;
2160 gfc_actual_arglist *dim_arg;
2161 gfc_se argse;
2162 tree desc, tmp;
2164 array_arg = expr->value.function.actual;
2165 dim_arg = array_arg->next;
2167 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
2169 gfc_init_se (&argse, NULL);
2170 gfc_conv_expr_descriptor (&argse, array_arg->expr);
2171 gfc_add_block_to_block (&se->pre, &argse.pre);
2172 gfc_add_block_to_block (&se->post, &argse.post);
2173 desc = argse.expr;
2175 gcc_assert (dim_arg->expr);
2176 gfc_init_se (&argse, NULL);
2177 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
2178 gfc_add_block_to_block (&se->pre, &argse.pre);
2179 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2180 argse.expr, gfc_index_one_node);
2181 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
2185 static void
2186 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
2188 tree arg, cabs;
2190 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
2192 switch (expr->value.function.actual->expr->ts.type)
2194 case BT_INTEGER:
2195 case BT_REAL:
2196 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
2197 arg);
2198 break;
2200 case BT_COMPLEX:
2201 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
2202 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
2203 break;
2205 default:
2206 gcc_unreachable ();
2211 /* Create a complex value from one or two real components. */
2213 static void
2214 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
2216 tree real;
2217 tree imag;
2218 tree type;
2219 tree *args;
2220 unsigned int num_args;
2222 num_args = gfc_intrinsic_argument_list_length (expr);
2223 args = XALLOCAVEC (tree, num_args);
2225 type = gfc_typenode_for_spec (&expr->ts);
2226 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2227 real = convert (TREE_TYPE (type), args[0]);
2228 if (both)
2229 imag = convert (TREE_TYPE (type), args[1]);
2230 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
2232 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
2233 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
2234 imag = convert (TREE_TYPE (type), imag);
2236 else
2237 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
2239 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
2243 /* Remainder function MOD(A, P) = A - INT(A / P) * P
2244 MODULO(A, P) = A - FLOOR (A / P) * P
2246 The obvious algorithms above are numerically instable for large
2247 arguments, hence these intrinsics are instead implemented via calls
2248 to the fmod family of functions. It is the responsibility of the
2249 user to ensure that the second argument is non-zero. */
2251 static void
2252 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
2254 tree type;
2255 tree tmp;
2256 tree test;
2257 tree test2;
2258 tree fmod;
2259 tree zero;
2260 tree args[2];
2262 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2264 switch (expr->ts.type)
2266 case BT_INTEGER:
2267 /* Integer case is easy, we've got a builtin op. */
2268 type = TREE_TYPE (args[0]);
2270 if (modulo)
2271 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
2272 args[0], args[1]);
2273 else
2274 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
2275 args[0], args[1]);
2276 break;
2278 case BT_REAL:
2279 fmod = NULL_TREE;
2280 /* Check if we have a builtin fmod. */
2281 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
2283 /* The builtin should always be available. */
2284 gcc_assert (fmod != NULL_TREE);
2286 tmp = build_addr (fmod, current_function_decl);
2287 se->expr = build_call_array_loc (input_location,
2288 TREE_TYPE (TREE_TYPE (fmod)),
2289 tmp, 2, args);
2290 if (modulo == 0)
2291 return;
2293 type = TREE_TYPE (args[0]);
2295 args[0] = gfc_evaluate_now (args[0], &se->pre);
2296 args[1] = gfc_evaluate_now (args[1], &se->pre);
2298 /* Definition:
2299 modulo = arg - floor (arg/arg2) * arg2
2301 In order to calculate the result accurately, we use the fmod
2302 function as follows.
2304 res = fmod (arg, arg2);
2305 if (res)
2307 if ((arg < 0) xor (arg2 < 0))
2308 res += arg2;
2310 else
2311 res = copysign (0., arg2);
2313 => As two nested ternary exprs:
2315 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
2316 : copysign (0., arg2);
2320 zero = gfc_build_const (type, integer_zero_node);
2321 tmp = gfc_evaluate_now (se->expr, &se->pre);
2322 if (!flag_signed_zeros)
2324 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2325 args[0], zero);
2326 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2327 args[1], zero);
2328 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
2329 boolean_type_node, test, test2);
2330 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
2331 tmp, zero);
2332 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2333 boolean_type_node, test, test2);
2334 test = gfc_evaluate_now (test, &se->pre);
2335 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
2336 fold_build2_loc (input_location,
2337 PLUS_EXPR,
2338 type, tmp, args[1]),
2339 tmp);
2341 else
2343 tree expr1, copysign, cscall;
2344 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
2345 expr->ts.kind);
2346 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2347 args[0], zero);
2348 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2349 args[1], zero);
2350 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
2351 boolean_type_node, test, test2);
2352 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
2353 fold_build2_loc (input_location,
2354 PLUS_EXPR,
2355 type, tmp, args[1]),
2356 tmp);
2357 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
2358 tmp, zero);
2359 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
2360 args[1]);
2361 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
2362 expr1, cscall);
2364 return;
2366 default:
2367 gcc_unreachable ();
2371 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
2372 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
2373 where the right shifts are logical (i.e. 0's are shifted in).
2374 Because SHIFT_EXPR's want shifts strictly smaller than the integral
2375 type width, we have to special-case both S == 0 and S == BITSIZE(J):
2376 DSHIFTL(I,J,0) = I
2377 DSHIFTL(I,J,BITSIZE) = J
2378 DSHIFTR(I,J,0) = J
2379 DSHIFTR(I,J,BITSIZE) = I. */
2381 static void
2382 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
2384 tree type, utype, stype, arg1, arg2, shift, res, left, right;
2385 tree args[3], cond, tmp;
2386 int bitsize;
2388 gfc_conv_intrinsic_function_args (se, expr, args, 3);
2390 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
2391 type = TREE_TYPE (args[0]);
2392 bitsize = TYPE_PRECISION (type);
2393 utype = unsigned_type_for (type);
2394 stype = TREE_TYPE (args[2]);
2396 arg1 = gfc_evaluate_now (args[0], &se->pre);
2397 arg2 = gfc_evaluate_now (args[1], &se->pre);
2398 shift = gfc_evaluate_now (args[2], &se->pre);
2400 /* The generic case. */
2401 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
2402 build_int_cst (stype, bitsize), shift);
2403 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
2404 arg1, dshiftl ? shift : tmp);
2406 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
2407 fold_convert (utype, arg2), dshiftl ? tmp : shift);
2408 right = fold_convert (type, right);
2410 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
2412 /* Special cases. */
2413 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
2414 build_int_cst (stype, 0));
2415 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
2416 dshiftl ? arg1 : arg2, res);
2418 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
2419 build_int_cst (stype, bitsize));
2420 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
2421 dshiftl ? arg2 : arg1, res);
2423 se->expr = res;
2427 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
2429 static void
2430 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
2432 tree val;
2433 tree tmp;
2434 tree type;
2435 tree zero;
2436 tree args[2];
2438 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2439 type = TREE_TYPE (args[0]);
2441 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
2442 val = gfc_evaluate_now (val, &se->pre);
2444 zero = gfc_build_const (type, integer_zero_node);
2445 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, val, zero);
2446 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
2450 /* SIGN(A, B) is absolute value of A times sign of B.
2451 The real value versions use library functions to ensure the correct
2452 handling of negative zero. Integer case implemented as:
2453 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
2456 static void
2457 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
2459 tree tmp;
2460 tree type;
2461 tree args[2];
2463 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2464 if (expr->ts.type == BT_REAL)
2466 tree abs;
2468 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
2469 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
2471 /* We explicitly have to ignore the minus sign. We do so by using
2472 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
2473 if (!gfc_option.flag_sign_zero
2474 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
2476 tree cond, zero;
2477 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
2478 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2479 args[1], zero);
2480 se->expr = fold_build3_loc (input_location, COND_EXPR,
2481 TREE_TYPE (args[0]), cond,
2482 build_call_expr_loc (input_location, abs, 1,
2483 args[0]),
2484 build_call_expr_loc (input_location, tmp, 2,
2485 args[0], args[1]));
2487 else
2488 se->expr = build_call_expr_loc (input_location, tmp, 2,
2489 args[0], args[1]);
2490 return;
2493 /* Having excluded floating point types, we know we are now dealing
2494 with signed integer types. */
2495 type = TREE_TYPE (args[0]);
2497 /* Args[0] is used multiple times below. */
2498 args[0] = gfc_evaluate_now (args[0], &se->pre);
2500 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
2501 the signs of A and B are the same, and of all ones if they differ. */
2502 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
2503 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
2504 build_int_cst (type, TYPE_PRECISION (type) - 1));
2505 tmp = gfc_evaluate_now (tmp, &se->pre);
2507 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
2508 is all ones (i.e. -1). */
2509 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
2510 fold_build2_loc (input_location, PLUS_EXPR,
2511 type, args[0], tmp), tmp);
2515 /* Test for the presence of an optional argument. */
2517 static void
2518 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
2520 gfc_expr *arg;
2522 arg = expr->value.function.actual->expr;
2523 gcc_assert (arg->expr_type == EXPR_VARIABLE);
2524 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
2525 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
2529 /* Calculate the double precision product of two single precision values. */
2531 static void
2532 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
2534 tree type;
2535 tree args[2];
2537 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2539 /* Convert the args to double precision before multiplying. */
2540 type = gfc_typenode_for_spec (&expr->ts);
2541 args[0] = convert (type, args[0]);
2542 args[1] = convert (type, args[1]);
2543 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
2544 args[1]);
2548 /* Return a length one character string containing an ascii character. */
2550 static void
2551 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
2553 tree arg[2];
2554 tree var;
2555 tree type;
2556 unsigned int num_args;
2558 num_args = gfc_intrinsic_argument_list_length (expr);
2559 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
2561 type = gfc_get_char_type (expr->ts.kind);
2562 var = gfc_create_var (type, "char");
2564 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
2565 gfc_add_modify (&se->pre, var, arg[0]);
2566 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
2567 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
2571 static void
2572 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
2574 tree var;
2575 tree len;
2576 tree tmp;
2577 tree cond;
2578 tree fndecl;
2579 tree *args;
2580 unsigned int num_args;
2582 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2583 args = XALLOCAVEC (tree, num_args);
2585 var = gfc_create_var (pchar_type_node, "pstr");
2586 len = gfc_create_var (gfc_charlen_type_node, "len");
2588 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2589 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2590 args[1] = gfc_build_addr_expr (NULL_TREE, len);
2592 fndecl = build_addr (gfor_fndecl_ctime, current_function_decl);
2593 tmp = build_call_array_loc (input_location,
2594 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
2595 fndecl, num_args, args);
2596 gfc_add_expr_to_block (&se->pre, tmp);
2598 /* Free the temporary afterwards, if necessary. */
2599 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2600 len, build_int_cst (TREE_TYPE (len), 0));
2601 tmp = gfc_call_free (var);
2602 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2603 gfc_add_expr_to_block (&se->post, tmp);
2605 se->expr = var;
2606 se->string_length = len;
2610 static void
2611 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
2613 tree var;
2614 tree len;
2615 tree tmp;
2616 tree cond;
2617 tree fndecl;
2618 tree *args;
2619 unsigned int num_args;
2621 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2622 args = XALLOCAVEC (tree, num_args);
2624 var = gfc_create_var (pchar_type_node, "pstr");
2625 len = gfc_create_var (gfc_charlen_type_node, "len");
2627 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2628 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2629 args[1] = gfc_build_addr_expr (NULL_TREE, len);
2631 fndecl = build_addr (gfor_fndecl_fdate, current_function_decl);
2632 tmp = build_call_array_loc (input_location,
2633 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
2634 fndecl, num_args, args);
2635 gfc_add_expr_to_block (&se->pre, tmp);
2637 /* Free the temporary afterwards, if necessary. */
2638 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2639 len, build_int_cst (TREE_TYPE (len), 0));
2640 tmp = gfc_call_free (var);
2641 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2642 gfc_add_expr_to_block (&se->post, tmp);
2644 se->expr = var;
2645 se->string_length = len;
2649 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
2650 conversions. */
2652 static tree
2653 conv_intrinsic_system_clock (gfc_code *code)
2655 stmtblock_t block;
2656 gfc_se count_se, count_rate_se, count_max_se;
2657 tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
2658 tree type, tmp;
2659 int kind;
2661 gfc_expr *count = code->ext.actual->expr;
2662 gfc_expr *count_rate = code->ext.actual->next->expr;
2663 gfc_expr *count_max = code->ext.actual->next->next->expr;
2665 /* The INTEGER(8) version has higher precision, it is used if both COUNT
2666 and COUNT_MAX can hold 64-bit values, or are absent. */
2667 if ((!count || count->ts.kind >= 8)
2668 && (!count_max || count_max->ts.kind >= 8))
2669 kind = 8;
2670 else
2671 kind = gfc_default_integer_kind;
2672 type = gfc_get_int_type (kind);
2674 /* Evaluate our arguments. */
2675 if (count)
2677 gfc_init_se (&count_se, NULL);
2678 gfc_conv_expr (&count_se, count);
2681 if (count_rate)
2683 gfc_init_se (&count_rate_se, NULL);
2684 gfc_conv_expr (&count_rate_se, count_rate);
2687 if (count_max)
2689 gfc_init_se (&count_max_se, NULL);
2690 gfc_conv_expr (&count_max_se, count_max);
2693 /* Prepare temporary variables if we need them. */
2694 if (count && count->ts.kind != kind)
2695 arg1 = gfc_create_var (type, "count");
2696 else if (count)
2697 arg1 = count_se.expr;
2699 if (count_rate && (count_rate->ts.kind != kind
2700 || count_rate->ts.type != BT_INTEGER))
2701 arg2 = gfc_create_var (type, "count_rate");
2702 else if (count_rate)
2703 arg2 = count_rate_se.expr;
2705 if (count_max && count_max->ts.kind != kind)
2706 arg3 = gfc_create_var (type, "count_max");
2707 else if (count_max)
2708 arg3 = count_max_se.expr;
2710 /* Make the function call. */
2711 gfc_init_block (&block);
2712 tmp = build_call_expr_loc (input_location,
2713 kind == 4 ? gfor_fndecl_system_clock4
2714 : gfor_fndecl_system_clock8,
2716 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
2717 : null_pointer_node,
2718 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
2719 : null_pointer_node,
2720 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
2721 : null_pointer_node);
2722 gfc_add_expr_to_block (&block, tmp);
2724 /* And store values back if needed. */
2725 if (arg1 && arg1 != count_se.expr)
2726 gfc_add_modify (&block, count_se.expr,
2727 fold_convert (TREE_TYPE (count_se.expr), arg1));
2728 if (arg2 && arg2 != count_rate_se.expr)
2729 gfc_add_modify (&block, count_rate_se.expr,
2730 fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
2731 if (arg3 && arg3 != count_max_se.expr)
2732 gfc_add_modify (&block, count_max_se.expr,
2733 fold_convert (TREE_TYPE (count_max_se.expr), arg3));
2735 return gfc_finish_block (&block);
2739 /* Return a character string containing the tty name. */
2741 static void
2742 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
2744 tree var;
2745 tree len;
2746 tree tmp;
2747 tree cond;
2748 tree fndecl;
2749 tree *args;
2750 unsigned int num_args;
2752 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2753 args = XALLOCAVEC (tree, num_args);
2755 var = gfc_create_var (pchar_type_node, "pstr");
2756 len = gfc_create_var (gfc_charlen_type_node, "len");
2758 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2759 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2760 args[1] = gfc_build_addr_expr (NULL_TREE, len);
2762 fndecl = build_addr (gfor_fndecl_ttynam, current_function_decl);
2763 tmp = build_call_array_loc (input_location,
2764 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
2765 fndecl, num_args, args);
2766 gfc_add_expr_to_block (&se->pre, tmp);
2768 /* Free the temporary afterwards, if necessary. */
2769 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2770 len, build_int_cst (TREE_TYPE (len), 0));
2771 tmp = gfc_call_free (var);
2772 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2773 gfc_add_expr_to_block (&se->post, tmp);
2775 se->expr = var;
2776 se->string_length = len;
2780 /* Get the minimum/maximum value of all the parameters.
2781 minmax (a1, a2, a3, ...)
2783 mvar = a1;
2784 if (a2 .op. mvar || isnan (mvar))
2785 mvar = a2;
2786 if (a3 .op. mvar || isnan (mvar))
2787 mvar = a3;
2789 return mvar
2793 /* TODO: Mismatching types can occur when specific names are used.
2794 These should be handled during resolution. */
2795 static void
2796 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
2798 tree tmp;
2799 tree mvar;
2800 tree val;
2801 tree thencase;
2802 tree *args;
2803 tree type;
2804 gfc_actual_arglist *argexpr;
2805 unsigned int i, nargs;
2807 nargs = gfc_intrinsic_argument_list_length (expr);
2808 args = XALLOCAVEC (tree, nargs);
2810 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
2811 type = gfc_typenode_for_spec (&expr->ts);
2813 argexpr = expr->value.function.actual;
2814 if (TREE_TYPE (args[0]) != type)
2815 args[0] = convert (type, args[0]);
2816 /* Only evaluate the argument once. */
2817 if (TREE_CODE (args[0]) != VAR_DECL && !TREE_CONSTANT (args[0]))
2818 args[0] = gfc_evaluate_now (args[0], &se->pre);
2820 mvar = gfc_create_var (type, "M");
2821 gfc_add_modify (&se->pre, mvar, args[0]);
2822 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
2824 tree cond, isnan;
2826 val = args[i];
2828 /* Handle absent optional arguments by ignoring the comparison. */
2829 if (argexpr->expr->expr_type == EXPR_VARIABLE
2830 && argexpr->expr->symtree->n.sym->attr.optional
2831 && TREE_CODE (val) == INDIRECT_REF)
2832 cond = fold_build2_loc (input_location,
2833 NE_EXPR, boolean_type_node,
2834 TREE_OPERAND (val, 0),
2835 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
2836 else
2838 cond = NULL_TREE;
2840 /* Only evaluate the argument once. */
2841 if (TREE_CODE (val) != VAR_DECL && !TREE_CONSTANT (val))
2842 val = gfc_evaluate_now (val, &se->pre);
2845 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
2847 tmp = fold_build2_loc (input_location, op, boolean_type_node,
2848 convert (type, val), mvar);
2850 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
2851 __builtin_isnan might be made dependent on that module being loaded,
2852 to help performance of programs that don't rely on IEEE semantics. */
2853 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
2855 isnan = build_call_expr_loc (input_location,
2856 builtin_decl_explicit (BUILT_IN_ISNAN),
2857 1, mvar);
2858 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2859 boolean_type_node, tmp,
2860 fold_convert (boolean_type_node, isnan));
2862 tmp = build3_v (COND_EXPR, tmp, thencase,
2863 build_empty_stmt (input_location));
2865 if (cond != NULL_TREE)
2866 tmp = build3_v (COND_EXPR, cond, tmp,
2867 build_empty_stmt (input_location));
2869 gfc_add_expr_to_block (&se->pre, tmp);
2870 argexpr = argexpr->next;
2872 se->expr = mvar;
2876 /* Generate library calls for MIN and MAX intrinsics for character
2877 variables. */
2878 static void
2879 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
2881 tree *args;
2882 tree var, len, fndecl, tmp, cond, function;
2883 unsigned int nargs;
2885 nargs = gfc_intrinsic_argument_list_length (expr);
2886 args = XALLOCAVEC (tree, nargs + 4);
2887 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
2889 /* Create the result variables. */
2890 len = gfc_create_var (gfc_charlen_type_node, "len");
2891 args[0] = gfc_build_addr_expr (NULL_TREE, len);
2892 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
2893 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
2894 args[2] = build_int_cst (integer_type_node, op);
2895 args[3] = build_int_cst (integer_type_node, nargs / 2);
2897 if (expr->ts.kind == 1)
2898 function = gfor_fndecl_string_minmax;
2899 else if (expr->ts.kind == 4)
2900 function = gfor_fndecl_string_minmax_char4;
2901 else
2902 gcc_unreachable ();
2904 /* Make the function call. */
2905 fndecl = build_addr (function, current_function_decl);
2906 tmp = build_call_array_loc (input_location,
2907 TREE_TYPE (TREE_TYPE (function)), fndecl,
2908 nargs + 4, args);
2909 gfc_add_expr_to_block (&se->pre, tmp);
2911 /* Free the temporary afterwards, if necessary. */
2912 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2913 len, build_int_cst (TREE_TYPE (len), 0));
2914 tmp = gfc_call_free (var);
2915 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2916 gfc_add_expr_to_block (&se->post, tmp);
2918 se->expr = var;
2919 se->string_length = len;
2923 /* Create a symbol node for this intrinsic. The symbol from the frontend
2924 has the generic name. */
2926 static gfc_symbol *
2927 gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
2929 gfc_symbol *sym;
2931 /* TODO: Add symbols for intrinsic function to the global namespace. */
2932 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
2933 sym = gfc_new_symbol (expr->value.function.name, NULL);
2935 sym->ts = expr->ts;
2936 sym->attr.external = 1;
2937 sym->attr.function = 1;
2938 sym->attr.always_explicit = 1;
2939 sym->attr.proc = PROC_INTRINSIC;
2940 sym->attr.flavor = FL_PROCEDURE;
2941 sym->result = sym;
2942 if (expr->rank > 0)
2944 sym->attr.dimension = 1;
2945 sym->as = gfc_get_array_spec ();
2946 sym->as->type = AS_ASSUMED_SHAPE;
2947 sym->as->rank = expr->rank;
2950 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
2951 ignore_optional ? expr->value.function.actual
2952 : NULL);
2954 return sym;
2957 /* Generate a call to an external intrinsic function. */
2958 static void
2959 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
2961 gfc_symbol *sym;
2962 vec<tree, va_gc> *append_args;
2964 gcc_assert (!se->ss || se->ss->info->expr == expr);
2966 if (se->ss)
2967 gcc_assert (expr->rank > 0);
2968 else
2969 gcc_assert (expr->rank == 0);
2971 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
2973 /* Calls to libgfortran_matmul need to be appended special arguments,
2974 to be able to call the BLAS ?gemm functions if required and possible. */
2975 append_args = NULL;
2976 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
2977 && sym->ts.type != BT_LOGICAL)
2979 tree cint = gfc_get_int_type (gfc_c_int_kind);
2981 if (gfc_option.flag_external_blas
2982 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
2983 && (sym->ts.kind == 4 || sym->ts.kind == 8))
2985 tree gemm_fndecl;
2987 if (sym->ts.type == BT_REAL)
2989 if (sym->ts.kind == 4)
2990 gemm_fndecl = gfor_fndecl_sgemm;
2991 else
2992 gemm_fndecl = gfor_fndecl_dgemm;
2994 else
2996 if (sym->ts.kind == 4)
2997 gemm_fndecl = gfor_fndecl_cgemm;
2998 else
2999 gemm_fndecl = gfor_fndecl_zgemm;
3002 vec_alloc (append_args, 3);
3003 append_args->quick_push (build_int_cst (cint, 1));
3004 append_args->quick_push (build_int_cst (cint,
3005 gfc_option.blas_matmul_limit));
3006 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
3007 gemm_fndecl));
3009 else
3011 vec_alloc (append_args, 3);
3012 append_args->quick_push (build_int_cst (cint, 0));
3013 append_args->quick_push (build_int_cst (cint, 0));
3014 append_args->quick_push (null_pointer_node);
3018 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
3019 append_args);
3020 gfc_free_symbol (sym);
3023 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
3024 Implemented as
3025 any(a)
3027 forall (i=...)
3028 if (a[i] != 0)
3029 return 1
3030 end forall
3031 return 0
3033 all(a)
3035 forall (i=...)
3036 if (a[i] == 0)
3037 return 0
3038 end forall
3039 return 1
3042 static void
3043 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
3045 tree resvar;
3046 stmtblock_t block;
3047 stmtblock_t body;
3048 tree type;
3049 tree tmp;
3050 tree found;
3051 gfc_loopinfo loop;
3052 gfc_actual_arglist *actual;
3053 gfc_ss *arrayss;
3054 gfc_se arrayse;
3055 tree exit_label;
3057 if (se->ss)
3059 gfc_conv_intrinsic_funcall (se, expr);
3060 return;
3063 actual = expr->value.function.actual;
3064 type = gfc_typenode_for_spec (&expr->ts);
3065 /* Initialize the result. */
3066 resvar = gfc_create_var (type, "test");
3067 if (op == EQ_EXPR)
3068 tmp = convert (type, boolean_true_node);
3069 else
3070 tmp = convert (type, boolean_false_node);
3071 gfc_add_modify (&se->pre, resvar, tmp);
3073 /* Walk the arguments. */
3074 arrayss = gfc_walk_expr (actual->expr);
3075 gcc_assert (arrayss != gfc_ss_terminator);
3077 /* Initialize the scalarizer. */
3078 gfc_init_loopinfo (&loop);
3079 exit_label = gfc_build_label_decl (NULL_TREE);
3080 TREE_USED (exit_label) = 1;
3081 gfc_add_ss_to_loop (&loop, arrayss);
3083 /* Initialize the loop. */
3084 gfc_conv_ss_startstride (&loop);
3085 gfc_conv_loop_setup (&loop, &expr->where);
3087 gfc_mark_ss_chain_used (arrayss, 1);
3088 /* Generate the loop body. */
3089 gfc_start_scalarized_body (&loop, &body);
3091 /* If the condition matches then set the return value. */
3092 gfc_start_block (&block);
3093 if (op == EQ_EXPR)
3094 tmp = convert (type, boolean_false_node);
3095 else
3096 tmp = convert (type, boolean_true_node);
3097 gfc_add_modify (&block, resvar, tmp);
3099 /* And break out of the loop. */
3100 tmp = build1_v (GOTO_EXPR, exit_label);
3101 gfc_add_expr_to_block (&block, tmp);
3103 found = gfc_finish_block (&block);
3105 /* Check this element. */
3106 gfc_init_se (&arrayse, NULL);
3107 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3108 arrayse.ss = arrayss;
3109 gfc_conv_expr_val (&arrayse, actual->expr);
3111 gfc_add_block_to_block (&body, &arrayse.pre);
3112 tmp = fold_build2_loc (input_location, op, boolean_type_node, arrayse.expr,
3113 build_int_cst (TREE_TYPE (arrayse.expr), 0));
3114 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
3115 gfc_add_expr_to_block (&body, tmp);
3116 gfc_add_block_to_block (&body, &arrayse.post);
3118 gfc_trans_scalarizing_loops (&loop, &body);
3120 /* Add the exit label. */
3121 tmp = build1_v (LABEL_EXPR, exit_label);
3122 gfc_add_expr_to_block (&loop.pre, tmp);
3124 gfc_add_block_to_block (&se->pre, &loop.pre);
3125 gfc_add_block_to_block (&se->pre, &loop.post);
3126 gfc_cleanup_loop (&loop);
3128 se->expr = resvar;
3131 /* COUNT(A) = Number of true elements in A. */
3132 static void
3133 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
3135 tree resvar;
3136 tree type;
3137 stmtblock_t body;
3138 tree tmp;
3139 gfc_loopinfo loop;
3140 gfc_actual_arglist *actual;
3141 gfc_ss *arrayss;
3142 gfc_se arrayse;
3144 if (se->ss)
3146 gfc_conv_intrinsic_funcall (se, expr);
3147 return;
3150 actual = expr->value.function.actual;
3152 type = gfc_typenode_for_spec (&expr->ts);
3153 /* Initialize the result. */
3154 resvar = gfc_create_var (type, "count");
3155 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
3157 /* Walk the arguments. */
3158 arrayss = gfc_walk_expr (actual->expr);
3159 gcc_assert (arrayss != gfc_ss_terminator);
3161 /* Initialize the scalarizer. */
3162 gfc_init_loopinfo (&loop);
3163 gfc_add_ss_to_loop (&loop, arrayss);
3165 /* Initialize the loop. */
3166 gfc_conv_ss_startstride (&loop);
3167 gfc_conv_loop_setup (&loop, &expr->where);
3169 gfc_mark_ss_chain_used (arrayss, 1);
3170 /* Generate the loop body. */
3171 gfc_start_scalarized_body (&loop, &body);
3173 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
3174 resvar, build_int_cst (TREE_TYPE (resvar), 1));
3175 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
3177 gfc_init_se (&arrayse, NULL);
3178 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3179 arrayse.ss = arrayss;
3180 gfc_conv_expr_val (&arrayse, actual->expr);
3181 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
3182 build_empty_stmt (input_location));
3184 gfc_add_block_to_block (&body, &arrayse.pre);
3185 gfc_add_expr_to_block (&body, tmp);
3186 gfc_add_block_to_block (&body, &arrayse.post);
3188 gfc_trans_scalarizing_loops (&loop, &body);
3190 gfc_add_block_to_block (&se->pre, &loop.pre);
3191 gfc_add_block_to_block (&se->pre, &loop.post);
3192 gfc_cleanup_loop (&loop);
3194 se->expr = resvar;
3198 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
3199 struct and return the corresponding loopinfo. */
3201 static gfc_loopinfo *
3202 enter_nested_loop (gfc_se *se)
3204 se->ss = se->ss->nested_ss;
3205 gcc_assert (se->ss == se->ss->loop->ss);
3207 return se->ss->loop;
3211 /* Inline implementation of the sum and product intrinsics. */
3212 static void
3213 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
3214 bool norm2)
3216 tree resvar;
3217 tree scale = NULL_TREE;
3218 tree type;
3219 stmtblock_t body;
3220 stmtblock_t block;
3221 tree tmp;
3222 gfc_loopinfo loop, *ploop;
3223 gfc_actual_arglist *arg_array, *arg_mask;
3224 gfc_ss *arrayss = NULL;
3225 gfc_ss *maskss = NULL;
3226 gfc_se arrayse;
3227 gfc_se maskse;
3228 gfc_se *parent_se;
3229 gfc_expr *arrayexpr;
3230 gfc_expr *maskexpr;
3232 if (expr->rank > 0)
3234 gcc_assert (gfc_inline_intrinsic_function_p (expr));
3235 parent_se = se;
3237 else
3238 parent_se = NULL;
3240 type = gfc_typenode_for_spec (&expr->ts);
3241 /* Initialize the result. */
3242 resvar = gfc_create_var (type, "val");
3243 if (norm2)
3245 /* result = 0.0;
3246 scale = 1.0. */
3247 scale = gfc_create_var (type, "scale");
3248 gfc_add_modify (&se->pre, scale,
3249 gfc_build_const (type, integer_one_node));
3250 tmp = gfc_build_const (type, integer_zero_node);
3252 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
3253 tmp = gfc_build_const (type, integer_zero_node);
3254 else if (op == NE_EXPR)
3255 /* PARITY. */
3256 tmp = convert (type, boolean_false_node);
3257 else if (op == BIT_AND_EXPR)
3258 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
3259 type, integer_one_node));
3260 else
3261 tmp = gfc_build_const (type, integer_one_node);
3263 gfc_add_modify (&se->pre, resvar, tmp);
3265 arg_array = expr->value.function.actual;
3267 arrayexpr = arg_array->expr;
3269 if (op == NE_EXPR || norm2)
3270 /* PARITY and NORM2. */
3271 maskexpr = NULL;
3272 else
3274 arg_mask = arg_array->next->next;
3275 gcc_assert (arg_mask != NULL);
3276 maskexpr = arg_mask->expr;
3279 if (expr->rank == 0)
3281 /* Walk the arguments. */
3282 arrayss = gfc_walk_expr (arrayexpr);
3283 gcc_assert (arrayss != gfc_ss_terminator);
3285 if (maskexpr && maskexpr->rank > 0)
3287 maskss = gfc_walk_expr (maskexpr);
3288 gcc_assert (maskss != gfc_ss_terminator);
3290 else
3291 maskss = NULL;
3293 /* Initialize the scalarizer. */
3294 gfc_init_loopinfo (&loop);
3295 gfc_add_ss_to_loop (&loop, arrayss);
3296 if (maskexpr && maskexpr->rank > 0)
3297 gfc_add_ss_to_loop (&loop, maskss);
3299 /* Initialize the loop. */
3300 gfc_conv_ss_startstride (&loop);
3301 gfc_conv_loop_setup (&loop, &expr->where);
3303 gfc_mark_ss_chain_used (arrayss, 1);
3304 if (maskexpr && maskexpr->rank > 0)
3305 gfc_mark_ss_chain_used (maskss, 1);
3307 ploop = &loop;
3309 else
3310 /* All the work has been done in the parent loops. */
3311 ploop = enter_nested_loop (se);
3313 gcc_assert (ploop);
3315 /* Generate the loop body. */
3316 gfc_start_scalarized_body (ploop, &body);
3318 /* If we have a mask, only add this element if the mask is set. */
3319 if (maskexpr && maskexpr->rank > 0)
3321 gfc_init_se (&maskse, parent_se);
3322 gfc_copy_loopinfo_to_se (&maskse, ploop);
3323 if (expr->rank == 0)
3324 maskse.ss = maskss;
3325 gfc_conv_expr_val (&maskse, maskexpr);
3326 gfc_add_block_to_block (&body, &maskse.pre);
3328 gfc_start_block (&block);
3330 else
3331 gfc_init_block (&block);
3333 /* Do the actual summation/product. */
3334 gfc_init_se (&arrayse, parent_se);
3335 gfc_copy_loopinfo_to_se (&arrayse, ploop);
3336 if (expr->rank == 0)
3337 arrayse.ss = arrayss;
3338 gfc_conv_expr_val (&arrayse, arrayexpr);
3339 gfc_add_block_to_block (&block, &arrayse.pre);
3341 if (norm2)
3343 /* if (x (i) != 0.0)
3345 absX = abs(x(i))
3346 if (absX > scale)
3348 val = scale/absX;
3349 result = 1.0 + result * val * val;
3350 scale = absX;
3352 else
3354 val = absX/scale;
3355 result += val * val;
3357 } */
3358 tree res1, res2, cond, absX, val;
3359 stmtblock_t ifblock1, ifblock2, ifblock3;
3361 gfc_init_block (&ifblock1);
3363 absX = gfc_create_var (type, "absX");
3364 gfc_add_modify (&ifblock1, absX,
3365 fold_build1_loc (input_location, ABS_EXPR, type,
3366 arrayse.expr));
3367 val = gfc_create_var (type, "val");
3368 gfc_add_expr_to_block (&ifblock1, val);
3370 gfc_init_block (&ifblock2);
3371 gfc_add_modify (&ifblock2, val,
3372 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
3373 absX));
3374 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
3375 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
3376 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
3377 gfc_build_const (type, integer_one_node));
3378 gfc_add_modify (&ifblock2, resvar, res1);
3379 gfc_add_modify (&ifblock2, scale, absX);
3380 res1 = gfc_finish_block (&ifblock2);
3382 gfc_init_block (&ifblock3);
3383 gfc_add_modify (&ifblock3, val,
3384 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
3385 scale));
3386 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
3387 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
3388 gfc_add_modify (&ifblock3, resvar, res2);
3389 res2 = gfc_finish_block (&ifblock3);
3391 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
3392 absX, scale);
3393 tmp = build3_v (COND_EXPR, cond, res1, res2);
3394 gfc_add_expr_to_block (&ifblock1, tmp);
3395 tmp = gfc_finish_block (&ifblock1);
3397 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
3398 arrayse.expr,
3399 gfc_build_const (type, integer_zero_node));
3401 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3402 gfc_add_expr_to_block (&block, tmp);
3404 else
3406 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
3407 gfc_add_modify (&block, resvar, tmp);
3410 gfc_add_block_to_block (&block, &arrayse.post);
3412 if (maskexpr && maskexpr->rank > 0)
3414 /* We enclose the above in if (mask) {...} . */
3416 tmp = gfc_finish_block (&block);
3417 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3418 build_empty_stmt (input_location));
3420 else
3421 tmp = gfc_finish_block (&block);
3422 gfc_add_expr_to_block (&body, tmp);
3424 gfc_trans_scalarizing_loops (ploop, &body);
3426 /* For a scalar mask, enclose the loop in an if statement. */
3427 if (maskexpr && maskexpr->rank == 0)
3429 gfc_init_block (&block);
3430 gfc_add_block_to_block (&block, &ploop->pre);
3431 gfc_add_block_to_block (&block, &ploop->post);
3432 tmp = gfc_finish_block (&block);
3434 if (expr->rank > 0)
3436 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
3437 build_empty_stmt (input_location));
3438 gfc_advance_se_ss_chain (se);
3440 else
3442 gcc_assert (expr->rank == 0);
3443 gfc_init_se (&maskse, NULL);
3444 gfc_conv_expr_val (&maskse, maskexpr);
3445 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3446 build_empty_stmt (input_location));
3449 gfc_add_expr_to_block (&block, tmp);
3450 gfc_add_block_to_block (&se->pre, &block);
3451 gcc_assert (se->post.head == NULL);
3453 else
3455 gfc_add_block_to_block (&se->pre, &ploop->pre);
3456 gfc_add_block_to_block (&se->pre, &ploop->post);
3459 if (expr->rank == 0)
3460 gfc_cleanup_loop (ploop);
3462 if (norm2)
3464 /* result = scale * sqrt(result). */
3465 tree sqrt;
3466 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
3467 resvar = build_call_expr_loc (input_location,
3468 sqrt, 1, resvar);
3469 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
3472 se->expr = resvar;
3476 /* Inline implementation of the dot_product intrinsic. This function
3477 is based on gfc_conv_intrinsic_arith (the previous function). */
3478 static void
3479 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
3481 tree resvar;
3482 tree type;
3483 stmtblock_t body;
3484 stmtblock_t block;
3485 tree tmp;
3486 gfc_loopinfo loop;
3487 gfc_actual_arglist *actual;
3488 gfc_ss *arrayss1, *arrayss2;
3489 gfc_se arrayse1, arrayse2;
3490 gfc_expr *arrayexpr1, *arrayexpr2;
3492 type = gfc_typenode_for_spec (&expr->ts);
3494 /* Initialize the result. */
3495 resvar = gfc_create_var (type, "val");
3496 if (expr->ts.type == BT_LOGICAL)
3497 tmp = build_int_cst (type, 0);
3498 else
3499 tmp = gfc_build_const (type, integer_zero_node);
3501 gfc_add_modify (&se->pre, resvar, tmp);
3503 /* Walk argument #1. */
3504 actual = expr->value.function.actual;
3505 arrayexpr1 = actual->expr;
3506 arrayss1 = gfc_walk_expr (arrayexpr1);
3507 gcc_assert (arrayss1 != gfc_ss_terminator);
3509 /* Walk argument #2. */
3510 actual = actual->next;
3511 arrayexpr2 = actual->expr;
3512 arrayss2 = gfc_walk_expr (arrayexpr2);
3513 gcc_assert (arrayss2 != gfc_ss_terminator);
3515 /* Initialize the scalarizer. */
3516 gfc_init_loopinfo (&loop);
3517 gfc_add_ss_to_loop (&loop, arrayss1);
3518 gfc_add_ss_to_loop (&loop, arrayss2);
3520 /* Initialize the loop. */
3521 gfc_conv_ss_startstride (&loop);
3522 gfc_conv_loop_setup (&loop, &expr->where);
3524 gfc_mark_ss_chain_used (arrayss1, 1);
3525 gfc_mark_ss_chain_used (arrayss2, 1);
3527 /* Generate the loop body. */
3528 gfc_start_scalarized_body (&loop, &body);
3529 gfc_init_block (&block);
3531 /* Make the tree expression for [conjg(]array1[)]. */
3532 gfc_init_se (&arrayse1, NULL);
3533 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
3534 arrayse1.ss = arrayss1;
3535 gfc_conv_expr_val (&arrayse1, arrayexpr1);
3536 if (expr->ts.type == BT_COMPLEX)
3537 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
3538 arrayse1.expr);
3539 gfc_add_block_to_block (&block, &arrayse1.pre);
3541 /* Make the tree expression for array2. */
3542 gfc_init_se (&arrayse2, NULL);
3543 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
3544 arrayse2.ss = arrayss2;
3545 gfc_conv_expr_val (&arrayse2, arrayexpr2);
3546 gfc_add_block_to_block (&block, &arrayse2.pre);
3548 /* Do the actual product and sum. */
3549 if (expr->ts.type == BT_LOGICAL)
3551 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
3552 arrayse1.expr, arrayse2.expr);
3553 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
3555 else
3557 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
3558 arrayse2.expr);
3559 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
3561 gfc_add_modify (&block, resvar, tmp);
3563 /* Finish up the loop block and the loop. */
3564 tmp = gfc_finish_block (&block);
3565 gfc_add_expr_to_block (&body, tmp);
3567 gfc_trans_scalarizing_loops (&loop, &body);
3568 gfc_add_block_to_block (&se->pre, &loop.pre);
3569 gfc_add_block_to_block (&se->pre, &loop.post);
3570 gfc_cleanup_loop (&loop);
3572 se->expr = resvar;
3576 /* Emit code for minloc or maxloc intrinsic. There are many different cases
3577 we need to handle. For performance reasons we sometimes create two
3578 loops instead of one, where the second one is much simpler.
3579 Examples for minloc intrinsic:
3580 1) Result is an array, a call is generated
3581 2) Array mask is used and NaNs need to be supported:
3582 limit = Infinity;
3583 pos = 0;
3584 S = from;
3585 while (S <= to) {
3586 if (mask[S]) {
3587 if (pos == 0) pos = S + (1 - from);
3588 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3590 S++;
3592 goto lab2;
3593 lab1:;
3594 while (S <= to) {
3595 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3596 S++;
3598 lab2:;
3599 3) NaNs need to be supported, but it is known at compile time or cheaply
3600 at runtime whether array is nonempty or not:
3601 limit = Infinity;
3602 pos = 0;
3603 S = from;
3604 while (S <= to) {
3605 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3606 S++;
3608 if (from <= to) pos = 1;
3609 goto lab2;
3610 lab1:;
3611 while (S <= to) {
3612 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3613 S++;
3615 lab2:;
3616 4) NaNs aren't supported, array mask is used:
3617 limit = infinities_supported ? Infinity : huge (limit);
3618 pos = 0;
3619 S = from;
3620 while (S <= to) {
3621 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3622 S++;
3624 goto lab2;
3625 lab1:;
3626 while (S <= to) {
3627 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3628 S++;
3630 lab2:;
3631 5) Same without array mask:
3632 limit = infinities_supported ? Infinity : huge (limit);
3633 pos = (from <= to) ? 1 : 0;
3634 S = from;
3635 while (S <= to) {
3636 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3637 S++;
3639 For 3) and 5), if mask is scalar, this all goes into a conditional,
3640 setting pos = 0; in the else branch. */
3642 static void
3643 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
3645 stmtblock_t body;
3646 stmtblock_t block;
3647 stmtblock_t ifblock;
3648 stmtblock_t elseblock;
3649 tree limit;
3650 tree type;
3651 tree tmp;
3652 tree cond;
3653 tree elsetmp;
3654 tree ifbody;
3655 tree offset;
3656 tree nonempty;
3657 tree lab1, lab2;
3658 gfc_loopinfo loop;
3659 gfc_actual_arglist *actual;
3660 gfc_ss *arrayss;
3661 gfc_ss *maskss;
3662 gfc_se arrayse;
3663 gfc_se maskse;
3664 gfc_expr *arrayexpr;
3665 gfc_expr *maskexpr;
3666 tree pos;
3667 int n;
3669 if (se->ss)
3671 gfc_conv_intrinsic_funcall (se, expr);
3672 return;
3675 /* Initialize the result. */
3676 pos = gfc_create_var (gfc_array_index_type, "pos");
3677 offset = gfc_create_var (gfc_array_index_type, "offset");
3678 type = gfc_typenode_for_spec (&expr->ts);
3680 /* Walk the arguments. */
3681 actual = expr->value.function.actual;
3682 arrayexpr = actual->expr;
3683 arrayss = gfc_walk_expr (arrayexpr);
3684 gcc_assert (arrayss != gfc_ss_terminator);
3686 actual = actual->next->next;
3687 gcc_assert (actual);
3688 maskexpr = actual->expr;
3689 nonempty = NULL;
3690 if (maskexpr && maskexpr->rank != 0)
3692 maskss = gfc_walk_expr (maskexpr);
3693 gcc_assert (maskss != gfc_ss_terminator);
3695 else
3697 mpz_t asize;
3698 if (gfc_array_size (arrayexpr, &asize))
3700 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
3701 mpz_clear (asize);
3702 nonempty = fold_build2_loc (input_location, GT_EXPR,
3703 boolean_type_node, nonempty,
3704 gfc_index_zero_node);
3706 maskss = NULL;
3709 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
3710 switch (arrayexpr->ts.type)
3712 case BT_REAL:
3713 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
3714 break;
3716 case BT_INTEGER:
3717 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
3718 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
3719 arrayexpr->ts.kind);
3720 break;
3722 default:
3723 gcc_unreachable ();
3726 /* We start with the most negative possible value for MAXLOC, and the most
3727 positive possible value for MINLOC. The most negative possible value is
3728 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
3729 possible value is HUGE in both cases. */
3730 if (op == GT_EXPR)
3731 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
3732 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
3733 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
3734 build_int_cst (type, 1));
3736 gfc_add_modify (&se->pre, limit, tmp);
3738 /* Initialize the scalarizer. */
3739 gfc_init_loopinfo (&loop);
3740 gfc_add_ss_to_loop (&loop, arrayss);
3741 if (maskss)
3742 gfc_add_ss_to_loop (&loop, maskss);
3744 /* Initialize the loop. */
3745 gfc_conv_ss_startstride (&loop);
3747 /* The code generated can have more than one loop in sequence (see the
3748 comment at the function header). This doesn't work well with the
3749 scalarizer, which changes arrays' offset when the scalarization loops
3750 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
3751 are currently inlined in the scalar case only (for which loop is of rank
3752 one). As there is no dependency to care about in that case, there is no
3753 temporary, so that we can use the scalarizer temporary code to handle
3754 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
3755 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
3756 to restore offset.
3757 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
3758 should eventually go away. We could either create two loops properly,
3759 or find another way to save/restore the array offsets between the two
3760 loops (without conflicting with temporary management), or use a single
3761 loop minmaxloc implementation. See PR 31067. */
3762 loop.temp_dim = loop.dimen;
3763 gfc_conv_loop_setup (&loop, &expr->where);
3765 gcc_assert (loop.dimen == 1);
3766 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
3767 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3768 loop.from[0], loop.to[0]);
3770 lab1 = NULL;
3771 lab2 = NULL;
3772 /* Initialize the position to zero, following Fortran 2003. We are free
3773 to do this because Fortran 95 allows the result of an entirely false
3774 mask to be processor dependent. If we know at compile time the array
3775 is non-empty and no MASK is used, we can initialize to 1 to simplify
3776 the inner loop. */
3777 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
3778 gfc_add_modify (&loop.pre, pos,
3779 fold_build3_loc (input_location, COND_EXPR,
3780 gfc_array_index_type,
3781 nonempty, gfc_index_one_node,
3782 gfc_index_zero_node));
3783 else
3785 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
3786 lab1 = gfc_build_label_decl (NULL_TREE);
3787 TREE_USED (lab1) = 1;
3788 lab2 = gfc_build_label_decl (NULL_TREE);
3789 TREE_USED (lab2) = 1;
3792 /* An offset must be added to the loop
3793 counter to obtain the required position. */
3794 gcc_assert (loop.from[0]);
3796 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3797 gfc_index_one_node, loop.from[0]);
3798 gfc_add_modify (&loop.pre, offset, tmp);
3800 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
3801 if (maskss)
3802 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
3803 /* Generate the loop body. */
3804 gfc_start_scalarized_body (&loop, &body);
3806 /* If we have a mask, only check this element if the mask is set. */
3807 if (maskss)
3809 gfc_init_se (&maskse, NULL);
3810 gfc_copy_loopinfo_to_se (&maskse, &loop);
3811 maskse.ss = maskss;
3812 gfc_conv_expr_val (&maskse, maskexpr);
3813 gfc_add_block_to_block (&body, &maskse.pre);
3815 gfc_start_block (&block);
3817 else
3818 gfc_init_block (&block);
3820 /* Compare with the current limit. */
3821 gfc_init_se (&arrayse, NULL);
3822 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3823 arrayse.ss = arrayss;
3824 gfc_conv_expr_val (&arrayse, arrayexpr);
3825 gfc_add_block_to_block (&block, &arrayse.pre);
3827 /* We do the following if this is a more extreme value. */
3828 gfc_start_block (&ifblock);
3830 /* Assign the value to the limit... */
3831 gfc_add_modify (&ifblock, limit, arrayse.expr);
3833 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
3835 stmtblock_t ifblock2;
3836 tree ifbody2;
3838 gfc_start_block (&ifblock2);
3839 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3840 loop.loopvar[0], offset);
3841 gfc_add_modify (&ifblock2, pos, tmp);
3842 ifbody2 = gfc_finish_block (&ifblock2);
3843 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, pos,
3844 gfc_index_zero_node);
3845 tmp = build3_v (COND_EXPR, cond, ifbody2,
3846 build_empty_stmt (input_location));
3847 gfc_add_expr_to_block (&block, tmp);
3850 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3851 loop.loopvar[0], offset);
3852 gfc_add_modify (&ifblock, pos, tmp);
3854 if (lab1)
3855 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
3857 ifbody = gfc_finish_block (&ifblock);
3859 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
3861 if (lab1)
3862 cond = fold_build2_loc (input_location,
3863 op == GT_EXPR ? GE_EXPR : LE_EXPR,
3864 boolean_type_node, arrayse.expr, limit);
3865 else
3866 cond = fold_build2_loc (input_location, op, boolean_type_node,
3867 arrayse.expr, limit);
3869 ifbody = build3_v (COND_EXPR, cond, ifbody,
3870 build_empty_stmt (input_location));
3872 gfc_add_expr_to_block (&block, ifbody);
3874 if (maskss)
3876 /* We enclose the above in if (mask) {...}. */
3877 tmp = gfc_finish_block (&block);
3879 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3880 build_empty_stmt (input_location));
3882 else
3883 tmp = gfc_finish_block (&block);
3884 gfc_add_expr_to_block (&body, tmp);
3886 if (lab1)
3888 gfc_trans_scalarized_loop_boundary (&loop, &body);
3890 if (HONOR_NANS (DECL_MODE (limit)))
3892 if (nonempty != NULL)
3894 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
3895 tmp = build3_v (COND_EXPR, nonempty, ifbody,
3896 build_empty_stmt (input_location));
3897 gfc_add_expr_to_block (&loop.code[0], tmp);
3901 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
3902 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
3904 /* If we have a mask, only check this element if the mask is set. */
3905 if (maskss)
3907 gfc_init_se (&maskse, NULL);
3908 gfc_copy_loopinfo_to_se (&maskse, &loop);
3909 maskse.ss = maskss;
3910 gfc_conv_expr_val (&maskse, maskexpr);
3911 gfc_add_block_to_block (&body, &maskse.pre);
3913 gfc_start_block (&block);
3915 else
3916 gfc_init_block (&block);
3918 /* Compare with the current limit. */
3919 gfc_init_se (&arrayse, NULL);
3920 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3921 arrayse.ss = arrayss;
3922 gfc_conv_expr_val (&arrayse, arrayexpr);
3923 gfc_add_block_to_block (&block, &arrayse.pre);
3925 /* We do the following if this is a more extreme value. */
3926 gfc_start_block (&ifblock);
3928 /* Assign the value to the limit... */
3929 gfc_add_modify (&ifblock, limit, arrayse.expr);
3931 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3932 loop.loopvar[0], offset);
3933 gfc_add_modify (&ifblock, pos, tmp);
3935 ifbody = gfc_finish_block (&ifblock);
3937 cond = fold_build2_loc (input_location, op, boolean_type_node,
3938 arrayse.expr, limit);
3940 tmp = build3_v (COND_EXPR, cond, ifbody,
3941 build_empty_stmt (input_location));
3942 gfc_add_expr_to_block (&block, tmp);
3944 if (maskss)
3946 /* We enclose the above in if (mask) {...}. */
3947 tmp = gfc_finish_block (&block);
3949 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3950 build_empty_stmt (input_location));
3952 else
3953 tmp = gfc_finish_block (&block);
3954 gfc_add_expr_to_block (&body, tmp);
3955 /* Avoid initializing loopvar[0] again, it should be left where
3956 it finished by the first loop. */
3957 loop.from[0] = loop.loopvar[0];
3960 gfc_trans_scalarizing_loops (&loop, &body);
3962 if (lab2)
3963 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
3965 /* For a scalar mask, enclose the loop in an if statement. */
3966 if (maskexpr && maskss == NULL)
3968 gfc_init_se (&maskse, NULL);
3969 gfc_conv_expr_val (&maskse, maskexpr);
3970 gfc_init_block (&block);
3971 gfc_add_block_to_block (&block, &loop.pre);
3972 gfc_add_block_to_block (&block, &loop.post);
3973 tmp = gfc_finish_block (&block);
3975 /* For the else part of the scalar mask, just initialize
3976 the pos variable the same way as above. */
3978 gfc_init_block (&elseblock);
3979 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
3980 elsetmp = gfc_finish_block (&elseblock);
3982 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
3983 gfc_add_expr_to_block (&block, tmp);
3984 gfc_add_block_to_block (&se->pre, &block);
3986 else
3988 gfc_add_block_to_block (&se->pre, &loop.pre);
3989 gfc_add_block_to_block (&se->pre, &loop.post);
3991 gfc_cleanup_loop (&loop);
3993 se->expr = convert (type, pos);
3996 /* Emit code for minval or maxval intrinsic. There are many different cases
3997 we need to handle. For performance reasons we sometimes create two
3998 loops instead of one, where the second one is much simpler.
3999 Examples for minval intrinsic:
4000 1) Result is an array, a call is generated
4001 2) Array mask is used and NaNs need to be supported, rank 1:
4002 limit = Infinity;
4003 nonempty = false;
4004 S = from;
4005 while (S <= to) {
4006 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
4007 S++;
4009 limit = nonempty ? NaN : huge (limit);
4010 lab:
4011 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
4012 3) NaNs need to be supported, but it is known at compile time or cheaply
4013 at runtime whether array is nonempty or not, rank 1:
4014 limit = Infinity;
4015 S = from;
4016 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
4017 limit = (from <= to) ? NaN : huge (limit);
4018 lab:
4019 while (S <= to) { limit = min (a[S], limit); S++; }
4020 4) Array mask is used and NaNs need to be supported, rank > 1:
4021 limit = Infinity;
4022 nonempty = false;
4023 fast = false;
4024 S1 = from1;
4025 while (S1 <= to1) {
4026 S2 = from2;
4027 while (S2 <= to2) {
4028 if (mask[S1][S2]) {
4029 if (fast) limit = min (a[S1][S2], limit);
4030 else {
4031 nonempty = true;
4032 if (a[S1][S2] <= limit) {
4033 limit = a[S1][S2];
4034 fast = true;
4038 S2++;
4040 S1++;
4042 if (!fast)
4043 limit = nonempty ? NaN : huge (limit);
4044 5) NaNs need to be supported, but it is known at compile time or cheaply
4045 at runtime whether array is nonempty or not, rank > 1:
4046 limit = Infinity;
4047 fast = false;
4048 S1 = from1;
4049 while (S1 <= to1) {
4050 S2 = from2;
4051 while (S2 <= to2) {
4052 if (fast) limit = min (a[S1][S2], limit);
4053 else {
4054 if (a[S1][S2] <= limit) {
4055 limit = a[S1][S2];
4056 fast = true;
4059 S2++;
4061 S1++;
4063 if (!fast)
4064 limit = (nonempty_array) ? NaN : huge (limit);
4065 6) NaNs aren't supported, but infinities are. Array mask is used:
4066 limit = Infinity;
4067 nonempty = false;
4068 S = from;
4069 while (S <= to) {
4070 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
4071 S++;
4073 limit = nonempty ? limit : huge (limit);
4074 7) Same without array mask:
4075 limit = Infinity;
4076 S = from;
4077 while (S <= to) { limit = min (a[S], limit); S++; }
4078 limit = (from <= to) ? limit : huge (limit);
4079 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
4080 limit = huge (limit);
4081 S = from;
4082 while (S <= to) { limit = min (a[S], limit); S++); }
4084 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
4085 with array mask instead).
4086 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
4087 setting limit = huge (limit); in the else branch. */
4089 static void
4090 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
4092 tree limit;
4093 tree type;
4094 tree tmp;
4095 tree ifbody;
4096 tree nonempty;
4097 tree nonempty_var;
4098 tree lab;
4099 tree fast;
4100 tree huge_cst = NULL, nan_cst = NULL;
4101 stmtblock_t body;
4102 stmtblock_t block, block2;
4103 gfc_loopinfo loop;
4104 gfc_actual_arglist *actual;
4105 gfc_ss *arrayss;
4106 gfc_ss *maskss;
4107 gfc_se arrayse;
4108 gfc_se maskse;
4109 gfc_expr *arrayexpr;
4110 gfc_expr *maskexpr;
4111 int n;
4113 if (se->ss)
4115 gfc_conv_intrinsic_funcall (se, expr);
4116 return;
4119 type = gfc_typenode_for_spec (&expr->ts);
4120 /* Initialize the result. */
4121 limit = gfc_create_var (type, "limit");
4122 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
4123 switch (expr->ts.type)
4125 case BT_REAL:
4126 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
4127 expr->ts.kind, 0);
4128 if (HONOR_INFINITIES (DECL_MODE (limit)))
4130 REAL_VALUE_TYPE real;
4131 real_inf (&real);
4132 tmp = build_real (type, real);
4134 else
4135 tmp = huge_cst;
4136 if (HONOR_NANS (DECL_MODE (limit)))
4137 nan_cst = gfc_build_nan (type, "");
4138 break;
4140 case BT_INTEGER:
4141 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
4142 break;
4144 default:
4145 gcc_unreachable ();
4148 /* We start with the most negative possible value for MAXVAL, and the most
4149 positive possible value for MINVAL. The most negative possible value is
4150 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
4151 possible value is HUGE in both cases. */
4152 if (op == GT_EXPR)
4154 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
4155 if (huge_cst)
4156 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
4157 TREE_TYPE (huge_cst), huge_cst);
4160 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
4161 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
4162 tmp, build_int_cst (type, 1));
4164 gfc_add_modify (&se->pre, limit, tmp);
4166 /* Walk the arguments. */
4167 actual = expr->value.function.actual;
4168 arrayexpr = actual->expr;
4169 arrayss = gfc_walk_expr (arrayexpr);
4170 gcc_assert (arrayss != gfc_ss_terminator);
4172 actual = actual->next->next;
4173 gcc_assert (actual);
4174 maskexpr = actual->expr;
4175 nonempty = NULL;
4176 if (maskexpr && maskexpr->rank != 0)
4178 maskss = gfc_walk_expr (maskexpr);
4179 gcc_assert (maskss != gfc_ss_terminator);
4181 else
4183 mpz_t asize;
4184 if (gfc_array_size (arrayexpr, &asize))
4186 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
4187 mpz_clear (asize);
4188 nonempty = fold_build2_loc (input_location, GT_EXPR,
4189 boolean_type_node, nonempty,
4190 gfc_index_zero_node);
4192 maskss = NULL;
4195 /* Initialize the scalarizer. */
4196 gfc_init_loopinfo (&loop);
4197 gfc_add_ss_to_loop (&loop, arrayss);
4198 if (maskss)
4199 gfc_add_ss_to_loop (&loop, maskss);
4201 /* Initialize the loop. */
4202 gfc_conv_ss_startstride (&loop);
4204 /* The code generated can have more than one loop in sequence (see the
4205 comment at the function header). This doesn't work well with the
4206 scalarizer, which changes arrays' offset when the scalarization loops
4207 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
4208 are currently inlined in the scalar case only. As there is no dependency
4209 to care about in that case, there is no temporary, so that we can use the
4210 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
4211 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
4212 gfc_trans_scalarized_loop_boundary even later to restore offset.
4213 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
4214 should eventually go away. We could either create two loops properly,
4215 or find another way to save/restore the array offsets between the two
4216 loops (without conflicting with temporary management), or use a single
4217 loop minmaxval implementation. See PR 31067. */
4218 loop.temp_dim = loop.dimen;
4219 gfc_conv_loop_setup (&loop, &expr->where);
4221 if (nonempty == NULL && maskss == NULL
4222 && loop.dimen == 1 && loop.from[0] && loop.to[0])
4223 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
4224 loop.from[0], loop.to[0]);
4225 nonempty_var = NULL;
4226 if (nonempty == NULL
4227 && (HONOR_INFINITIES (DECL_MODE (limit))
4228 || HONOR_NANS (DECL_MODE (limit))))
4230 nonempty_var = gfc_create_var (boolean_type_node, "nonempty");
4231 gfc_add_modify (&se->pre, nonempty_var, boolean_false_node);
4232 nonempty = nonempty_var;
4234 lab = NULL;
4235 fast = NULL;
4236 if (HONOR_NANS (DECL_MODE (limit)))
4238 if (loop.dimen == 1)
4240 lab = gfc_build_label_decl (NULL_TREE);
4241 TREE_USED (lab) = 1;
4243 else
4245 fast = gfc_create_var (boolean_type_node, "fast");
4246 gfc_add_modify (&se->pre, fast, boolean_false_node);
4250 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
4251 if (maskss)
4252 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
4253 /* Generate the loop body. */
4254 gfc_start_scalarized_body (&loop, &body);
4256 /* If we have a mask, only add this element if the mask is set. */
4257 if (maskss)
4259 gfc_init_se (&maskse, NULL);
4260 gfc_copy_loopinfo_to_se (&maskse, &loop);
4261 maskse.ss = maskss;
4262 gfc_conv_expr_val (&maskse, maskexpr);
4263 gfc_add_block_to_block (&body, &maskse.pre);
4265 gfc_start_block (&block);
4267 else
4268 gfc_init_block (&block);
4270 /* Compare with the current limit. */
4271 gfc_init_se (&arrayse, NULL);
4272 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4273 arrayse.ss = arrayss;
4274 gfc_conv_expr_val (&arrayse, arrayexpr);
4275 gfc_add_block_to_block (&block, &arrayse.pre);
4277 gfc_init_block (&block2);
4279 if (nonempty_var)
4280 gfc_add_modify (&block2, nonempty_var, boolean_true_node);
4282 if (HONOR_NANS (DECL_MODE (limit)))
4284 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
4285 boolean_type_node, arrayse.expr, limit);
4286 if (lab)
4287 ifbody = build1_v (GOTO_EXPR, lab);
4288 else
4290 stmtblock_t ifblock;
4292 gfc_init_block (&ifblock);
4293 gfc_add_modify (&ifblock, limit, arrayse.expr);
4294 gfc_add_modify (&ifblock, fast, boolean_true_node);
4295 ifbody = gfc_finish_block (&ifblock);
4297 tmp = build3_v (COND_EXPR, tmp, ifbody,
4298 build_empty_stmt (input_location));
4299 gfc_add_expr_to_block (&block2, tmp);
4301 else
4303 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
4304 signed zeros. */
4305 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
4307 tmp = fold_build2_loc (input_location, op, boolean_type_node,
4308 arrayse.expr, limit);
4309 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
4310 tmp = build3_v (COND_EXPR, tmp, ifbody,
4311 build_empty_stmt (input_location));
4312 gfc_add_expr_to_block (&block2, tmp);
4314 else
4316 tmp = fold_build2_loc (input_location,
4317 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
4318 type, arrayse.expr, limit);
4319 gfc_add_modify (&block2, limit, tmp);
4323 if (fast)
4325 tree elsebody = gfc_finish_block (&block2);
4327 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
4328 signed zeros. */
4329 if (HONOR_NANS (DECL_MODE (limit))
4330 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
4332 tmp = fold_build2_loc (input_location, op, boolean_type_node,
4333 arrayse.expr, limit);
4334 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
4335 ifbody = build3_v (COND_EXPR, tmp, ifbody,
4336 build_empty_stmt (input_location));
4338 else
4340 tmp = fold_build2_loc (input_location,
4341 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
4342 type, arrayse.expr, limit);
4343 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
4345 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
4346 gfc_add_expr_to_block (&block, tmp);
4348 else
4349 gfc_add_block_to_block (&block, &block2);
4351 gfc_add_block_to_block (&block, &arrayse.post);
4353 tmp = gfc_finish_block (&block);
4354 if (maskss)
4355 /* We enclose the above in if (mask) {...}. */
4356 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4357 build_empty_stmt (input_location));
4358 gfc_add_expr_to_block (&body, tmp);
4360 if (lab)
4362 gfc_trans_scalarized_loop_boundary (&loop, &body);
4364 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
4365 nan_cst, huge_cst);
4366 gfc_add_modify (&loop.code[0], limit, tmp);
4367 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
4369 /* If we have a mask, only add this element if the mask is set. */
4370 if (maskss)
4372 gfc_init_se (&maskse, NULL);
4373 gfc_copy_loopinfo_to_se (&maskse, &loop);
4374 maskse.ss = maskss;
4375 gfc_conv_expr_val (&maskse, maskexpr);
4376 gfc_add_block_to_block (&body, &maskse.pre);
4378 gfc_start_block (&block);
4380 else
4381 gfc_init_block (&block);
4383 /* Compare with the current limit. */
4384 gfc_init_se (&arrayse, NULL);
4385 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4386 arrayse.ss = arrayss;
4387 gfc_conv_expr_val (&arrayse, arrayexpr);
4388 gfc_add_block_to_block (&block, &arrayse.pre);
4390 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
4391 signed zeros. */
4392 if (HONOR_NANS (DECL_MODE (limit))
4393 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
4395 tmp = fold_build2_loc (input_location, op, boolean_type_node,
4396 arrayse.expr, limit);
4397 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
4398 tmp = build3_v (COND_EXPR, tmp, ifbody,
4399 build_empty_stmt (input_location));
4400 gfc_add_expr_to_block (&block, tmp);
4402 else
4404 tmp = fold_build2_loc (input_location,
4405 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
4406 type, arrayse.expr, limit);
4407 gfc_add_modify (&block, limit, tmp);
4410 gfc_add_block_to_block (&block, &arrayse.post);
4412 tmp = gfc_finish_block (&block);
4413 if (maskss)
4414 /* We enclose the above in if (mask) {...}. */
4415 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4416 build_empty_stmt (input_location));
4417 gfc_add_expr_to_block (&body, tmp);
4418 /* Avoid initializing loopvar[0] again, it should be left where
4419 it finished by the first loop. */
4420 loop.from[0] = loop.loopvar[0];
4422 gfc_trans_scalarizing_loops (&loop, &body);
4424 if (fast)
4426 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
4427 nan_cst, huge_cst);
4428 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
4429 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
4430 ifbody);
4431 gfc_add_expr_to_block (&loop.pre, tmp);
4433 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
4435 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
4436 huge_cst);
4437 gfc_add_modify (&loop.pre, limit, tmp);
4440 /* For a scalar mask, enclose the loop in an if statement. */
4441 if (maskexpr && maskss == NULL)
4443 tree else_stmt;
4445 gfc_init_se (&maskse, NULL);
4446 gfc_conv_expr_val (&maskse, maskexpr);
4447 gfc_init_block (&block);
4448 gfc_add_block_to_block (&block, &loop.pre);
4449 gfc_add_block_to_block (&block, &loop.post);
4450 tmp = gfc_finish_block (&block);
4452 if (HONOR_INFINITIES (DECL_MODE (limit)))
4453 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
4454 else
4455 else_stmt = build_empty_stmt (input_location);
4456 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
4457 gfc_add_expr_to_block (&block, tmp);
4458 gfc_add_block_to_block (&se->pre, &block);
4460 else
4462 gfc_add_block_to_block (&se->pre, &loop.pre);
4463 gfc_add_block_to_block (&se->pre, &loop.post);
4466 gfc_cleanup_loop (&loop);
4468 se->expr = limit;
4471 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
4472 static void
4473 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
4475 tree args[2];
4476 tree type;
4477 tree tmp;
4479 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4480 type = TREE_TYPE (args[0]);
4482 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
4483 build_int_cst (type, 1), args[1]);
4484 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
4485 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
4486 build_int_cst (type, 0));
4487 type = gfc_typenode_for_spec (&expr->ts);
4488 se->expr = convert (type, tmp);
4492 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
4493 static void
4494 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
4496 tree args[2];
4498 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4500 /* Convert both arguments to the unsigned type of the same size. */
4501 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
4502 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
4504 /* If they have unequal type size, convert to the larger one. */
4505 if (TYPE_PRECISION (TREE_TYPE (args[0]))
4506 > TYPE_PRECISION (TREE_TYPE (args[1])))
4507 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
4508 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
4509 > TYPE_PRECISION (TREE_TYPE (args[0])))
4510 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
4512 /* Now, we compare them. */
4513 se->expr = fold_build2_loc (input_location, op, boolean_type_node,
4514 args[0], args[1]);
4518 /* Generate code to perform the specified operation. */
4519 static void
4520 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
4522 tree args[2];
4524 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4525 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
4526 args[0], args[1]);
4529 /* Bitwise not. */
4530 static void
4531 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
4533 tree arg;
4535 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4536 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
4537 TREE_TYPE (arg), arg);
4540 /* Set or clear a single bit. */
4541 static void
4542 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
4544 tree args[2];
4545 tree type;
4546 tree tmp;
4547 enum tree_code op;
4549 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4550 type = TREE_TYPE (args[0]);
4552 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
4553 build_int_cst (type, 1), args[1]);
4554 if (set)
4555 op = BIT_IOR_EXPR;
4556 else
4558 op = BIT_AND_EXPR;
4559 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
4561 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
4564 /* Extract a sequence of bits.
4565 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
4566 static void
4567 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
4569 tree args[3];
4570 tree type;
4571 tree tmp;
4572 tree mask;
4574 gfc_conv_intrinsic_function_args (se, expr, args, 3);
4575 type = TREE_TYPE (args[0]);
4577 mask = build_int_cst (type, -1);
4578 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
4579 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
4581 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
4583 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
4586 static void
4587 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
4588 bool arithmetic)
4590 tree args[2], type, num_bits, cond;
4592 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4594 args[0] = gfc_evaluate_now (args[0], &se->pre);
4595 args[1] = gfc_evaluate_now (args[1], &se->pre);
4596 type = TREE_TYPE (args[0]);
4598 if (!arithmetic)
4599 args[0] = fold_convert (unsigned_type_for (type), args[0]);
4600 else
4601 gcc_assert (right_shift);
4603 se->expr = fold_build2_loc (input_location,
4604 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
4605 TREE_TYPE (args[0]), args[0], args[1]);
4607 if (!arithmetic)
4608 se->expr = fold_convert (type, se->expr);
4610 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4611 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4612 special case. */
4613 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
4614 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
4615 args[1], num_bits);
4617 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
4618 build_int_cst (type, 0), se->expr);
4621 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
4623 : ((shift >= 0) ? i << shift : i >> -shift)
4624 where all shifts are logical shifts. */
4625 static void
4626 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
4628 tree args[2];
4629 tree type;
4630 tree utype;
4631 tree tmp;
4632 tree width;
4633 tree num_bits;
4634 tree cond;
4635 tree lshift;
4636 tree rshift;
4638 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4640 args[0] = gfc_evaluate_now (args[0], &se->pre);
4641 args[1] = gfc_evaluate_now (args[1], &se->pre);
4643 type = TREE_TYPE (args[0]);
4644 utype = unsigned_type_for (type);
4646 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
4647 args[1]);
4649 /* Left shift if positive. */
4650 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
4652 /* Right shift if negative.
4653 We convert to an unsigned type because we want a logical shift.
4654 The standard doesn't define the case of shifting negative
4655 numbers, and we try to be compatible with other compilers, most
4656 notably g77, here. */
4657 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
4658 utype, convert (utype, args[0]), width));
4660 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, args[1],
4661 build_int_cst (TREE_TYPE (args[1]), 0));
4662 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
4664 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4665 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4666 special case. */
4667 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
4668 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, width,
4669 num_bits);
4670 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
4671 build_int_cst (type, 0), tmp);
4675 /* Circular shift. AKA rotate or barrel shift. */
4677 static void
4678 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
4680 tree *args;
4681 tree type;
4682 tree tmp;
4683 tree lrot;
4684 tree rrot;
4685 tree zero;
4686 unsigned int num_args;
4688 num_args = gfc_intrinsic_argument_list_length (expr);
4689 args = XALLOCAVEC (tree, num_args);
4691 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4693 if (num_args == 3)
4695 /* Use a library function for the 3 parameter version. */
4696 tree int4type = gfc_get_int_type (4);
4698 type = TREE_TYPE (args[0]);
4699 /* We convert the first argument to at least 4 bytes, and
4700 convert back afterwards. This removes the need for library
4701 functions for all argument sizes, and function will be
4702 aligned to at least 32 bits, so there's no loss. */
4703 if (expr->ts.kind < 4)
4704 args[0] = convert (int4type, args[0]);
4706 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
4707 need loads of library functions. They cannot have values >
4708 BIT_SIZE (I) so the conversion is safe. */
4709 args[1] = convert (int4type, args[1]);
4710 args[2] = convert (int4type, args[2]);
4712 switch (expr->ts.kind)
4714 case 1:
4715 case 2:
4716 case 4:
4717 tmp = gfor_fndecl_math_ishftc4;
4718 break;
4719 case 8:
4720 tmp = gfor_fndecl_math_ishftc8;
4721 break;
4722 case 16:
4723 tmp = gfor_fndecl_math_ishftc16;
4724 break;
4725 default:
4726 gcc_unreachable ();
4728 se->expr = build_call_expr_loc (input_location,
4729 tmp, 3, args[0], args[1], args[2]);
4730 /* Convert the result back to the original type, if we extended
4731 the first argument's width above. */
4732 if (expr->ts.kind < 4)
4733 se->expr = convert (type, se->expr);
4735 return;
4737 type = TREE_TYPE (args[0]);
4739 /* Evaluate arguments only once. */
4740 args[0] = gfc_evaluate_now (args[0], &se->pre);
4741 args[1] = gfc_evaluate_now (args[1], &se->pre);
4743 /* Rotate left if positive. */
4744 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
4746 /* Rotate right if negative. */
4747 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
4748 args[1]);
4749 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
4751 zero = build_int_cst (TREE_TYPE (args[1]), 0);
4752 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, args[1],
4753 zero);
4754 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
4756 /* Do nothing if shift == 0. */
4757 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, args[1],
4758 zero);
4759 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
4760 rrot);
4764 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
4765 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
4767 The conditional expression is necessary because the result of LEADZ(0)
4768 is defined, but the result of __builtin_clz(0) is undefined for most
4769 targets.
4771 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
4772 difference in bit size between the argument of LEADZ and the C int. */
4774 static void
4775 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
4777 tree arg;
4778 tree arg_type;
4779 tree cond;
4780 tree result_type;
4781 tree leadz;
4782 tree bit_size;
4783 tree tmp;
4784 tree func;
4785 int s, argsize;
4787 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4788 argsize = TYPE_PRECISION (TREE_TYPE (arg));
4790 /* Which variant of __builtin_clz* should we call? */
4791 if (argsize <= INT_TYPE_SIZE)
4793 arg_type = unsigned_type_node;
4794 func = builtin_decl_explicit (BUILT_IN_CLZ);
4796 else if (argsize <= LONG_TYPE_SIZE)
4798 arg_type = long_unsigned_type_node;
4799 func = builtin_decl_explicit (BUILT_IN_CLZL);
4801 else if (argsize <= LONG_LONG_TYPE_SIZE)
4803 arg_type = long_long_unsigned_type_node;
4804 func = builtin_decl_explicit (BUILT_IN_CLZLL);
4806 else
4808 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4809 arg_type = gfc_build_uint_type (argsize);
4810 func = NULL_TREE;
4813 /* Convert the actual argument twice: first, to the unsigned type of the
4814 same size; then, to the proper argument type for the built-in
4815 function. But the return type is of the default INTEGER kind. */
4816 arg = fold_convert (gfc_build_uint_type (argsize), arg);
4817 arg = fold_convert (arg_type, arg);
4818 arg = gfc_evaluate_now (arg, &se->pre);
4819 result_type = gfc_get_int_type (gfc_default_integer_kind);
4821 /* Compute LEADZ for the case i .ne. 0. */
4822 if (func)
4824 s = TYPE_PRECISION (arg_type) - argsize;
4825 tmp = fold_convert (result_type,
4826 build_call_expr_loc (input_location, func,
4827 1, arg));
4828 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
4829 tmp, build_int_cst (result_type, s));
4831 else
4833 /* We end up here if the argument type is larger than 'long long'.
4834 We generate this code:
4836 if (x & (ULL_MAX << ULL_SIZE) != 0)
4837 return clzll ((unsigned long long) (x >> ULLSIZE));
4838 else
4839 return ULL_SIZE + clzll ((unsigned long long) x);
4840 where ULL_MAX is the largest value that a ULL_MAX can hold
4841 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
4842 is the bit-size of the long long type (64 in this example). */
4843 tree ullsize, ullmax, tmp1, tmp2, btmp;
4845 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
4846 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
4847 long_long_unsigned_type_node,
4848 build_int_cst (long_long_unsigned_type_node,
4849 0));
4851 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
4852 fold_convert (arg_type, ullmax), ullsize);
4853 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
4854 arg, cond);
4855 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
4856 cond, build_int_cst (arg_type, 0));
4858 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
4859 arg, ullsize);
4860 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
4861 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4862 tmp1 = fold_convert (result_type,
4863 build_call_expr_loc (input_location, btmp, 1, tmp1));
4865 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
4866 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4867 tmp2 = fold_convert (result_type,
4868 build_call_expr_loc (input_location, btmp, 1, tmp2));
4869 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4870 tmp2, ullsize);
4872 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
4873 cond, tmp1, tmp2);
4876 /* Build BIT_SIZE. */
4877 bit_size = build_int_cst (result_type, argsize);
4879 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4880 arg, build_int_cst (arg_type, 0));
4881 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
4882 bit_size, leadz);
4886 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
4888 The conditional expression is necessary because the result of TRAILZ(0)
4889 is defined, but the result of __builtin_ctz(0) is undefined for most
4890 targets. */
4892 static void
4893 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
4895 tree arg;
4896 tree arg_type;
4897 tree cond;
4898 tree result_type;
4899 tree trailz;
4900 tree bit_size;
4901 tree func;
4902 int argsize;
4904 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4905 argsize = TYPE_PRECISION (TREE_TYPE (arg));
4907 /* Which variant of __builtin_ctz* should we call? */
4908 if (argsize <= INT_TYPE_SIZE)
4910 arg_type = unsigned_type_node;
4911 func = builtin_decl_explicit (BUILT_IN_CTZ);
4913 else if (argsize <= LONG_TYPE_SIZE)
4915 arg_type = long_unsigned_type_node;
4916 func = builtin_decl_explicit (BUILT_IN_CTZL);
4918 else if (argsize <= LONG_LONG_TYPE_SIZE)
4920 arg_type = long_long_unsigned_type_node;
4921 func = builtin_decl_explicit (BUILT_IN_CTZLL);
4923 else
4925 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4926 arg_type = gfc_build_uint_type (argsize);
4927 func = NULL_TREE;
4930 /* Convert the actual argument twice: first, to the unsigned type of the
4931 same size; then, to the proper argument type for the built-in
4932 function. But the return type is of the default INTEGER kind. */
4933 arg = fold_convert (gfc_build_uint_type (argsize), arg);
4934 arg = fold_convert (arg_type, arg);
4935 arg = gfc_evaluate_now (arg, &se->pre);
4936 result_type = gfc_get_int_type (gfc_default_integer_kind);
4938 /* Compute TRAILZ for the case i .ne. 0. */
4939 if (func)
4940 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
4941 func, 1, arg));
4942 else
4944 /* We end up here if the argument type is larger than 'long long'.
4945 We generate this code:
4947 if ((x & ULL_MAX) == 0)
4948 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
4949 else
4950 return ctzll ((unsigned long long) x);
4952 where ULL_MAX is the largest value that a ULL_MAX can hold
4953 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
4954 is the bit-size of the long long type (64 in this example). */
4955 tree ullsize, ullmax, tmp1, tmp2, btmp;
4957 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
4958 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
4959 long_long_unsigned_type_node,
4960 build_int_cst (long_long_unsigned_type_node, 0));
4962 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
4963 fold_convert (arg_type, ullmax));
4964 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, cond,
4965 build_int_cst (arg_type, 0));
4967 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
4968 arg, ullsize);
4969 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
4970 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
4971 tmp1 = fold_convert (result_type,
4972 build_call_expr_loc (input_location, btmp, 1, tmp1));
4973 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4974 tmp1, ullsize);
4976 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
4977 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
4978 tmp2 = fold_convert (result_type,
4979 build_call_expr_loc (input_location, btmp, 1, tmp2));
4981 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
4982 cond, tmp1, tmp2);
4985 /* Build BIT_SIZE. */
4986 bit_size = build_int_cst (result_type, argsize);
4988 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4989 arg, build_int_cst (arg_type, 0));
4990 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
4991 bit_size, trailz);
4994 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
4995 for types larger than "long long", we call the long long built-in for
4996 the lower and higher bits and combine the result. */
4998 static void
4999 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
5001 tree arg;
5002 tree arg_type;
5003 tree result_type;
5004 tree func;
5005 int argsize;
5007 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5008 argsize = TYPE_PRECISION (TREE_TYPE (arg));
5009 result_type = gfc_get_int_type (gfc_default_integer_kind);
5011 /* Which variant of the builtin should we call? */
5012 if (argsize <= INT_TYPE_SIZE)
5014 arg_type = unsigned_type_node;
5015 func = builtin_decl_explicit (parity
5016 ? BUILT_IN_PARITY
5017 : BUILT_IN_POPCOUNT);
5019 else if (argsize <= LONG_TYPE_SIZE)
5021 arg_type = long_unsigned_type_node;
5022 func = builtin_decl_explicit (parity
5023 ? BUILT_IN_PARITYL
5024 : BUILT_IN_POPCOUNTL);
5026 else if (argsize <= LONG_LONG_TYPE_SIZE)
5028 arg_type = long_long_unsigned_type_node;
5029 func = builtin_decl_explicit (parity
5030 ? BUILT_IN_PARITYLL
5031 : BUILT_IN_POPCOUNTLL);
5033 else
5035 /* Our argument type is larger than 'long long', which mean none
5036 of the POPCOUNT builtins covers it. We thus call the 'long long'
5037 variant multiple times, and add the results. */
5038 tree utype, arg2, call1, call2;
5040 /* For now, we only cover the case where argsize is twice as large
5041 as 'long long'. */
5042 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
5044 func = builtin_decl_explicit (parity
5045 ? BUILT_IN_PARITYLL
5046 : BUILT_IN_POPCOUNTLL);
5048 /* Convert it to an integer, and store into a variable. */
5049 utype = gfc_build_uint_type (argsize);
5050 arg = fold_convert (utype, arg);
5051 arg = gfc_evaluate_now (arg, &se->pre);
5053 /* Call the builtin twice. */
5054 call1 = build_call_expr_loc (input_location, func, 1,
5055 fold_convert (long_long_unsigned_type_node,
5056 arg));
5058 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
5059 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
5060 call2 = build_call_expr_loc (input_location, func, 1,
5061 fold_convert (long_long_unsigned_type_node,
5062 arg2));
5064 /* Combine the results. */
5065 if (parity)
5066 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
5067 call1, call2);
5068 else
5069 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
5070 call1, call2);
5072 return;
5075 /* Convert the actual argument twice: first, to the unsigned type of the
5076 same size; then, to the proper argument type for the built-in
5077 function. */
5078 arg = fold_convert (gfc_build_uint_type (argsize), arg);
5079 arg = fold_convert (arg_type, arg);
5081 se->expr = fold_convert (result_type,
5082 build_call_expr_loc (input_location, func, 1, arg));
5086 /* Process an intrinsic with unspecified argument-types that has an optional
5087 argument (which could be of type character), e.g. EOSHIFT. For those, we
5088 need to append the string length of the optional argument if it is not
5089 present and the type is really character.
5090 primary specifies the position (starting at 1) of the non-optional argument
5091 specifying the type and optional gives the position of the optional
5092 argument in the arglist. */
5094 static void
5095 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
5096 unsigned primary, unsigned optional)
5098 gfc_actual_arglist* prim_arg;
5099 gfc_actual_arglist* opt_arg;
5100 unsigned cur_pos;
5101 gfc_actual_arglist* arg;
5102 gfc_symbol* sym;
5103 vec<tree, va_gc> *append_args;
5105 /* Find the two arguments given as position. */
5106 cur_pos = 0;
5107 prim_arg = NULL;
5108 opt_arg = NULL;
5109 for (arg = expr->value.function.actual; arg; arg = arg->next)
5111 ++cur_pos;
5113 if (cur_pos == primary)
5114 prim_arg = arg;
5115 if (cur_pos == optional)
5116 opt_arg = arg;
5118 if (cur_pos >= primary && cur_pos >= optional)
5119 break;
5121 gcc_assert (prim_arg);
5122 gcc_assert (prim_arg->expr);
5123 gcc_assert (opt_arg);
5125 /* If we do have type CHARACTER and the optional argument is really absent,
5126 append a dummy 0 as string length. */
5127 append_args = NULL;
5128 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
5130 tree dummy;
5132 dummy = build_int_cst (gfc_charlen_type_node, 0);
5133 vec_alloc (append_args, 1);
5134 append_args->quick_push (dummy);
5137 /* Build the call itself. */
5138 gcc_assert (!se->ignore_optional);
5139 sym = gfc_get_symbol_for_expr (expr, false);
5140 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
5141 append_args);
5142 gfc_free_symbol (sym);
5146 /* The length of a character string. */
5147 static void
5148 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
5150 tree len;
5151 tree type;
5152 tree decl;
5153 gfc_symbol *sym;
5154 gfc_se argse;
5155 gfc_expr *arg;
5157 gcc_assert (!se->ss);
5159 arg = expr->value.function.actual->expr;
5161 type = gfc_typenode_for_spec (&expr->ts);
5162 switch (arg->expr_type)
5164 case EXPR_CONSTANT:
5165 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
5166 break;
5168 case EXPR_ARRAY:
5169 /* Obtain the string length from the function used by
5170 trans-array.c(gfc_trans_array_constructor). */
5171 len = NULL_TREE;
5172 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
5173 break;
5175 case EXPR_VARIABLE:
5176 if (arg->ref == NULL
5177 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
5179 /* This doesn't catch all cases.
5180 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
5181 and the surrounding thread. */
5182 sym = arg->symtree->n.sym;
5183 decl = gfc_get_symbol_decl (sym);
5184 if (decl == current_function_decl && sym->attr.function
5185 && (sym->result == sym))
5186 decl = gfc_get_fake_result_decl (sym, 0);
5188 len = sym->ts.u.cl->backend_decl;
5189 gcc_assert (len);
5190 break;
5193 /* Otherwise fall through. */
5195 default:
5196 /* Anybody stupid enough to do this deserves inefficient code. */
5197 gfc_init_se (&argse, se);
5198 if (arg->rank == 0)
5199 gfc_conv_expr (&argse, arg);
5200 else
5201 gfc_conv_expr_descriptor (&argse, arg);
5202 gfc_add_block_to_block (&se->pre, &argse.pre);
5203 gfc_add_block_to_block (&se->post, &argse.post);
5204 len = argse.string_length;
5205 break;
5207 se->expr = convert (type, len);
5210 /* The length of a character string not including trailing blanks. */
5211 static void
5212 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
5214 int kind = expr->value.function.actual->expr->ts.kind;
5215 tree args[2], type, fndecl;
5217 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5218 type = gfc_typenode_for_spec (&expr->ts);
5220 if (kind == 1)
5221 fndecl = gfor_fndecl_string_len_trim;
5222 else if (kind == 4)
5223 fndecl = gfor_fndecl_string_len_trim_char4;
5224 else
5225 gcc_unreachable ();
5227 se->expr = build_call_expr_loc (input_location,
5228 fndecl, 2, args[0], args[1]);
5229 se->expr = convert (type, se->expr);
5233 /* Returns the starting position of a substring within a string. */
5235 static void
5236 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
5237 tree function)
5239 tree logical4_type_node = gfc_get_logical_type (4);
5240 tree type;
5241 tree fndecl;
5242 tree *args;
5243 unsigned int num_args;
5245 args = XALLOCAVEC (tree, 5);
5247 /* Get number of arguments; characters count double due to the
5248 string length argument. Kind= is not passed to the library
5249 and thus ignored. */
5250 if (expr->value.function.actual->next->next->expr == NULL)
5251 num_args = 4;
5252 else
5253 num_args = 5;
5255 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
5256 type = gfc_typenode_for_spec (&expr->ts);
5258 if (num_args == 4)
5259 args[4] = build_int_cst (logical4_type_node, 0);
5260 else
5261 args[4] = convert (logical4_type_node, args[4]);
5263 fndecl = build_addr (function, current_function_decl);
5264 se->expr = build_call_array_loc (input_location,
5265 TREE_TYPE (TREE_TYPE (function)), fndecl,
5266 5, args);
5267 se->expr = convert (type, se->expr);
5271 /* The ascii value for a single character. */
5272 static void
5273 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
5275 tree args[3], type, pchartype;
5276 int nargs;
5278 nargs = gfc_intrinsic_argument_list_length (expr);
5279 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
5280 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
5281 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
5282 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
5283 type = gfc_typenode_for_spec (&expr->ts);
5285 se->expr = build_fold_indirect_ref_loc (input_location,
5286 args[1]);
5287 se->expr = convert (type, se->expr);
5291 /* Intrinsic ISNAN calls __builtin_isnan. */
5293 static void
5294 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
5296 tree arg;
5298 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5299 se->expr = build_call_expr_loc (input_location,
5300 builtin_decl_explicit (BUILT_IN_ISNAN),
5301 1, arg);
5302 STRIP_TYPE_NOPS (se->expr);
5303 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
5307 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
5308 their argument against a constant integer value. */
5310 static void
5311 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
5313 tree arg;
5315 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5316 se->expr = fold_build2_loc (input_location, EQ_EXPR,
5317 gfc_typenode_for_spec (&expr->ts),
5318 arg, build_int_cst (TREE_TYPE (arg), value));
5323 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
5325 static void
5326 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
5328 tree tsource;
5329 tree fsource;
5330 tree mask;
5331 tree type;
5332 tree len, len2;
5333 tree *args;
5334 unsigned int num_args;
5336 num_args = gfc_intrinsic_argument_list_length (expr);
5337 args = XALLOCAVEC (tree, num_args);
5339 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
5340 if (expr->ts.type != BT_CHARACTER)
5342 tsource = args[0];
5343 fsource = args[1];
5344 mask = args[2];
5346 else
5348 /* We do the same as in the non-character case, but the argument
5349 list is different because of the string length arguments. We
5350 also have to set the string length for the result. */
5351 len = args[0];
5352 tsource = args[1];
5353 len2 = args[2];
5354 fsource = args[3];
5355 mask = args[4];
5357 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
5358 &se->pre);
5359 se->string_length = len;
5361 type = TREE_TYPE (tsource);
5362 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
5363 fold_convert (type, fsource));
5367 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
5369 static void
5370 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
5372 tree args[3], mask, type;
5374 gfc_conv_intrinsic_function_args (se, expr, args, 3);
5375 mask = gfc_evaluate_now (args[2], &se->pre);
5377 type = TREE_TYPE (args[0]);
5378 gcc_assert (TREE_TYPE (args[1]) == type);
5379 gcc_assert (TREE_TYPE (mask) == type);
5381 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
5382 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
5383 fold_build1_loc (input_location, BIT_NOT_EXPR,
5384 type, mask));
5385 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
5386 args[0], args[1]);
5390 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
5391 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
5393 static void
5394 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
5396 tree arg, allones, type, utype, res, cond, bitsize;
5397 int i;
5399 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5400 arg = gfc_evaluate_now (arg, &se->pre);
5402 type = gfc_get_int_type (expr->ts.kind);
5403 utype = unsigned_type_for (type);
5405 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
5406 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
5408 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
5409 build_int_cst (utype, 0));
5411 if (left)
5413 /* Left-justified mask. */
5414 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
5415 bitsize, arg);
5416 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
5417 fold_convert (utype, res));
5419 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
5420 smaller than type width. */
5421 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
5422 build_int_cst (TREE_TYPE (arg), 0));
5423 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
5424 build_int_cst (utype, 0), res);
5426 else
5428 /* Right-justified mask. */
5429 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
5430 fold_convert (utype, arg));
5431 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
5433 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
5434 strictly smaller than type width. */
5435 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5436 arg, bitsize);
5437 res = fold_build3_loc (input_location, COND_EXPR, utype,
5438 cond, allones, res);
5441 se->expr = fold_convert (type, res);
5445 /* FRACTION (s) is translated into:
5446 isfinite (s) ? frexp (s, &dummy_int) : NaN */
5447 static void
5448 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
5450 tree arg, type, tmp, res, frexp, cond;
5452 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
5454 type = gfc_typenode_for_spec (&expr->ts);
5455 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5456 arg = gfc_evaluate_now (arg, &se->pre);
5458 cond = build_call_expr_loc (input_location,
5459 builtin_decl_explicit (BUILT_IN_ISFINITE),
5460 1, arg);
5462 tmp = gfc_create_var (integer_type_node, NULL);
5463 res = build_call_expr_loc (input_location, frexp, 2,
5464 fold_convert (type, arg),
5465 gfc_build_addr_expr (NULL_TREE, tmp));
5466 res = fold_convert (type, res);
5468 se->expr = fold_build3_loc (input_location, COND_EXPR, type,
5469 cond, res, gfc_build_nan (type, ""));
5473 /* NEAREST (s, dir) is translated into
5474 tmp = copysign (HUGE_VAL, dir);
5475 return nextafter (s, tmp);
5477 static void
5478 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
5480 tree args[2], type, tmp, nextafter, copysign, huge_val;
5482 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
5483 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
5485 type = gfc_typenode_for_spec (&expr->ts);
5486 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5488 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
5489 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
5490 fold_convert (type, args[1]));
5491 se->expr = build_call_expr_loc (input_location, nextafter, 2,
5492 fold_convert (type, args[0]), tmp);
5493 se->expr = fold_convert (type, se->expr);
5497 /* SPACING (s) is translated into
5498 int e;
5499 if (!isfinite (s))
5500 res = NaN;
5501 else if (s == 0)
5502 res = tiny;
5503 else
5505 frexp (s, &e);
5506 e = e - prec;
5507 e = MAX_EXPR (e, emin);
5508 res = scalbn (1., e);
5510 return res;
5512 where prec is the precision of s, gfc_real_kinds[k].digits,
5513 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
5514 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
5516 static void
5517 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
5519 tree arg, type, prec, emin, tiny, res, e;
5520 tree cond, nan, tmp, frexp, scalbn;
5521 int k;
5522 stmtblock_t block;
5524 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
5525 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
5526 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
5527 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
5529 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
5530 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5532 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5533 arg = gfc_evaluate_now (arg, &se->pre);
5535 type = gfc_typenode_for_spec (&expr->ts);
5536 e = gfc_create_var (integer_type_node, NULL);
5537 res = gfc_create_var (type, NULL);
5540 /* Build the block for s /= 0. */
5541 gfc_start_block (&block);
5542 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
5543 gfc_build_addr_expr (NULL_TREE, e));
5544 gfc_add_expr_to_block (&block, tmp);
5546 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
5547 prec);
5548 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
5549 integer_type_node, tmp, emin));
5551 tmp = build_call_expr_loc (input_location, scalbn, 2,
5552 build_real_from_int_cst (type, integer_one_node), e);
5553 gfc_add_modify (&block, res, tmp);
5555 /* Finish by building the IF statement for value zero. */
5556 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
5557 build_real_from_int_cst (type, integer_zero_node));
5558 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
5559 gfc_finish_block (&block));
5561 /* And deal with infinities and NaNs. */
5562 cond = build_call_expr_loc (input_location,
5563 builtin_decl_explicit (BUILT_IN_ISFINITE),
5564 1, arg);
5565 nan = gfc_build_nan (type, "");
5566 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
5568 gfc_add_expr_to_block (&se->pre, tmp);
5569 se->expr = res;
5573 /* RRSPACING (s) is translated into
5574 int e;
5575 real x;
5576 x = fabs (s);
5577 if (isfinite (x))
5579 if (x != 0)
5581 frexp (s, &e);
5582 x = scalbn (x, precision - e);
5585 else
5586 x = NaN;
5587 return x;
5589 where precision is gfc_real_kinds[k].digits. */
5591 static void
5592 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
5594 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
5595 int prec, k;
5596 stmtblock_t block;
5598 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
5599 prec = gfc_real_kinds[k].digits;
5601 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
5602 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5603 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
5605 type = gfc_typenode_for_spec (&expr->ts);
5606 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5607 arg = gfc_evaluate_now (arg, &se->pre);
5609 e = gfc_create_var (integer_type_node, NULL);
5610 x = gfc_create_var (type, NULL);
5611 gfc_add_modify (&se->pre, x,
5612 build_call_expr_loc (input_location, fabs, 1, arg));
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,
5621 build_int_cst (integer_type_node, prec), e);
5622 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
5623 gfc_add_modify (&block, x, tmp);
5624 stmt = gfc_finish_block (&block);
5626 /* if (x != 0) */
5627 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, x,
5628 build_real_from_int_cst (type, integer_zero_node));
5629 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
5631 /* And deal with infinities and NaNs. */
5632 cond = build_call_expr_loc (input_location,
5633 builtin_decl_explicit (BUILT_IN_ISFINITE),
5634 1, x);
5635 nan = gfc_build_nan (type, "");
5636 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
5638 gfc_add_expr_to_block (&se->pre, tmp);
5639 se->expr = fold_convert (type, x);
5643 /* SCALE (s, i) is translated into scalbn (s, i). */
5644 static void
5645 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
5647 tree args[2], type, scalbn;
5649 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5651 type = gfc_typenode_for_spec (&expr->ts);
5652 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5653 se->expr = build_call_expr_loc (input_location, scalbn, 2,
5654 fold_convert (type, args[0]),
5655 fold_convert (integer_type_node, args[1]));
5656 se->expr = fold_convert (type, se->expr);
5660 /* SET_EXPONENT (s, i) is translated into
5661 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
5662 static void
5663 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
5665 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
5667 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
5668 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5670 type = gfc_typenode_for_spec (&expr->ts);
5671 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5672 args[0] = gfc_evaluate_now (args[0], &se->pre);
5674 tmp = gfc_create_var (integer_type_node, NULL);
5675 tmp = build_call_expr_loc (input_location, frexp, 2,
5676 fold_convert (type, args[0]),
5677 gfc_build_addr_expr (NULL_TREE, tmp));
5678 res = build_call_expr_loc (input_location, scalbn, 2, tmp,
5679 fold_convert (integer_type_node, args[1]));
5680 res = fold_convert (type, res);
5682 /* Call to isfinite */
5683 cond = build_call_expr_loc (input_location,
5684 builtin_decl_explicit (BUILT_IN_ISFINITE),
5685 1, args[0]);
5686 nan = gfc_build_nan (type, "");
5688 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5689 res, nan);
5693 static void
5694 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
5696 gfc_actual_arglist *actual;
5697 tree arg1;
5698 tree type;
5699 tree fncall0;
5700 tree fncall1;
5701 gfc_se argse;
5703 gfc_init_se (&argse, NULL);
5704 actual = expr->value.function.actual;
5706 if (actual->expr->ts.type == BT_CLASS)
5707 gfc_add_class_array_ref (actual->expr);
5709 argse.want_pointer = 1;
5710 argse.data_not_needed = 1;
5711 gfc_conv_expr_descriptor (&argse, actual->expr);
5712 gfc_add_block_to_block (&se->pre, &argse.pre);
5713 gfc_add_block_to_block (&se->post, &argse.post);
5714 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
5716 /* Build the call to size0. */
5717 fncall0 = build_call_expr_loc (input_location,
5718 gfor_fndecl_size0, 1, arg1);
5720 actual = actual->next;
5722 if (actual->expr)
5724 gfc_init_se (&argse, NULL);
5725 gfc_conv_expr_type (&argse, actual->expr,
5726 gfc_array_index_type);
5727 gfc_add_block_to_block (&se->pre, &argse.pre);
5729 /* Unusually, for an intrinsic, size does not exclude
5730 an optional arg2, so we must test for it. */
5731 if (actual->expr->expr_type == EXPR_VARIABLE
5732 && actual->expr->symtree->n.sym->attr.dummy
5733 && actual->expr->symtree->n.sym->attr.optional)
5735 tree tmp;
5736 /* Build the call to size1. */
5737 fncall1 = build_call_expr_loc (input_location,
5738 gfor_fndecl_size1, 2,
5739 arg1, argse.expr);
5741 gfc_init_se (&argse, NULL);
5742 argse.want_pointer = 1;
5743 argse.data_not_needed = 1;
5744 gfc_conv_expr (&argse, actual->expr);
5745 gfc_add_block_to_block (&se->pre, &argse.pre);
5746 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5747 argse.expr, null_pointer_node);
5748 tmp = gfc_evaluate_now (tmp, &se->pre);
5749 se->expr = fold_build3_loc (input_location, COND_EXPR,
5750 pvoid_type_node, tmp, fncall1, fncall0);
5752 else
5754 se->expr = NULL_TREE;
5755 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
5756 gfc_array_index_type,
5757 argse.expr, gfc_index_one_node);
5760 else if (expr->value.function.actual->expr->rank == 1)
5762 argse.expr = gfc_index_zero_node;
5763 se->expr = NULL_TREE;
5765 else
5766 se->expr = fncall0;
5768 if (se->expr == NULL_TREE)
5770 tree ubound, lbound;
5772 arg1 = build_fold_indirect_ref_loc (input_location,
5773 arg1);
5774 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
5775 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
5776 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
5777 gfc_array_index_type, ubound, lbound);
5778 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
5779 gfc_array_index_type,
5780 se->expr, gfc_index_one_node);
5781 se->expr = fold_build2_loc (input_location, MAX_EXPR,
5782 gfc_array_index_type, se->expr,
5783 gfc_index_zero_node);
5786 type = gfc_typenode_for_spec (&expr->ts);
5787 se->expr = convert (type, se->expr);
5791 /* Helper function to compute the size of a character variable,
5792 excluding the terminating null characters. The result has
5793 gfc_array_index_type type. */
5795 tree
5796 size_of_string_in_bytes (int kind, tree string_length)
5798 tree bytesize;
5799 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
5801 bytesize = build_int_cst (gfc_array_index_type,
5802 gfc_character_kinds[i].bit_size / 8);
5804 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5805 bytesize,
5806 fold_convert (gfc_array_index_type, string_length));
5810 static void
5811 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
5813 gfc_expr *arg;
5814 gfc_se argse;
5815 tree source_bytes;
5816 tree tmp;
5817 tree lower;
5818 tree upper;
5819 tree byte_size;
5820 int n;
5822 gfc_init_se (&argse, NULL);
5823 arg = expr->value.function.actual->expr;
5825 if (arg->rank || arg->ts.type == BT_ASSUMED)
5826 gfc_conv_expr_descriptor (&argse, arg);
5827 else
5828 gfc_conv_expr_reference (&argse, arg);
5830 if (arg->ts.type == BT_ASSUMED)
5832 /* This only works if an array descriptor has been passed; thus, extract
5833 the size from the descriptor. */
5834 gcc_assert (TYPE_PRECISION (gfc_array_index_type)
5835 == TYPE_PRECISION (size_type_node));
5836 tmp = arg->symtree->n.sym->backend_decl;
5837 tmp = DECL_LANG_SPECIFIC (tmp)
5838 && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
5839 ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
5840 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
5841 tmp = build_fold_indirect_ref_loc (input_location, tmp);
5842 tmp = fold_convert (size_type_node, gfc_conv_descriptor_dtype (tmp));
5843 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, TREE_TYPE (tmp), tmp,
5844 build_int_cst (TREE_TYPE (tmp),
5845 GFC_DTYPE_SIZE_SHIFT));
5846 byte_size = fold_convert (gfc_array_index_type, tmp);
5848 else if (arg->ts.type == BT_CLASS)
5850 if (arg->rank)
5851 byte_size = gfc_vtable_size_get (TREE_OPERAND (argse.expr, 0));
5852 else
5853 byte_size = gfc_vtable_size_get (argse.expr);
5855 else
5857 if (arg->ts.type == BT_CHARACTER)
5858 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
5859 else
5861 if (arg->rank == 0)
5862 byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5863 argse.expr));
5864 else
5865 byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
5866 byte_size = fold_convert (gfc_array_index_type,
5867 size_in_bytes (byte_size));
5871 if (arg->rank == 0)
5872 se->expr = byte_size;
5873 else
5875 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
5876 gfc_add_modify (&argse.pre, source_bytes, byte_size);
5878 if (arg->rank == -1)
5880 tree cond, loop_var, exit_label;
5881 stmtblock_t body;
5883 tmp = fold_convert (gfc_array_index_type,
5884 gfc_conv_descriptor_rank (argse.expr));
5885 loop_var = gfc_create_var (gfc_array_index_type, "i");
5886 gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
5887 exit_label = gfc_build_label_decl (NULL_TREE);
5889 /* Create loop:
5890 for (;;)
5892 if (i >= rank)
5893 goto exit;
5894 source_bytes = source_bytes * array.dim[i].extent;
5895 i = i + 1;
5897 exit: */
5898 gfc_start_block (&body);
5899 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
5900 loop_var, tmp);
5901 tmp = build1_v (GOTO_EXPR, exit_label);
5902 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5903 cond, tmp, build_empty_stmt (input_location));
5904 gfc_add_expr_to_block (&body, tmp);
5906 lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
5907 upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
5908 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
5909 tmp = fold_build2_loc (input_location, MULT_EXPR,
5910 gfc_array_index_type, tmp, source_bytes);
5911 gfc_add_modify (&body, source_bytes, tmp);
5913 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5914 gfc_array_index_type, loop_var,
5915 gfc_index_one_node);
5916 gfc_add_modify_loc (input_location, &body, loop_var, tmp);
5918 tmp = gfc_finish_block (&body);
5920 tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
5921 tmp);
5922 gfc_add_expr_to_block (&argse.pre, tmp);
5924 tmp = build1_v (LABEL_EXPR, exit_label);
5925 gfc_add_expr_to_block (&argse.pre, tmp);
5927 else
5929 /* Obtain the size of the array in bytes. */
5930 for (n = 0; n < arg->rank; n++)
5932 tree idx;
5933 idx = gfc_rank_cst[n];
5934 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
5935 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
5936 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
5937 tmp = fold_build2_loc (input_location, MULT_EXPR,
5938 gfc_array_index_type, tmp, source_bytes);
5939 gfc_add_modify (&argse.pre, source_bytes, tmp);
5942 se->expr = source_bytes;
5945 gfc_add_block_to_block (&se->pre, &argse.pre);
5949 static void
5950 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
5952 gfc_expr *arg;
5953 gfc_se argse;
5954 tree type, result_type, tmp;
5956 arg = expr->value.function.actual->expr;
5958 gfc_init_se (&argse, NULL);
5959 result_type = gfc_get_int_type (expr->ts.kind);
5961 if (arg->rank == 0)
5963 if (arg->ts.type == BT_CLASS)
5965 gfc_add_vptr_component (arg);
5966 gfc_add_size_component (arg);
5967 gfc_conv_expr (&argse, arg);
5968 tmp = fold_convert (result_type, argse.expr);
5969 goto done;
5972 gfc_conv_expr_reference (&argse, arg);
5973 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5974 argse.expr));
5976 else
5978 argse.want_pointer = 0;
5979 gfc_conv_expr_descriptor (&argse, arg);
5980 if (arg->ts.type == BT_CLASS)
5982 tmp = gfc_vtable_size_get (TREE_OPERAND (argse.expr, 0));
5983 tmp = fold_convert (result_type, tmp);
5984 goto done;
5986 type = gfc_get_element_type (TREE_TYPE (argse.expr));
5989 /* Obtain the argument's word length. */
5990 if (arg->ts.type == BT_CHARACTER)
5991 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
5992 else
5993 tmp = size_in_bytes (type);
5994 tmp = fold_convert (result_type, tmp);
5996 done:
5997 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
5998 build_int_cst (result_type, BITS_PER_UNIT));
5999 gfc_add_block_to_block (&se->pre, &argse.pre);
6003 /* Intrinsic string comparison functions. */
6005 static void
6006 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
6008 tree args[4];
6010 gfc_conv_intrinsic_function_args (se, expr, args, 4);
6012 se->expr
6013 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
6014 expr->value.function.actual->expr->ts.kind,
6015 op);
6016 se->expr = fold_build2_loc (input_location, op,
6017 gfc_typenode_for_spec (&expr->ts), se->expr,
6018 build_int_cst (TREE_TYPE (se->expr), 0));
6021 /* Generate a call to the adjustl/adjustr library function. */
6022 static void
6023 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
6025 tree args[3];
6026 tree len;
6027 tree type;
6028 tree var;
6029 tree tmp;
6031 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
6032 len = args[1];
6034 type = TREE_TYPE (args[2]);
6035 var = gfc_conv_string_tmp (se, type, len);
6036 args[0] = var;
6038 tmp = build_call_expr_loc (input_location,
6039 fndecl, 3, args[0], args[1], args[2]);
6040 gfc_add_expr_to_block (&se->pre, tmp);
6041 se->expr = var;
6042 se->string_length = len;
6046 /* Generate code for the TRANSFER intrinsic:
6047 For scalar results:
6048 DEST = TRANSFER (SOURCE, MOLD)
6049 where:
6050 typeof<DEST> = typeof<MOLD>
6051 and:
6052 MOLD is scalar.
6054 For array results:
6055 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
6056 where:
6057 typeof<DEST> = typeof<MOLD>
6058 and:
6059 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
6060 sizeof (DEST(0) * SIZE). */
6061 static void
6062 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
6064 tree tmp;
6065 tree tmpdecl;
6066 tree ptr;
6067 tree extent;
6068 tree source;
6069 tree source_type;
6070 tree source_bytes;
6071 tree mold_type;
6072 tree dest_word_len;
6073 tree size_words;
6074 tree size_bytes;
6075 tree upper;
6076 tree lower;
6077 tree stmt;
6078 gfc_actual_arglist *arg;
6079 gfc_se argse;
6080 gfc_array_info *info;
6081 stmtblock_t block;
6082 int n;
6083 bool scalar_mold;
6084 gfc_expr *source_expr, *mold_expr;
6086 info = NULL;
6087 if (se->loop)
6088 info = &se->ss->info->data.array;
6090 /* Convert SOURCE. The output from this stage is:-
6091 source_bytes = length of the source in bytes
6092 source = pointer to the source data. */
6093 arg = expr->value.function.actual;
6094 source_expr = arg->expr;
6096 /* Ensure double transfer through LOGICAL preserves all
6097 the needed bits. */
6098 if (arg->expr->expr_type == EXPR_FUNCTION
6099 && arg->expr->value.function.esym == NULL
6100 && arg->expr->value.function.isym != NULL
6101 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
6102 && arg->expr->ts.type == BT_LOGICAL
6103 && expr->ts.type != arg->expr->ts.type)
6104 arg->expr->value.function.name = "__transfer_in_transfer";
6106 gfc_init_se (&argse, NULL);
6108 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
6110 /* Obtain the pointer to source and the length of source in bytes. */
6111 if (arg->expr->rank == 0)
6113 gfc_conv_expr_reference (&argse, arg->expr);
6114 if (arg->expr->ts.type == BT_CLASS)
6115 source = gfc_class_data_get (argse.expr);
6116 else
6117 source = argse.expr;
6119 /* Obtain the source word length. */
6120 switch (arg->expr->ts.type)
6122 case BT_CHARACTER:
6123 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
6124 argse.string_length);
6125 break;
6126 case BT_CLASS:
6127 tmp = gfc_vtable_size_get (argse.expr);
6128 break;
6129 default:
6130 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
6131 source));
6132 tmp = fold_convert (gfc_array_index_type,
6133 size_in_bytes (source_type));
6134 break;
6137 else
6139 argse.want_pointer = 0;
6140 gfc_conv_expr_descriptor (&argse, arg->expr);
6141 source = gfc_conv_descriptor_data_get (argse.expr);
6142 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
6144 /* Repack the source if not simply contiguous. */
6145 if (!gfc_is_simply_contiguous (arg->expr, false))
6147 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
6149 if (gfc_option.warn_array_temp)
6150 gfc_warning ("Creating array temporary at %L", &expr->where);
6152 source = build_call_expr_loc (input_location,
6153 gfor_fndecl_in_pack, 1, tmp);
6154 source = gfc_evaluate_now (source, &argse.pre);
6156 /* Free the temporary. */
6157 gfc_start_block (&block);
6158 tmp = gfc_call_free (convert (pvoid_type_node, source));
6159 gfc_add_expr_to_block (&block, tmp);
6160 stmt = gfc_finish_block (&block);
6162 /* Clean up if it was repacked. */
6163 gfc_init_block (&block);
6164 tmp = gfc_conv_array_data (argse.expr);
6165 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6166 source, tmp);
6167 tmp = build3_v (COND_EXPR, tmp, stmt,
6168 build_empty_stmt (input_location));
6169 gfc_add_expr_to_block (&block, tmp);
6170 gfc_add_block_to_block (&block, &se->post);
6171 gfc_init_block (&se->post);
6172 gfc_add_block_to_block (&se->post, &block);
6175 /* Obtain the source word length. */
6176 if (arg->expr->ts.type == BT_CHARACTER)
6177 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
6178 argse.string_length);
6179 else
6180 tmp = fold_convert (gfc_array_index_type,
6181 size_in_bytes (source_type));
6183 /* Obtain the size of the array in bytes. */
6184 extent = gfc_create_var (gfc_array_index_type, NULL);
6185 for (n = 0; n < arg->expr->rank; n++)
6187 tree idx;
6188 idx = gfc_rank_cst[n];
6189 gfc_add_modify (&argse.pre, source_bytes, tmp);
6190 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
6191 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
6192 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6193 gfc_array_index_type, upper, lower);
6194 gfc_add_modify (&argse.pre, extent, tmp);
6195 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6196 gfc_array_index_type, extent,
6197 gfc_index_one_node);
6198 tmp = fold_build2_loc (input_location, MULT_EXPR,
6199 gfc_array_index_type, tmp, source_bytes);
6203 gfc_add_modify (&argse.pre, source_bytes, tmp);
6204 gfc_add_block_to_block (&se->pre, &argse.pre);
6205 gfc_add_block_to_block (&se->post, &argse.post);
6207 /* Now convert MOLD. The outputs are:
6208 mold_type = the TREE type of MOLD
6209 dest_word_len = destination word length in bytes. */
6210 arg = arg->next;
6211 mold_expr = arg->expr;
6213 gfc_init_se (&argse, NULL);
6215 scalar_mold = arg->expr->rank == 0;
6217 if (arg->expr->rank == 0)
6219 gfc_conv_expr_reference (&argse, arg->expr);
6220 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
6221 argse.expr));
6223 else
6225 gfc_init_se (&argse, NULL);
6226 argse.want_pointer = 0;
6227 gfc_conv_expr_descriptor (&argse, arg->expr);
6228 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
6231 gfc_add_block_to_block (&se->pre, &argse.pre);
6232 gfc_add_block_to_block (&se->post, &argse.post);
6234 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
6236 /* If this TRANSFER is nested in another TRANSFER, use a type
6237 that preserves all bits. */
6238 if (arg->expr->ts.type == BT_LOGICAL)
6239 mold_type = gfc_get_int_type (arg->expr->ts.kind);
6242 /* Obtain the destination word length. */
6243 switch (arg->expr->ts.type)
6245 case BT_CHARACTER:
6246 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
6247 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
6248 break;
6249 case BT_CLASS:
6250 tmp = gfc_vtable_size_get (argse.expr);
6251 break;
6252 default:
6253 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
6254 break;
6256 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
6257 gfc_add_modify (&se->pre, dest_word_len, tmp);
6259 /* Finally convert SIZE, if it is present. */
6260 arg = arg->next;
6261 size_words = gfc_create_var (gfc_array_index_type, NULL);
6263 if (arg->expr)
6265 gfc_init_se (&argse, NULL);
6266 gfc_conv_expr_reference (&argse, arg->expr);
6267 tmp = convert (gfc_array_index_type,
6268 build_fold_indirect_ref_loc (input_location,
6269 argse.expr));
6270 gfc_add_block_to_block (&se->pre, &argse.pre);
6271 gfc_add_block_to_block (&se->post, &argse.post);
6273 else
6274 tmp = NULL_TREE;
6276 /* Separate array and scalar results. */
6277 if (scalar_mold && tmp == NULL_TREE)
6278 goto scalar_transfer;
6280 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
6281 if (tmp != NULL_TREE)
6282 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6283 tmp, dest_word_len);
6284 else
6285 tmp = source_bytes;
6287 gfc_add_modify (&se->pre, size_bytes, tmp);
6288 gfc_add_modify (&se->pre, size_words,
6289 fold_build2_loc (input_location, CEIL_DIV_EXPR,
6290 gfc_array_index_type,
6291 size_bytes, dest_word_len));
6293 /* Evaluate the bounds of the result. If the loop range exists, we have
6294 to check if it is too large. If so, we modify loop->to be consistent
6295 with min(size, size(source)). Otherwise, size is made consistent with
6296 the loop range, so that the right number of bytes is transferred.*/
6297 n = se->loop->order[0];
6298 if (se->loop->to[n] != NULL_TREE)
6300 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6301 se->loop->to[n], se->loop->from[n]);
6302 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
6303 tmp, gfc_index_one_node);
6304 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
6305 tmp, size_words);
6306 gfc_add_modify (&se->pre, size_words, tmp);
6307 gfc_add_modify (&se->pre, size_bytes,
6308 fold_build2_loc (input_location, MULT_EXPR,
6309 gfc_array_index_type,
6310 size_words, dest_word_len));
6311 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
6312 size_words, se->loop->from[n]);
6313 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6314 upper, gfc_index_one_node);
6316 else
6318 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6319 size_words, gfc_index_one_node);
6320 se->loop->from[n] = gfc_index_zero_node;
6323 se->loop->to[n] = upper;
6325 /* Build a destination descriptor, using the pointer, source, as the
6326 data field. */
6327 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
6328 NULL_TREE, false, true, false, &expr->where);
6330 /* Cast the pointer to the result. */
6331 tmp = gfc_conv_descriptor_data_get (info->descriptor);
6332 tmp = fold_convert (pvoid_type_node, tmp);
6334 /* Use memcpy to do the transfer. */
6336 = build_call_expr_loc (input_location,
6337 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
6338 fold_convert (pvoid_type_node, source),
6339 fold_convert (size_type_node,
6340 fold_build2_loc (input_location,
6341 MIN_EXPR,
6342 gfc_array_index_type,
6343 size_bytes,
6344 source_bytes)));
6345 gfc_add_expr_to_block (&se->pre, tmp);
6347 se->expr = info->descriptor;
6348 if (expr->ts.type == BT_CHARACTER)
6349 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
6351 return;
6353 /* Deal with scalar results. */
6354 scalar_transfer:
6355 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
6356 dest_word_len, source_bytes);
6357 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
6358 extent, gfc_index_zero_node);
6360 if (expr->ts.type == BT_CHARACTER)
6362 tree direct, indirect, free;
6364 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
6365 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
6366 "transfer");
6368 /* If source is longer than the destination, use a pointer to
6369 the source directly. */
6370 gfc_init_block (&block);
6371 gfc_add_modify (&block, tmpdecl, ptr);
6372 direct = gfc_finish_block (&block);
6374 /* Otherwise, allocate a string with the length of the destination
6375 and copy the source into it. */
6376 gfc_init_block (&block);
6377 tmp = gfc_get_pchar_type (expr->ts.kind);
6378 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
6379 gfc_add_modify (&block, tmpdecl,
6380 fold_convert (TREE_TYPE (ptr), tmp));
6381 tmp = build_call_expr_loc (input_location,
6382 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
6383 fold_convert (pvoid_type_node, tmpdecl),
6384 fold_convert (pvoid_type_node, ptr),
6385 fold_convert (size_type_node, extent));
6386 gfc_add_expr_to_block (&block, tmp);
6387 indirect = gfc_finish_block (&block);
6389 /* Wrap it up with the condition. */
6390 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
6391 dest_word_len, source_bytes);
6392 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
6393 gfc_add_expr_to_block (&se->pre, tmp);
6395 /* Free the temporary string, if necessary. */
6396 free = gfc_call_free (tmpdecl);
6397 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6398 dest_word_len, source_bytes);
6399 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
6400 gfc_add_expr_to_block (&se->post, tmp);
6402 se->expr = tmpdecl;
6403 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
6405 else
6407 tmpdecl = gfc_create_var (mold_type, "transfer");
6409 ptr = convert (build_pointer_type (mold_type), source);
6411 /* For CLASS results, allocate the needed memory first. */
6412 if (mold_expr->ts.type == BT_CLASS)
6414 tree cdata;
6415 cdata = gfc_class_data_get (tmpdecl);
6416 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
6417 gfc_add_modify (&se->pre, cdata, tmp);
6420 /* Use memcpy to do the transfer. */
6421 if (mold_expr->ts.type == BT_CLASS)
6422 tmp = gfc_class_data_get (tmpdecl);
6423 else
6424 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
6426 tmp = build_call_expr_loc (input_location,
6427 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
6428 fold_convert (pvoid_type_node, tmp),
6429 fold_convert (pvoid_type_node, ptr),
6430 fold_convert (size_type_node, extent));
6431 gfc_add_expr_to_block (&se->pre, tmp);
6433 /* For CLASS results, set the _vptr. */
6434 if (mold_expr->ts.type == BT_CLASS)
6436 tree vptr;
6437 gfc_symbol *vtab;
6438 vptr = gfc_class_vptr_get (tmpdecl);
6439 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
6440 gcc_assert (vtab);
6441 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
6442 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
6445 se->expr = tmpdecl;
6450 /* Generate code for the ALLOCATED intrinsic.
6451 Generate inline code that directly check the address of the argument. */
6453 static void
6454 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
6456 gfc_actual_arglist *arg1;
6457 gfc_se arg1se;
6458 tree tmp;
6460 gfc_init_se (&arg1se, NULL);
6461 arg1 = expr->value.function.actual;
6463 if (arg1->expr->ts.type == BT_CLASS)
6465 /* Make sure that class array expressions have both a _data
6466 component reference and an array reference.... */
6467 if (CLASS_DATA (arg1->expr)->attr.dimension)
6468 gfc_add_class_array_ref (arg1->expr);
6469 /* .... whilst scalars only need the _data component. */
6470 else
6471 gfc_add_data_component (arg1->expr);
6474 if (arg1->expr->rank == 0)
6476 /* Allocatable scalar. */
6477 arg1se.want_pointer = 1;
6478 gfc_conv_expr (&arg1se, arg1->expr);
6479 tmp = arg1se.expr;
6481 else
6483 /* Allocatable array. */
6484 arg1se.descriptor_only = 1;
6485 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
6486 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
6489 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
6490 fold_convert (TREE_TYPE (tmp), null_pointer_node));
6491 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
6495 /* Generate code for the ASSOCIATED intrinsic.
6496 If both POINTER and TARGET are arrays, generate a call to library function
6497 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
6498 In other cases, generate inline code that directly compare the address of
6499 POINTER with the address of TARGET. */
6501 static void
6502 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
6504 gfc_actual_arglist *arg1;
6505 gfc_actual_arglist *arg2;
6506 gfc_se arg1se;
6507 gfc_se arg2se;
6508 tree tmp2;
6509 tree tmp;
6510 tree nonzero_charlen;
6511 tree nonzero_arraylen;
6512 gfc_ss *ss;
6513 bool scalar;
6515 gfc_init_se (&arg1se, NULL);
6516 gfc_init_se (&arg2se, NULL);
6517 arg1 = expr->value.function.actual;
6518 arg2 = arg1->next;
6520 /* Check whether the expression is a scalar or not; we cannot use
6521 arg1->expr->rank as it can be nonzero for proc pointers. */
6522 ss = gfc_walk_expr (arg1->expr);
6523 scalar = ss == gfc_ss_terminator;
6524 if (!scalar)
6525 gfc_free_ss_chain (ss);
6527 if (!arg2->expr)
6529 /* No optional target. */
6530 if (scalar)
6532 /* A pointer to a scalar. */
6533 arg1se.want_pointer = 1;
6534 gfc_conv_expr (&arg1se, arg1->expr);
6535 if (arg1->expr->symtree->n.sym->attr.proc_pointer
6536 && arg1->expr->symtree->n.sym->attr.dummy)
6537 arg1se.expr = build_fold_indirect_ref_loc (input_location,
6538 arg1se.expr);
6539 if (arg1->expr->ts.type == BT_CLASS)
6540 tmp2 = gfc_class_data_get (arg1se.expr);
6541 else
6542 tmp2 = arg1se.expr;
6544 else
6546 /* A pointer to an array. */
6547 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
6548 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
6550 gfc_add_block_to_block (&se->pre, &arg1se.pre);
6551 gfc_add_block_to_block (&se->post, &arg1se.post);
6552 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp2,
6553 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
6554 se->expr = tmp;
6556 else
6558 /* An optional target. */
6559 if (arg2->expr->ts.type == BT_CLASS)
6560 gfc_add_data_component (arg2->expr);
6562 nonzero_charlen = NULL_TREE;
6563 if (arg1->expr->ts.type == BT_CHARACTER)
6564 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
6565 boolean_type_node,
6566 arg1->expr->ts.u.cl->backend_decl,
6567 integer_zero_node);
6568 if (scalar)
6570 /* A pointer to a scalar. */
6571 arg1se.want_pointer = 1;
6572 gfc_conv_expr (&arg1se, arg1->expr);
6573 if (arg1->expr->symtree->n.sym->attr.proc_pointer
6574 && arg1->expr->symtree->n.sym->attr.dummy)
6575 arg1se.expr = build_fold_indirect_ref_loc (input_location,
6576 arg1se.expr);
6577 if (arg1->expr->ts.type == BT_CLASS)
6578 arg1se.expr = gfc_class_data_get (arg1se.expr);
6580 arg2se.want_pointer = 1;
6581 gfc_conv_expr (&arg2se, arg2->expr);
6582 if (arg2->expr->symtree->n.sym->attr.proc_pointer
6583 && arg2->expr->symtree->n.sym->attr.dummy)
6584 arg2se.expr = build_fold_indirect_ref_loc (input_location,
6585 arg2se.expr);
6586 gfc_add_block_to_block (&se->pre, &arg1se.pre);
6587 gfc_add_block_to_block (&se->post, &arg1se.post);
6588 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
6589 arg1se.expr, arg2se.expr);
6590 tmp2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6591 arg1se.expr, null_pointer_node);
6592 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6593 boolean_type_node, tmp, tmp2);
6595 else
6597 /* An array pointer of zero length is not associated if target is
6598 present. */
6599 arg1se.descriptor_only = 1;
6600 gfc_conv_expr_lhs (&arg1se, arg1->expr);
6601 if (arg1->expr->rank == -1)
6603 tmp = gfc_conv_descriptor_rank (arg1se.expr);
6604 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6605 TREE_TYPE (tmp), tmp, gfc_index_one_node);
6607 else
6608 tmp = gfc_rank_cst[arg1->expr->rank - 1];
6609 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
6610 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
6611 boolean_type_node, tmp,
6612 build_int_cst (TREE_TYPE (tmp), 0));
6614 /* A pointer to an array, call library function _gfor_associated. */
6615 arg1se.want_pointer = 1;
6616 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
6618 arg2se.want_pointer = 1;
6619 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
6620 gfc_add_block_to_block (&se->pre, &arg2se.pre);
6621 gfc_add_block_to_block (&se->post, &arg2se.post);
6622 se->expr = build_call_expr_loc (input_location,
6623 gfor_fndecl_associated, 2,
6624 arg1se.expr, arg2se.expr);
6625 se->expr = convert (boolean_type_node, se->expr);
6626 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6627 boolean_type_node, se->expr,
6628 nonzero_arraylen);
6631 /* If target is present zero character length pointers cannot
6632 be associated. */
6633 if (nonzero_charlen != NULL_TREE)
6634 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6635 boolean_type_node,
6636 se->expr, nonzero_charlen);
6639 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6643 /* Generate code for the SAME_TYPE_AS intrinsic.
6644 Generate inline code that directly checks the vindices. */
6646 static void
6647 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
6649 gfc_expr *a, *b;
6650 gfc_se se1, se2;
6651 tree tmp;
6652 tree conda = NULL_TREE, condb = NULL_TREE;
6654 gfc_init_se (&se1, NULL);
6655 gfc_init_se (&se2, NULL);
6657 a = expr->value.function.actual->expr;
6658 b = expr->value.function.actual->next->expr;
6660 if (UNLIMITED_POLY (a))
6662 tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
6663 conda = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6664 tmp, build_int_cst (TREE_TYPE (tmp), 0));
6667 if (UNLIMITED_POLY (b))
6669 tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
6670 condb = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6671 tmp, build_int_cst (TREE_TYPE (tmp), 0));
6674 if (a->ts.type == BT_CLASS)
6676 gfc_add_vptr_component (a);
6677 gfc_add_hash_component (a);
6679 else if (a->ts.type == BT_DERIVED)
6680 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
6681 a->ts.u.derived->hash_value);
6683 if (b->ts.type == BT_CLASS)
6685 gfc_add_vptr_component (b);
6686 gfc_add_hash_component (b);
6688 else if (b->ts.type == BT_DERIVED)
6689 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
6690 b->ts.u.derived->hash_value);
6692 gfc_conv_expr (&se1, a);
6693 gfc_conv_expr (&se2, b);
6695 tmp = fold_build2_loc (input_location, EQ_EXPR,
6696 boolean_type_node, se1.expr,
6697 fold_convert (TREE_TYPE (se1.expr), se2.expr));
6699 if (conda)
6700 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
6701 boolean_type_node, conda, tmp);
6703 if (condb)
6704 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
6705 boolean_type_node, condb, tmp);
6707 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
6711 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
6713 static void
6714 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
6716 tree args[2];
6718 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6719 se->expr = build_call_expr_loc (input_location,
6720 gfor_fndecl_sc_kind, 2, args[0], args[1]);
6721 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6725 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
6727 static void
6728 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
6730 tree arg, type;
6732 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6734 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
6735 type = gfc_get_int_type (4);
6736 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
6738 /* Convert it to the required type. */
6739 type = gfc_typenode_for_spec (&expr->ts);
6740 se->expr = build_call_expr_loc (input_location,
6741 gfor_fndecl_si_kind, 1, arg);
6742 se->expr = fold_convert (type, se->expr);
6746 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
6748 static void
6749 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
6751 gfc_actual_arglist *actual;
6752 tree type;
6753 gfc_se argse;
6754 vec<tree, va_gc> *args = NULL;
6756 for (actual = expr->value.function.actual; actual; actual = actual->next)
6758 gfc_init_se (&argse, se);
6760 /* Pass a NULL pointer for an absent arg. */
6761 if (actual->expr == NULL)
6762 argse.expr = null_pointer_node;
6763 else
6765 gfc_typespec ts;
6766 gfc_clear_ts (&ts);
6768 if (actual->expr->ts.kind != gfc_c_int_kind)
6770 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
6771 ts.type = BT_INTEGER;
6772 ts.kind = gfc_c_int_kind;
6773 gfc_convert_type (actual->expr, &ts, 2);
6775 gfc_conv_expr_reference (&argse, actual->expr);
6778 gfc_add_block_to_block (&se->pre, &argse.pre);
6779 gfc_add_block_to_block (&se->post, &argse.post);
6780 vec_safe_push (args, argse.expr);
6783 /* Convert it to the required type. */
6784 type = gfc_typenode_for_spec (&expr->ts);
6785 se->expr = build_call_expr_loc_vec (input_location,
6786 gfor_fndecl_sr_kind, args);
6787 se->expr = fold_convert (type, se->expr);
6791 /* Generate code for TRIM (A) intrinsic function. */
6793 static void
6794 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
6796 tree var;
6797 tree len;
6798 tree addr;
6799 tree tmp;
6800 tree cond;
6801 tree fndecl;
6802 tree function;
6803 tree *args;
6804 unsigned int num_args;
6806 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
6807 args = XALLOCAVEC (tree, num_args);
6809 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
6810 addr = gfc_build_addr_expr (ppvoid_type_node, var);
6811 len = gfc_create_var (gfc_charlen_type_node, "len");
6813 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
6814 args[0] = gfc_build_addr_expr (NULL_TREE, len);
6815 args[1] = addr;
6817 if (expr->ts.kind == 1)
6818 function = gfor_fndecl_string_trim;
6819 else if (expr->ts.kind == 4)
6820 function = gfor_fndecl_string_trim_char4;
6821 else
6822 gcc_unreachable ();
6824 fndecl = build_addr (function, current_function_decl);
6825 tmp = build_call_array_loc (input_location,
6826 TREE_TYPE (TREE_TYPE (function)), fndecl,
6827 num_args, args);
6828 gfc_add_expr_to_block (&se->pre, tmp);
6830 /* Free the temporary afterwards, if necessary. */
6831 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6832 len, build_int_cst (TREE_TYPE (len), 0));
6833 tmp = gfc_call_free (var);
6834 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
6835 gfc_add_expr_to_block (&se->post, tmp);
6837 se->expr = var;
6838 se->string_length = len;
6842 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
6844 static void
6845 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
6847 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
6848 tree type, cond, tmp, count, exit_label, n, max, largest;
6849 tree size;
6850 stmtblock_t block, body;
6851 int i;
6853 /* We store in charsize the size of a character. */
6854 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
6855 size = build_int_cst (size_type_node, gfc_character_kinds[i].bit_size / 8);
6857 /* Get the arguments. */
6858 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6859 slen = fold_convert (size_type_node, gfc_evaluate_now (args[0], &se->pre));
6860 src = args[1];
6861 ncopies = gfc_evaluate_now (args[2], &se->pre);
6862 ncopies_type = TREE_TYPE (ncopies);
6864 /* Check that NCOPIES is not negative. */
6865 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, ncopies,
6866 build_int_cst (ncopies_type, 0));
6867 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
6868 "Argument NCOPIES of REPEAT intrinsic is negative "
6869 "(its value is %ld)",
6870 fold_convert (long_integer_type_node, ncopies));
6872 /* If the source length is zero, any non negative value of NCOPIES
6873 is valid, and nothing happens. */
6874 n = gfc_create_var (ncopies_type, "ncopies");
6875 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
6876 build_int_cst (size_type_node, 0));
6877 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
6878 build_int_cst (ncopies_type, 0), ncopies);
6879 gfc_add_modify (&se->pre, n, tmp);
6880 ncopies = n;
6882 /* Check that ncopies is not too large: ncopies should be less than
6883 (or equal to) MAX / slen, where MAX is the maximal integer of
6884 the gfc_charlen_type_node type. If slen == 0, we need a special
6885 case to avoid the division by zero. */
6886 i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
6887 max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_charlen_int_kind);
6888 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node,
6889 fold_convert (size_type_node, max), slen);
6890 largest = TYPE_PRECISION (size_type_node) > TYPE_PRECISION (ncopies_type)
6891 ? size_type_node : ncopies_type;
6892 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6893 fold_convert (largest, ncopies),
6894 fold_convert (largest, max));
6895 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
6896 build_int_cst (size_type_node, 0));
6897 cond = fold_build3_loc (input_location, COND_EXPR, boolean_type_node, tmp,
6898 boolean_false_node, cond);
6899 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
6900 "Argument NCOPIES of REPEAT intrinsic is too large");
6902 /* Compute the destination length. */
6903 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6904 fold_convert (gfc_charlen_type_node, slen),
6905 fold_convert (gfc_charlen_type_node, ncopies));
6906 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
6907 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
6909 /* Generate the code to do the repeat operation:
6910 for (i = 0; i < ncopies; i++)
6911 memmove (dest + (i * slen * size), src, slen*size); */
6912 gfc_start_block (&block);
6913 count = gfc_create_var (ncopies_type, "count");
6914 gfc_add_modify (&block, count, build_int_cst (ncopies_type, 0));
6915 exit_label = gfc_build_label_decl (NULL_TREE);
6917 /* Start the loop body. */
6918 gfc_start_block (&body);
6920 /* Exit the loop if count >= ncopies. */
6921 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, count,
6922 ncopies);
6923 tmp = build1_v (GOTO_EXPR, exit_label);
6924 TREE_USED (exit_label) = 1;
6925 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
6926 build_empty_stmt (input_location));
6927 gfc_add_expr_to_block (&body, tmp);
6929 /* Call memmove (dest + (i*slen*size), src, slen*size). */
6930 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6931 fold_convert (gfc_charlen_type_node, slen),
6932 fold_convert (gfc_charlen_type_node, count));
6933 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6934 tmp, fold_convert (gfc_charlen_type_node, size));
6935 tmp = fold_build_pointer_plus_loc (input_location,
6936 fold_convert (pvoid_type_node, dest), tmp);
6937 tmp = build_call_expr_loc (input_location,
6938 builtin_decl_explicit (BUILT_IN_MEMMOVE),
6939 3, tmp, src,
6940 fold_build2_loc (input_location, MULT_EXPR,
6941 size_type_node, slen,
6942 fold_convert (size_type_node,
6943 size)));
6944 gfc_add_expr_to_block (&body, tmp);
6946 /* Increment count. */
6947 tmp = fold_build2_loc (input_location, PLUS_EXPR, ncopies_type,
6948 count, build_int_cst (TREE_TYPE (count), 1));
6949 gfc_add_modify (&body, count, tmp);
6951 /* Build the loop. */
6952 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
6953 gfc_add_expr_to_block (&block, tmp);
6955 /* Add the exit label. */
6956 tmp = build1_v (LABEL_EXPR, exit_label);
6957 gfc_add_expr_to_block (&block, tmp);
6959 /* Finish the block. */
6960 tmp = gfc_finish_block (&block);
6961 gfc_add_expr_to_block (&se->pre, tmp);
6963 /* Set the result value. */
6964 se->expr = dest;
6965 se->string_length = dlen;
6969 /* Generate code for the IARGC intrinsic. */
6971 static void
6972 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
6974 tree tmp;
6975 tree fndecl;
6976 tree type;
6978 /* Call the library function. This always returns an INTEGER(4). */
6979 fndecl = gfor_fndecl_iargc;
6980 tmp = build_call_expr_loc (input_location,
6981 fndecl, 0);
6983 /* Convert it to the required type. */
6984 type = gfc_typenode_for_spec (&expr->ts);
6985 tmp = fold_convert (type, tmp);
6987 se->expr = tmp;
6991 /* The loc intrinsic returns the address of its argument as
6992 gfc_index_integer_kind integer. */
6994 static void
6995 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
6997 tree temp_var;
6998 gfc_expr *arg_expr;
7000 gcc_assert (!se->ss);
7002 arg_expr = expr->value.function.actual->expr;
7003 if (arg_expr->rank == 0)
7004 gfc_conv_expr_reference (se, arg_expr);
7005 else
7006 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
7007 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
7009 /* Create a temporary variable for loc return value. Without this,
7010 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
7011 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
7012 gfc_add_modify (&se->pre, temp_var, se->expr);
7013 se->expr = temp_var;
7017 /* The following routine generates code for the intrinsic
7018 functions from the ISO_C_BINDING module:
7019 * C_LOC
7020 * C_FUNLOC
7021 * C_ASSOCIATED */
7023 static void
7024 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
7026 gfc_actual_arglist *arg = expr->value.function.actual;
7028 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
7030 if (arg->expr->rank == 0)
7031 gfc_conv_expr_reference (se, arg->expr);
7032 else if (gfc_is_simply_contiguous (arg->expr, false))
7033 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
7034 else
7036 gfc_conv_expr_descriptor (se, arg->expr);
7037 se->expr = gfc_conv_descriptor_data_get (se->expr);
7040 /* TODO -- the following two lines shouldn't be necessary, but if
7041 they're removed, a bug is exposed later in the code path.
7042 This workaround was thus introduced, but will have to be
7043 removed; please see PR 35150 for details about the issue. */
7044 se->expr = convert (pvoid_type_node, se->expr);
7045 se->expr = gfc_evaluate_now (se->expr, &se->pre);
7047 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
7048 gfc_conv_expr_reference (se, arg->expr);
7049 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
7051 gfc_se arg1se;
7052 gfc_se arg2se;
7054 /* Build the addr_expr for the first argument. The argument is
7055 already an *address* so we don't need to set want_pointer in
7056 the gfc_se. */
7057 gfc_init_se (&arg1se, NULL);
7058 gfc_conv_expr (&arg1se, arg->expr);
7059 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7060 gfc_add_block_to_block (&se->post, &arg1se.post);
7062 /* See if we were given two arguments. */
7063 if (arg->next->expr == NULL)
7064 /* Only given one arg so generate a null and do a
7065 not-equal comparison against the first arg. */
7066 se->expr = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7067 arg1se.expr,
7068 fold_convert (TREE_TYPE (arg1se.expr),
7069 null_pointer_node));
7070 else
7072 tree eq_expr;
7073 tree not_null_expr;
7075 /* Given two arguments so build the arg2se from second arg. */
7076 gfc_init_se (&arg2se, NULL);
7077 gfc_conv_expr (&arg2se, arg->next->expr);
7078 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7079 gfc_add_block_to_block (&se->post, &arg2se.post);
7081 /* Generate test to compare that the two args are equal. */
7082 eq_expr = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
7083 arg1se.expr, arg2se.expr);
7084 /* Generate test to ensure that the first arg is not null. */
7085 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
7086 boolean_type_node,
7087 arg1se.expr, null_pointer_node);
7089 /* Finally, the generated test must check that both arg1 is not
7090 NULL and that it is equal to the second arg. */
7091 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7092 boolean_type_node,
7093 not_null_expr, eq_expr);
7096 else
7097 gcc_unreachable ();
7101 /* The following routine generates code for the intrinsic
7102 subroutines from the ISO_C_BINDING module:
7103 * C_F_POINTER
7104 * C_F_PROCPOINTER. */
7106 static tree
7107 conv_isocbinding_subroutine (gfc_code *code)
7109 gfc_se se;
7110 gfc_se cptrse;
7111 gfc_se fptrse;
7112 gfc_se shapese;
7113 gfc_ss *shape_ss;
7114 tree desc, dim, tmp, stride, offset;
7115 stmtblock_t body, block;
7116 gfc_loopinfo loop;
7117 gfc_actual_arglist *arg = code->ext.actual;
7119 gfc_init_se (&se, NULL);
7120 gfc_init_se (&cptrse, NULL);
7121 gfc_conv_expr (&cptrse, arg->expr);
7122 gfc_add_block_to_block (&se.pre, &cptrse.pre);
7123 gfc_add_block_to_block (&se.post, &cptrse.post);
7125 gfc_init_se (&fptrse, NULL);
7126 if (arg->next->expr->rank == 0)
7128 fptrse.want_pointer = 1;
7129 gfc_conv_expr (&fptrse, arg->next->expr);
7130 gfc_add_block_to_block (&se.pre, &fptrse.pre);
7131 gfc_add_block_to_block (&se.post, &fptrse.post);
7132 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
7133 && arg->next->expr->symtree->n.sym->attr.dummy)
7134 fptrse.expr = build_fold_indirect_ref_loc (input_location,
7135 fptrse.expr);
7136 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
7137 TREE_TYPE (fptrse.expr),
7138 fptrse.expr,
7139 fold_convert (TREE_TYPE (fptrse.expr),
7140 cptrse.expr));
7141 gfc_add_expr_to_block (&se.pre, se.expr);
7142 gfc_add_block_to_block (&se.pre, &se.post);
7143 return gfc_finish_block (&se.pre);
7146 gfc_start_block (&block);
7148 /* Get the descriptor of the Fortran pointer. */
7149 fptrse.descriptor_only = 1;
7150 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
7151 gfc_add_block_to_block (&block, &fptrse.pre);
7152 desc = fptrse.expr;
7154 /* Set data value, dtype, and offset. */
7155 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
7156 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
7157 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
7158 gfc_get_dtype (TREE_TYPE (desc)));
7160 /* Start scalarization of the bounds, using the shape argument. */
7162 shape_ss = gfc_walk_expr (arg->next->next->expr);
7163 gcc_assert (shape_ss != gfc_ss_terminator);
7164 gfc_init_se (&shapese, NULL);
7166 gfc_init_loopinfo (&loop);
7167 gfc_add_ss_to_loop (&loop, shape_ss);
7168 gfc_conv_ss_startstride (&loop);
7169 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
7170 gfc_mark_ss_chain_used (shape_ss, 1);
7172 gfc_copy_loopinfo_to_se (&shapese, &loop);
7173 shapese.ss = shape_ss;
7175 stride = gfc_create_var (gfc_array_index_type, "stride");
7176 offset = gfc_create_var (gfc_array_index_type, "offset");
7177 gfc_add_modify (&block, stride, gfc_index_one_node);
7178 gfc_add_modify (&block, offset, gfc_index_zero_node);
7180 /* Loop body. */
7181 gfc_start_scalarized_body (&loop, &body);
7183 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7184 loop.loopvar[0], loop.from[0]);
7186 /* Set bounds and stride. */
7187 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
7188 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
7190 gfc_conv_expr (&shapese, arg->next->next->expr);
7191 gfc_add_block_to_block (&body, &shapese.pre);
7192 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
7193 gfc_add_block_to_block (&body, &shapese.post);
7195 /* Calculate offset. */
7196 gfc_add_modify (&body, offset,
7197 fold_build2_loc (input_location, PLUS_EXPR,
7198 gfc_array_index_type, offset, stride));
7199 /* Update stride. */
7200 gfc_add_modify (&body, stride,
7201 fold_build2_loc (input_location, MULT_EXPR,
7202 gfc_array_index_type, stride,
7203 fold_convert (gfc_array_index_type,
7204 shapese.expr)));
7205 /* Finish scalarization loop. */
7206 gfc_trans_scalarizing_loops (&loop, &body);
7207 gfc_add_block_to_block (&block, &loop.pre);
7208 gfc_add_block_to_block (&block, &loop.post);
7209 gfc_add_block_to_block (&block, &fptrse.post);
7210 gfc_cleanup_loop (&loop);
7212 gfc_add_modify (&block, offset,
7213 fold_build1_loc (input_location, NEGATE_EXPR,
7214 gfc_array_index_type, offset));
7215 gfc_conv_descriptor_offset_set (&block, desc, offset);
7217 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
7218 gfc_add_block_to_block (&se.pre, &se.post);
7219 return gfc_finish_block (&se.pre);
7223 /* Save and restore floating-point state. */
7225 tree
7226 gfc_save_fp_state (stmtblock_t *block)
7228 tree type, fpstate, tmp;
7230 type = build_array_type (char_type_node,
7231 build_range_type (size_type_node, size_zero_node,
7232 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
7233 fpstate = gfc_create_var (type, "fpstate");
7234 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
7236 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
7237 1, fpstate);
7238 gfc_add_expr_to_block (block, tmp);
7240 return fpstate;
7244 void
7245 gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
7247 tree tmp;
7249 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
7250 1, fpstate);
7251 gfc_add_expr_to_block (block, tmp);
7255 /* Generate code for arguments of IEEE functions. */
7257 static void
7258 conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
7259 int nargs)
7261 gfc_actual_arglist *actual;
7262 gfc_expr *e;
7263 gfc_se argse;
7264 int arg;
7266 actual = expr->value.function.actual;
7267 for (arg = 0; arg < nargs; arg++, actual = actual->next)
7269 gcc_assert (actual);
7270 e = actual->expr;
7272 gfc_init_se (&argse, se);
7273 gfc_conv_expr_val (&argse, e);
7275 gfc_add_block_to_block (&se->pre, &argse.pre);
7276 gfc_add_block_to_block (&se->post, &argse.post);
7277 argarray[arg] = argse.expr;
7282 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
7283 and IEEE_UNORDERED, which translate directly to GCC type-generic
7284 built-ins. */
7286 static void
7287 conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
7288 enum built_in_function code, int nargs)
7290 tree args[2];
7291 gcc_assert ((unsigned) nargs <= sizeof(args)/sizeof(args[0]));
7293 conv_ieee_function_args (se, expr, args, nargs);
7294 se->expr = build_call_expr_loc_array (input_location,
7295 builtin_decl_explicit (code),
7296 nargs, args);
7297 STRIP_TYPE_NOPS (se->expr);
7298 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7302 /* Generate code for IEEE_IS_NORMAL intrinsic:
7303 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
7305 static void
7306 conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
7308 tree arg, isnormal, iszero;
7310 /* Convert arg, evaluate it only once. */
7311 conv_ieee_function_args (se, expr, &arg, 1);
7312 arg = gfc_evaluate_now (arg, &se->pre);
7314 isnormal = build_call_expr_loc (input_location,
7315 builtin_decl_explicit (BUILT_IN_ISNORMAL),
7316 1, arg);
7317 iszero = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
7318 build_real_from_int_cst (TREE_TYPE (arg),
7319 integer_zero_node));
7320 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
7321 boolean_type_node, isnormal, iszero);
7322 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7326 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
7327 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
7329 static void
7330 conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
7332 tree arg, signbit, isnan, decl;
7333 int argprec;
7335 /* Convert arg, evaluate it only once. */
7336 conv_ieee_function_args (se, expr, &arg, 1);
7337 arg = gfc_evaluate_now (arg, &se->pre);
7339 isnan = build_call_expr_loc (input_location,
7340 builtin_decl_explicit (BUILT_IN_ISNAN),
7341 1, arg);
7342 STRIP_TYPE_NOPS (isnan);
7344 argprec = TYPE_PRECISION (TREE_TYPE (arg));
7345 decl = builtin_decl_for_precision (BUILT_IN_SIGNBIT, argprec);
7346 signbit = build_call_expr_loc (input_location, decl, 1, arg);
7347 signbit = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7348 signbit, integer_zero_node);
7350 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7351 boolean_type_node, signbit,
7352 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
7353 TREE_TYPE(isnan), isnan));
7355 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7359 /* Generate code for IEEE_LOGB and IEEE_RINT. */
7361 static void
7362 conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
7363 enum built_in_function code)
7365 tree arg, decl, call, fpstate;
7366 int argprec;
7368 conv_ieee_function_args (se, expr, &arg, 1);
7369 argprec = TYPE_PRECISION (TREE_TYPE (arg));
7370 decl = builtin_decl_for_precision (code, argprec);
7372 /* Save floating-point state. */
7373 fpstate = gfc_save_fp_state (&se->pre);
7375 /* Make the function call. */
7376 call = build_call_expr_loc (input_location, decl, 1, arg);
7377 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
7379 /* Restore floating-point state. */
7380 gfc_restore_fp_state (&se->post, fpstate);
7384 /* Generate code for IEEE_REM. */
7386 static void
7387 conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
7389 tree args[2], decl, call, fpstate;
7390 int argprec;
7392 conv_ieee_function_args (se, expr, args, 2);
7394 /* If arguments have unequal size, convert them to the larger. */
7395 if (TYPE_PRECISION (TREE_TYPE (args[0]))
7396 > TYPE_PRECISION (TREE_TYPE (args[1])))
7397 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
7398 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
7399 > TYPE_PRECISION (TREE_TYPE (args[0])))
7400 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
7402 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
7403 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
7405 /* Save floating-point state. */
7406 fpstate = gfc_save_fp_state (&se->pre);
7408 /* Make the function call. */
7409 call = build_call_expr_loc_array (input_location, decl, 2, args);
7410 se->expr = fold_convert (TREE_TYPE (args[0]), call);
7412 /* Restore floating-point state. */
7413 gfc_restore_fp_state (&se->post, fpstate);
7417 /* Generate code for IEEE_NEXT_AFTER. */
7419 static void
7420 conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
7422 tree args[2], decl, call, fpstate;
7423 int argprec;
7425 conv_ieee_function_args (se, expr, args, 2);
7427 /* Result has the characteristics of first argument. */
7428 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
7429 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
7430 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
7432 /* Save floating-point state. */
7433 fpstate = gfc_save_fp_state (&se->pre);
7435 /* Make the function call. */
7436 call = build_call_expr_loc_array (input_location, decl, 2, args);
7437 se->expr = fold_convert (TREE_TYPE (args[0]), call);
7439 /* Restore floating-point state. */
7440 gfc_restore_fp_state (&se->post, fpstate);
7444 /* Generate code for IEEE_SCALB. */
7446 static void
7447 conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
7449 tree args[2], decl, call, huge, type;
7450 int argprec, n;
7452 conv_ieee_function_args (se, expr, args, 2);
7454 /* Result has the characteristics of first argument. */
7455 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
7456 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
7458 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
7460 /* We need to fold the integer into the range of a C int. */
7461 args[1] = gfc_evaluate_now (args[1], &se->pre);
7462 type = TREE_TYPE (args[1]);
7464 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
7465 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
7466 gfc_c_int_kind);
7467 huge = fold_convert (type, huge);
7468 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
7469 huge);
7470 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
7471 fold_build1_loc (input_location, NEGATE_EXPR,
7472 type, huge));
7475 args[1] = fold_convert (integer_type_node, args[1]);
7477 /* Make the function call. */
7478 call = build_call_expr_loc_array (input_location, decl, 2, args);
7479 se->expr = fold_convert (TREE_TYPE (args[0]), call);
7483 /* Generate code for IEEE_COPY_SIGN. */
7485 static void
7486 conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
7488 tree args[2], decl, sign;
7489 int argprec;
7491 conv_ieee_function_args (se, expr, args, 2);
7493 /* Get the sign of the second argument. */
7494 argprec = TYPE_PRECISION (TREE_TYPE (args[1]));
7495 decl = builtin_decl_for_precision (BUILT_IN_SIGNBIT, argprec);
7496 sign = build_call_expr_loc (input_location, decl, 1, args[1]);
7497 sign = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7498 sign, integer_zero_node);
7500 /* Create a value of one, with the right sign. */
7501 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
7502 sign,
7503 fold_build1_loc (input_location, NEGATE_EXPR,
7504 integer_type_node,
7505 integer_one_node),
7506 integer_one_node);
7507 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
7509 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
7510 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
7512 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
7516 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
7517 module. */
7519 bool
7520 gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
7522 const char *name = expr->value.function.name;
7524 #define STARTS_WITH(A,B) (strncmp((A), (B), strlen(B)) == 0)
7526 if (STARTS_WITH (name, "_gfortran_ieee_is_nan"))
7527 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
7528 else if (STARTS_WITH (name, "_gfortran_ieee_is_finite"))
7529 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
7530 else if (STARTS_WITH (name, "_gfortran_ieee_unordered"))
7531 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
7532 else if (STARTS_WITH (name, "_gfortran_ieee_is_normal"))
7533 conv_intrinsic_ieee_is_normal (se, expr);
7534 else if (STARTS_WITH (name, "_gfortran_ieee_is_negative"))
7535 conv_intrinsic_ieee_is_negative (se, expr);
7536 else if (STARTS_WITH (name, "_gfortran_ieee_copy_sign"))
7537 conv_intrinsic_ieee_copy_sign (se, expr);
7538 else if (STARTS_WITH (name, "_gfortran_ieee_scalb"))
7539 conv_intrinsic_ieee_scalb (se, expr);
7540 else if (STARTS_WITH (name, "_gfortran_ieee_next_after"))
7541 conv_intrinsic_ieee_next_after (se, expr);
7542 else if (STARTS_WITH (name, "_gfortran_ieee_rem"))
7543 conv_intrinsic_ieee_rem (se, expr);
7544 else if (STARTS_WITH (name, "_gfortran_ieee_logb"))
7545 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
7546 else if (STARTS_WITH (name, "_gfortran_ieee_rint"))
7547 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
7548 else
7549 /* It is not among the functions we translate directly. We return
7550 false, so a library function call is emitted. */
7551 return false;
7553 #undef STARTS_WITH
7555 return true;
7559 /* Generate code for an intrinsic function. Some map directly to library
7560 calls, others get special handling. In some cases the name of the function
7561 used depends on the type specifiers. */
7563 void
7564 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
7566 const char *name;
7567 int lib, kind;
7568 tree fndecl;
7570 name = &expr->value.function.name[2];
7572 if (expr->rank > 0)
7574 lib = gfc_is_intrinsic_libcall (expr);
7575 if (lib != 0)
7577 if (lib == 1)
7578 se->ignore_optional = 1;
7580 switch (expr->value.function.isym->id)
7582 case GFC_ISYM_EOSHIFT:
7583 case GFC_ISYM_PACK:
7584 case GFC_ISYM_RESHAPE:
7585 /* For all of those the first argument specifies the type and the
7586 third is optional. */
7587 conv_generic_with_optional_char_arg (se, expr, 1, 3);
7588 break;
7590 default:
7591 gfc_conv_intrinsic_funcall (se, expr);
7592 break;
7595 return;
7599 switch (expr->value.function.isym->id)
7601 case GFC_ISYM_NONE:
7602 gcc_unreachable ();
7604 case GFC_ISYM_REPEAT:
7605 gfc_conv_intrinsic_repeat (se, expr);
7606 break;
7608 case GFC_ISYM_TRIM:
7609 gfc_conv_intrinsic_trim (se, expr);
7610 break;
7612 case GFC_ISYM_SC_KIND:
7613 gfc_conv_intrinsic_sc_kind (se, expr);
7614 break;
7616 case GFC_ISYM_SI_KIND:
7617 gfc_conv_intrinsic_si_kind (se, expr);
7618 break;
7620 case GFC_ISYM_SR_KIND:
7621 gfc_conv_intrinsic_sr_kind (se, expr);
7622 break;
7624 case GFC_ISYM_EXPONENT:
7625 gfc_conv_intrinsic_exponent (se, expr);
7626 break;
7628 case GFC_ISYM_SCAN:
7629 kind = expr->value.function.actual->expr->ts.kind;
7630 if (kind == 1)
7631 fndecl = gfor_fndecl_string_scan;
7632 else if (kind == 4)
7633 fndecl = gfor_fndecl_string_scan_char4;
7634 else
7635 gcc_unreachable ();
7637 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
7638 break;
7640 case GFC_ISYM_VERIFY:
7641 kind = expr->value.function.actual->expr->ts.kind;
7642 if (kind == 1)
7643 fndecl = gfor_fndecl_string_verify;
7644 else if (kind == 4)
7645 fndecl = gfor_fndecl_string_verify_char4;
7646 else
7647 gcc_unreachable ();
7649 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
7650 break;
7652 case GFC_ISYM_ALLOCATED:
7653 gfc_conv_allocated (se, expr);
7654 break;
7656 case GFC_ISYM_ASSOCIATED:
7657 gfc_conv_associated(se, expr);
7658 break;
7660 case GFC_ISYM_SAME_TYPE_AS:
7661 gfc_conv_same_type_as (se, expr);
7662 break;
7664 case GFC_ISYM_ABS:
7665 gfc_conv_intrinsic_abs (se, expr);
7666 break;
7668 case GFC_ISYM_ADJUSTL:
7669 if (expr->ts.kind == 1)
7670 fndecl = gfor_fndecl_adjustl;
7671 else if (expr->ts.kind == 4)
7672 fndecl = gfor_fndecl_adjustl_char4;
7673 else
7674 gcc_unreachable ();
7676 gfc_conv_intrinsic_adjust (se, expr, fndecl);
7677 break;
7679 case GFC_ISYM_ADJUSTR:
7680 if (expr->ts.kind == 1)
7681 fndecl = gfor_fndecl_adjustr;
7682 else if (expr->ts.kind == 4)
7683 fndecl = gfor_fndecl_adjustr_char4;
7684 else
7685 gcc_unreachable ();
7687 gfc_conv_intrinsic_adjust (se, expr, fndecl);
7688 break;
7690 case GFC_ISYM_AIMAG:
7691 gfc_conv_intrinsic_imagpart (se, expr);
7692 break;
7694 case GFC_ISYM_AINT:
7695 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
7696 break;
7698 case GFC_ISYM_ALL:
7699 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
7700 break;
7702 case GFC_ISYM_ANINT:
7703 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
7704 break;
7706 case GFC_ISYM_AND:
7707 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
7708 break;
7710 case GFC_ISYM_ANY:
7711 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
7712 break;
7714 case GFC_ISYM_BTEST:
7715 gfc_conv_intrinsic_btest (se, expr);
7716 break;
7718 case GFC_ISYM_BGE:
7719 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
7720 break;
7722 case GFC_ISYM_BGT:
7723 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
7724 break;
7726 case GFC_ISYM_BLE:
7727 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
7728 break;
7730 case GFC_ISYM_BLT:
7731 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
7732 break;
7734 case GFC_ISYM_C_ASSOCIATED:
7735 case GFC_ISYM_C_FUNLOC:
7736 case GFC_ISYM_C_LOC:
7737 conv_isocbinding_function (se, expr);
7738 break;
7740 case GFC_ISYM_ACHAR:
7741 case GFC_ISYM_CHAR:
7742 gfc_conv_intrinsic_char (se, expr);
7743 break;
7745 case GFC_ISYM_CONVERSION:
7746 case GFC_ISYM_REAL:
7747 case GFC_ISYM_LOGICAL:
7748 case GFC_ISYM_DBLE:
7749 gfc_conv_intrinsic_conversion (se, expr);
7750 break;
7752 /* Integer conversions are handled separately to make sure we get the
7753 correct rounding mode. */
7754 case GFC_ISYM_INT:
7755 case GFC_ISYM_INT2:
7756 case GFC_ISYM_INT8:
7757 case GFC_ISYM_LONG:
7758 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
7759 break;
7761 case GFC_ISYM_NINT:
7762 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
7763 break;
7765 case GFC_ISYM_CEILING:
7766 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
7767 break;
7769 case GFC_ISYM_FLOOR:
7770 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
7771 break;
7773 case GFC_ISYM_MOD:
7774 gfc_conv_intrinsic_mod (se, expr, 0);
7775 break;
7777 case GFC_ISYM_MODULO:
7778 gfc_conv_intrinsic_mod (se, expr, 1);
7779 break;
7781 case GFC_ISYM_CAF_GET:
7782 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE);
7783 break;
7785 case GFC_ISYM_CMPLX:
7786 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
7787 break;
7789 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
7790 gfc_conv_intrinsic_iargc (se, expr);
7791 break;
7793 case GFC_ISYM_COMPLEX:
7794 gfc_conv_intrinsic_cmplx (se, expr, 1);
7795 break;
7797 case GFC_ISYM_CONJG:
7798 gfc_conv_intrinsic_conjg (se, expr);
7799 break;
7801 case GFC_ISYM_COUNT:
7802 gfc_conv_intrinsic_count (se, expr);
7803 break;
7805 case GFC_ISYM_CTIME:
7806 gfc_conv_intrinsic_ctime (se, expr);
7807 break;
7809 case GFC_ISYM_DIM:
7810 gfc_conv_intrinsic_dim (se, expr);
7811 break;
7813 case GFC_ISYM_DOT_PRODUCT:
7814 gfc_conv_intrinsic_dot_product (se, expr);
7815 break;
7817 case GFC_ISYM_DPROD:
7818 gfc_conv_intrinsic_dprod (se, expr);
7819 break;
7821 case GFC_ISYM_DSHIFTL:
7822 gfc_conv_intrinsic_dshift (se, expr, true);
7823 break;
7825 case GFC_ISYM_DSHIFTR:
7826 gfc_conv_intrinsic_dshift (se, expr, false);
7827 break;
7829 case GFC_ISYM_FDATE:
7830 gfc_conv_intrinsic_fdate (se, expr);
7831 break;
7833 case GFC_ISYM_FRACTION:
7834 gfc_conv_intrinsic_fraction (se, expr);
7835 break;
7837 case GFC_ISYM_IALL:
7838 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
7839 break;
7841 case GFC_ISYM_IAND:
7842 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
7843 break;
7845 case GFC_ISYM_IANY:
7846 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
7847 break;
7849 case GFC_ISYM_IBCLR:
7850 gfc_conv_intrinsic_singlebitop (se, expr, 0);
7851 break;
7853 case GFC_ISYM_IBITS:
7854 gfc_conv_intrinsic_ibits (se, expr);
7855 break;
7857 case GFC_ISYM_IBSET:
7858 gfc_conv_intrinsic_singlebitop (se, expr, 1);
7859 break;
7861 case GFC_ISYM_IACHAR:
7862 case GFC_ISYM_ICHAR:
7863 /* We assume ASCII character sequence. */
7864 gfc_conv_intrinsic_ichar (se, expr);
7865 break;
7867 case GFC_ISYM_IARGC:
7868 gfc_conv_intrinsic_iargc (se, expr);
7869 break;
7871 case GFC_ISYM_IEOR:
7872 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
7873 break;
7875 case GFC_ISYM_INDEX:
7876 kind = expr->value.function.actual->expr->ts.kind;
7877 if (kind == 1)
7878 fndecl = gfor_fndecl_string_index;
7879 else if (kind == 4)
7880 fndecl = gfor_fndecl_string_index_char4;
7881 else
7882 gcc_unreachable ();
7884 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
7885 break;
7887 case GFC_ISYM_IOR:
7888 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
7889 break;
7891 case GFC_ISYM_IPARITY:
7892 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
7893 break;
7895 case GFC_ISYM_IS_IOSTAT_END:
7896 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
7897 break;
7899 case GFC_ISYM_IS_IOSTAT_EOR:
7900 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
7901 break;
7903 case GFC_ISYM_ISNAN:
7904 gfc_conv_intrinsic_isnan (se, expr);
7905 break;
7907 case GFC_ISYM_LSHIFT:
7908 gfc_conv_intrinsic_shift (se, expr, false, false);
7909 break;
7911 case GFC_ISYM_RSHIFT:
7912 gfc_conv_intrinsic_shift (se, expr, true, true);
7913 break;
7915 case GFC_ISYM_SHIFTA:
7916 gfc_conv_intrinsic_shift (se, expr, true, true);
7917 break;
7919 case GFC_ISYM_SHIFTL:
7920 gfc_conv_intrinsic_shift (se, expr, false, false);
7921 break;
7923 case GFC_ISYM_SHIFTR:
7924 gfc_conv_intrinsic_shift (se, expr, true, false);
7925 break;
7927 case GFC_ISYM_ISHFT:
7928 gfc_conv_intrinsic_ishft (se, expr);
7929 break;
7931 case GFC_ISYM_ISHFTC:
7932 gfc_conv_intrinsic_ishftc (se, expr);
7933 break;
7935 case GFC_ISYM_LEADZ:
7936 gfc_conv_intrinsic_leadz (se, expr);
7937 break;
7939 case GFC_ISYM_TRAILZ:
7940 gfc_conv_intrinsic_trailz (se, expr);
7941 break;
7943 case GFC_ISYM_POPCNT:
7944 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
7945 break;
7947 case GFC_ISYM_POPPAR:
7948 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
7949 break;
7951 case GFC_ISYM_LBOUND:
7952 gfc_conv_intrinsic_bound (se, expr, 0);
7953 break;
7955 case GFC_ISYM_LCOBOUND:
7956 conv_intrinsic_cobound (se, expr);
7957 break;
7959 case GFC_ISYM_TRANSPOSE:
7960 /* The scalarizer has already been set up for reversed dimension access
7961 order ; now we just get the argument value normally. */
7962 gfc_conv_expr (se, expr->value.function.actual->expr);
7963 break;
7965 case GFC_ISYM_LEN:
7966 gfc_conv_intrinsic_len (se, expr);
7967 break;
7969 case GFC_ISYM_LEN_TRIM:
7970 gfc_conv_intrinsic_len_trim (se, expr);
7971 break;
7973 case GFC_ISYM_LGE:
7974 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
7975 break;
7977 case GFC_ISYM_LGT:
7978 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
7979 break;
7981 case GFC_ISYM_LLE:
7982 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
7983 break;
7985 case GFC_ISYM_LLT:
7986 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
7987 break;
7989 case GFC_ISYM_MASKL:
7990 gfc_conv_intrinsic_mask (se, expr, 1);
7991 break;
7993 case GFC_ISYM_MASKR:
7994 gfc_conv_intrinsic_mask (se, expr, 0);
7995 break;
7997 case GFC_ISYM_MAX:
7998 if (expr->ts.type == BT_CHARACTER)
7999 gfc_conv_intrinsic_minmax_char (se, expr, 1);
8000 else
8001 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
8002 break;
8004 case GFC_ISYM_MAXLOC:
8005 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
8006 break;
8008 case GFC_ISYM_MAXVAL:
8009 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
8010 break;
8012 case GFC_ISYM_MERGE:
8013 gfc_conv_intrinsic_merge (se, expr);
8014 break;
8016 case GFC_ISYM_MERGE_BITS:
8017 gfc_conv_intrinsic_merge_bits (se, expr);
8018 break;
8020 case GFC_ISYM_MIN:
8021 if (expr->ts.type == BT_CHARACTER)
8022 gfc_conv_intrinsic_minmax_char (se, expr, -1);
8023 else
8024 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
8025 break;
8027 case GFC_ISYM_MINLOC:
8028 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
8029 break;
8031 case GFC_ISYM_MINVAL:
8032 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
8033 break;
8035 case GFC_ISYM_NEAREST:
8036 gfc_conv_intrinsic_nearest (se, expr);
8037 break;
8039 case GFC_ISYM_NORM2:
8040 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
8041 break;
8043 case GFC_ISYM_NOT:
8044 gfc_conv_intrinsic_not (se, expr);
8045 break;
8047 case GFC_ISYM_OR:
8048 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
8049 break;
8051 case GFC_ISYM_PARITY:
8052 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
8053 break;
8055 case GFC_ISYM_PRESENT:
8056 gfc_conv_intrinsic_present (se, expr);
8057 break;
8059 case GFC_ISYM_PRODUCT:
8060 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
8061 break;
8063 case GFC_ISYM_RANK:
8064 gfc_conv_intrinsic_rank (se, expr);
8065 break;
8067 case GFC_ISYM_RRSPACING:
8068 gfc_conv_intrinsic_rrspacing (se, expr);
8069 break;
8071 case GFC_ISYM_SET_EXPONENT:
8072 gfc_conv_intrinsic_set_exponent (se, expr);
8073 break;
8075 case GFC_ISYM_SCALE:
8076 gfc_conv_intrinsic_scale (se, expr);
8077 break;
8079 case GFC_ISYM_SIGN:
8080 gfc_conv_intrinsic_sign (se, expr);
8081 break;
8083 case GFC_ISYM_SIZE:
8084 gfc_conv_intrinsic_size (se, expr);
8085 break;
8087 case GFC_ISYM_SIZEOF:
8088 case GFC_ISYM_C_SIZEOF:
8089 gfc_conv_intrinsic_sizeof (se, expr);
8090 break;
8092 case GFC_ISYM_STORAGE_SIZE:
8093 gfc_conv_intrinsic_storage_size (se, expr);
8094 break;
8096 case GFC_ISYM_SPACING:
8097 gfc_conv_intrinsic_spacing (se, expr);
8098 break;
8100 case GFC_ISYM_STRIDE:
8101 conv_intrinsic_stride (se, expr);
8102 break;
8104 case GFC_ISYM_SUM:
8105 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
8106 break;
8108 case GFC_ISYM_TRANSFER:
8109 if (se->ss && se->ss->info->useflags)
8110 /* Access the previously obtained result. */
8111 gfc_conv_tmp_array_ref (se);
8112 else
8113 gfc_conv_intrinsic_transfer (se, expr);
8114 break;
8116 case GFC_ISYM_TTYNAM:
8117 gfc_conv_intrinsic_ttynam (se, expr);
8118 break;
8120 case GFC_ISYM_UBOUND:
8121 gfc_conv_intrinsic_bound (se, expr, 1);
8122 break;
8124 case GFC_ISYM_UCOBOUND:
8125 conv_intrinsic_cobound (se, expr);
8126 break;
8128 case GFC_ISYM_XOR:
8129 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
8130 break;
8132 case GFC_ISYM_LOC:
8133 gfc_conv_intrinsic_loc (se, expr);
8134 break;
8136 case GFC_ISYM_THIS_IMAGE:
8137 /* For num_images() == 1, handle as LCOBOUND. */
8138 if (expr->value.function.actual->expr
8139 && gfc_option.coarray == GFC_FCOARRAY_SINGLE)
8140 conv_intrinsic_cobound (se, expr);
8141 else
8142 trans_this_image (se, expr);
8143 break;
8145 case GFC_ISYM_IMAGE_INDEX:
8146 trans_image_index (se, expr);
8147 break;
8149 case GFC_ISYM_NUM_IMAGES:
8150 trans_num_images (se, expr);
8151 break;
8153 case GFC_ISYM_ACCESS:
8154 case GFC_ISYM_CHDIR:
8155 case GFC_ISYM_CHMOD:
8156 case GFC_ISYM_DTIME:
8157 case GFC_ISYM_ETIME:
8158 case GFC_ISYM_EXTENDS_TYPE_OF:
8159 case GFC_ISYM_FGET:
8160 case GFC_ISYM_FGETC:
8161 case GFC_ISYM_FNUM:
8162 case GFC_ISYM_FPUT:
8163 case GFC_ISYM_FPUTC:
8164 case GFC_ISYM_FSTAT:
8165 case GFC_ISYM_FTELL:
8166 case GFC_ISYM_GETCWD:
8167 case GFC_ISYM_GETGID:
8168 case GFC_ISYM_GETPID:
8169 case GFC_ISYM_GETUID:
8170 case GFC_ISYM_HOSTNM:
8171 case GFC_ISYM_KILL:
8172 case GFC_ISYM_IERRNO:
8173 case GFC_ISYM_IRAND:
8174 case GFC_ISYM_ISATTY:
8175 case GFC_ISYM_JN2:
8176 case GFC_ISYM_LINK:
8177 case GFC_ISYM_LSTAT:
8178 case GFC_ISYM_MALLOC:
8179 case GFC_ISYM_MATMUL:
8180 case GFC_ISYM_MCLOCK:
8181 case GFC_ISYM_MCLOCK8:
8182 case GFC_ISYM_RAND:
8183 case GFC_ISYM_RENAME:
8184 case GFC_ISYM_SECOND:
8185 case GFC_ISYM_SECNDS:
8186 case GFC_ISYM_SIGNAL:
8187 case GFC_ISYM_STAT:
8188 case GFC_ISYM_SYMLNK:
8189 case GFC_ISYM_SYSTEM:
8190 case GFC_ISYM_TIME:
8191 case GFC_ISYM_TIME8:
8192 case GFC_ISYM_UMASK:
8193 case GFC_ISYM_UNLINK:
8194 case GFC_ISYM_YN2:
8195 gfc_conv_intrinsic_funcall (se, expr);
8196 break;
8198 case GFC_ISYM_EOSHIFT:
8199 case GFC_ISYM_PACK:
8200 case GFC_ISYM_RESHAPE:
8201 /* For those, expr->rank should always be >0 and thus the if above the
8202 switch should have matched. */
8203 gcc_unreachable ();
8204 break;
8206 default:
8207 gfc_conv_intrinsic_lib_function (se, expr);
8208 break;
8213 static gfc_ss *
8214 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
8216 gfc_ss *arg_ss, *tmp_ss;
8217 gfc_actual_arglist *arg;
8219 arg = expr->value.function.actual;
8221 gcc_assert (arg->expr);
8223 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
8224 gcc_assert (arg_ss != gfc_ss_terminator);
8226 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
8228 if (tmp_ss->info->type != GFC_SS_SCALAR
8229 && tmp_ss->info->type != GFC_SS_REFERENCE)
8231 int tmp_dim;
8233 gcc_assert (tmp_ss->dimen == 2);
8235 /* We just invert dimensions. */
8236 tmp_dim = tmp_ss->dim[0];
8237 tmp_ss->dim[0] = tmp_ss->dim[1];
8238 tmp_ss->dim[1] = tmp_dim;
8241 /* Stop when tmp_ss points to the last valid element of the chain... */
8242 if (tmp_ss->next == gfc_ss_terminator)
8243 break;
8246 /* ... so that we can attach the rest of the chain to it. */
8247 tmp_ss->next = ss;
8249 return arg_ss;
8253 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
8254 This has the side effect of reversing the nested list, so there is no
8255 need to call gfc_reverse_ss on it (the given list is assumed not to be
8256 reversed yet). */
8258 static gfc_ss *
8259 nest_loop_dimension (gfc_ss *ss, int dim)
8261 int ss_dim, i;
8262 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
8263 gfc_loopinfo *new_loop;
8265 gcc_assert (ss != gfc_ss_terminator);
8267 for (; ss != gfc_ss_terminator; ss = ss->next)
8269 new_ss = gfc_get_ss ();
8270 new_ss->next = prev_ss;
8271 new_ss->parent = ss;
8272 new_ss->info = ss->info;
8273 new_ss->info->refcount++;
8274 if (ss->dimen != 0)
8276 gcc_assert (ss->info->type != GFC_SS_SCALAR
8277 && ss->info->type != GFC_SS_REFERENCE);
8279 new_ss->dimen = 1;
8280 new_ss->dim[0] = ss->dim[dim];
8282 gcc_assert (dim < ss->dimen);
8284 ss_dim = --ss->dimen;
8285 for (i = dim; i < ss_dim; i++)
8286 ss->dim[i] = ss->dim[i + 1];
8288 ss->dim[ss_dim] = 0;
8290 prev_ss = new_ss;
8292 if (ss->nested_ss)
8294 ss->nested_ss->parent = new_ss;
8295 new_ss->nested_ss = ss->nested_ss;
8297 ss->nested_ss = new_ss;
8300 new_loop = gfc_get_loopinfo ();
8301 gfc_init_loopinfo (new_loop);
8303 gcc_assert (prev_ss != NULL);
8304 gcc_assert (prev_ss != gfc_ss_terminator);
8305 gfc_add_ss_to_loop (new_loop, prev_ss);
8306 return new_ss->parent;
8310 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
8311 is to be inlined. */
8313 static gfc_ss *
8314 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
8316 gfc_ss *tmp_ss, *tail, *array_ss;
8317 gfc_actual_arglist *arg1, *arg2, *arg3;
8318 int sum_dim;
8319 bool scalar_mask = false;
8321 /* The rank of the result will be determined later. */
8322 arg1 = expr->value.function.actual;
8323 arg2 = arg1->next;
8324 arg3 = arg2->next;
8325 gcc_assert (arg3 != NULL);
8327 if (expr->rank == 0)
8328 return ss;
8330 tmp_ss = gfc_ss_terminator;
8332 if (arg3->expr)
8334 gfc_ss *mask_ss;
8336 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
8337 if (mask_ss == tmp_ss)
8338 scalar_mask = 1;
8340 tmp_ss = mask_ss;
8343 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
8344 gcc_assert (array_ss != tmp_ss);
8346 /* Odd thing: If the mask is scalar, it is used by the frontend after
8347 the array (to make an if around the nested loop). Thus it shall
8348 be after array_ss once the gfc_ss list is reversed. */
8349 if (scalar_mask)
8350 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
8351 else
8352 tmp_ss = array_ss;
8354 /* "Hide" the dimension on which we will sum in the first arg's scalarization
8355 chain. */
8356 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
8357 tail = nest_loop_dimension (tmp_ss, sum_dim);
8358 tail->next = ss;
8360 return tmp_ss;
8364 static gfc_ss *
8365 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
8368 switch (expr->value.function.isym->id)
8370 case GFC_ISYM_PRODUCT:
8371 case GFC_ISYM_SUM:
8372 return walk_inline_intrinsic_arith (ss, expr);
8374 case GFC_ISYM_TRANSPOSE:
8375 return walk_inline_intrinsic_transpose (ss, expr);
8377 default:
8378 gcc_unreachable ();
8380 gcc_unreachable ();
8384 /* This generates code to execute before entering the scalarization loop.
8385 Currently does nothing. */
8387 void
8388 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
8390 switch (ss->info->expr->value.function.isym->id)
8392 case GFC_ISYM_UBOUND:
8393 case GFC_ISYM_LBOUND:
8394 case GFC_ISYM_UCOBOUND:
8395 case GFC_ISYM_LCOBOUND:
8396 case GFC_ISYM_THIS_IMAGE:
8397 break;
8399 default:
8400 gcc_unreachable ();
8405 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
8406 are expanded into code inside the scalarization loop. */
8408 static gfc_ss *
8409 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
8411 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
8412 gfc_add_class_array_ref (expr->value.function.actual->expr);
8414 /* The two argument version returns a scalar. */
8415 if (expr->value.function.actual->next->expr)
8416 return ss;
8418 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
8422 /* Walk an intrinsic array libcall. */
8424 static gfc_ss *
8425 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
8427 gcc_assert (expr->rank > 0);
8428 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
8432 /* Return whether the function call expression EXPR will be expanded
8433 inline by gfc_conv_intrinsic_function. */
8435 bool
8436 gfc_inline_intrinsic_function_p (gfc_expr *expr)
8438 gfc_actual_arglist *args;
8440 if (!expr->value.function.isym)
8441 return false;
8443 switch (expr->value.function.isym->id)
8445 case GFC_ISYM_PRODUCT:
8446 case GFC_ISYM_SUM:
8447 /* Disable inline expansion if code size matters. */
8448 if (optimize_size)
8449 return false;
8451 args = expr->value.function.actual;
8452 /* We need to be able to subset the SUM argument at compile-time. */
8453 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
8454 return false;
8456 return true;
8458 case GFC_ISYM_TRANSPOSE:
8459 return true;
8461 default:
8462 return false;
8467 /* Returns nonzero if the specified intrinsic function call maps directly to
8468 an external library call. Should only be used for functions that return
8469 arrays. */
8472 gfc_is_intrinsic_libcall (gfc_expr * expr)
8474 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
8475 gcc_assert (expr->rank > 0);
8477 if (gfc_inline_intrinsic_function_p (expr))
8478 return 0;
8480 switch (expr->value.function.isym->id)
8482 case GFC_ISYM_ALL:
8483 case GFC_ISYM_ANY:
8484 case GFC_ISYM_COUNT:
8485 case GFC_ISYM_JN2:
8486 case GFC_ISYM_IANY:
8487 case GFC_ISYM_IALL:
8488 case GFC_ISYM_IPARITY:
8489 case GFC_ISYM_MATMUL:
8490 case GFC_ISYM_MAXLOC:
8491 case GFC_ISYM_MAXVAL:
8492 case GFC_ISYM_MINLOC:
8493 case GFC_ISYM_MINVAL:
8494 case GFC_ISYM_NORM2:
8495 case GFC_ISYM_PARITY:
8496 case GFC_ISYM_PRODUCT:
8497 case GFC_ISYM_SUM:
8498 case GFC_ISYM_SHAPE:
8499 case GFC_ISYM_SPREAD:
8500 case GFC_ISYM_YN2:
8501 /* Ignore absent optional parameters. */
8502 return 1;
8504 case GFC_ISYM_RESHAPE:
8505 case GFC_ISYM_CSHIFT:
8506 case GFC_ISYM_EOSHIFT:
8507 case GFC_ISYM_PACK:
8508 case GFC_ISYM_UNPACK:
8509 /* Pass absent optional parameters. */
8510 return 2;
8512 default:
8513 return 0;
8517 /* Walk an intrinsic function. */
8518 gfc_ss *
8519 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
8520 gfc_intrinsic_sym * isym)
8522 gcc_assert (isym);
8524 if (isym->elemental)
8525 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
8526 NULL, GFC_SS_SCALAR);
8528 if (expr->rank == 0)
8529 return ss;
8531 if (gfc_inline_intrinsic_function_p (expr))
8532 return walk_inline_intrinsic_function (ss, expr);
8534 if (gfc_is_intrinsic_libcall (expr))
8535 return gfc_walk_intrinsic_libfunc (ss, expr);
8537 /* Special cases. */
8538 switch (isym->id)
8540 case GFC_ISYM_LBOUND:
8541 case GFC_ISYM_LCOBOUND:
8542 case GFC_ISYM_UBOUND:
8543 case GFC_ISYM_UCOBOUND:
8544 case GFC_ISYM_THIS_IMAGE:
8545 return gfc_walk_intrinsic_bound (ss, expr);
8547 case GFC_ISYM_TRANSFER:
8548 case GFC_ISYM_CAF_GET:
8549 return gfc_walk_intrinsic_libfunc (ss, expr);
8551 default:
8552 /* This probably meant someone forgot to add an intrinsic to the above
8553 list(s) when they implemented it, or something's gone horribly
8554 wrong. */
8555 gcc_unreachable ();
8560 static tree
8561 conv_co_collective (gfc_code *code)
8563 gfc_se argse;
8564 stmtblock_t block, post_block;
8565 tree fndecl, array, strlen, image_index, stat, errmsg, errmsg_len;
8566 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
8568 gfc_start_block (&block);
8569 gfc_init_block (&post_block);
8571 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
8573 opr_expr = code->ext.actual->next->expr;
8574 image_idx_expr = code->ext.actual->next->next->expr;
8575 stat_expr = code->ext.actual->next->next->next->expr;
8576 errmsg_expr = code->ext.actual->next->next->next->next->expr;
8578 else
8580 opr_expr = NULL;
8581 image_idx_expr = code->ext.actual->next->expr;
8582 stat_expr = code->ext.actual->next->next->expr;
8583 errmsg_expr = code->ext.actual->next->next->next->expr;
8586 /* stat. */
8587 if (stat_expr)
8589 gfc_init_se (&argse, NULL);
8590 gfc_conv_expr (&argse, stat_expr);
8591 gfc_add_block_to_block (&block, &argse.pre);
8592 gfc_add_block_to_block (&post_block, &argse.post);
8593 stat = argse.expr;
8594 if (gfc_option.coarray != GFC_FCOARRAY_SINGLE)
8595 stat = gfc_build_addr_expr (NULL_TREE, stat);
8597 else if (gfc_option.coarray == GFC_FCOARRAY_SINGLE)
8598 stat = NULL_TREE;
8599 else
8600 stat = null_pointer_node;
8602 /* Early exit for GFC_FCOARRAY_SINGLE. */
8603 if (gfc_option.coarray == GFC_FCOARRAY_SINGLE)
8605 if (stat != NULL_TREE)
8606 gfc_add_modify (&block, stat,
8607 fold_convert (TREE_TYPE (stat), integer_zero_node));
8608 return gfc_finish_block (&block);
8611 /* Handle the array. */
8612 gfc_init_se (&argse, NULL);
8613 if (code->ext.actual->expr->rank == 0)
8615 symbol_attribute attr;
8616 gfc_clear_attr (&attr);
8617 gfc_init_se (&argse, NULL);
8618 gfc_conv_expr (&argse, code->ext.actual->expr);
8619 gfc_add_block_to_block (&block, &argse.pre);
8620 gfc_add_block_to_block (&post_block, &argse.post);
8621 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
8622 array = gfc_build_addr_expr (NULL_TREE, array);
8624 else
8626 argse.want_pointer = 1;
8627 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
8628 array = argse.expr;
8630 gfc_add_block_to_block (&block, &argse.pre);
8631 gfc_add_block_to_block (&post_block, &argse.post);
8633 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
8634 strlen = argse.string_length;
8635 else
8636 strlen = integer_zero_node;
8638 /* image_index. */
8639 if (image_idx_expr)
8641 gfc_init_se (&argse, NULL);
8642 gfc_conv_expr (&argse, image_idx_expr);
8643 gfc_add_block_to_block (&block, &argse.pre);
8644 gfc_add_block_to_block (&post_block, &argse.post);
8645 image_index = fold_convert (integer_type_node, argse.expr);
8647 else
8648 image_index = integer_zero_node;
8650 /* errmsg. */
8651 if (errmsg_expr)
8653 gfc_init_se (&argse, NULL);
8654 gfc_conv_expr (&argse, errmsg_expr);
8655 gfc_add_block_to_block (&block, &argse.pre);
8656 gfc_add_block_to_block (&post_block, &argse.post);
8657 errmsg = argse.expr;
8658 errmsg_len = fold_convert (integer_type_node, argse.string_length);
8660 else
8662 errmsg = null_pointer_node;
8663 errmsg_len = integer_zero_node;
8666 /* Generate the function call. */
8667 switch (code->resolved_isym->id)
8669 case GFC_ISYM_CO_BROADCAST:
8670 fndecl = gfor_fndecl_co_broadcast;
8671 break;
8672 case GFC_ISYM_CO_MAX:
8673 fndecl = gfor_fndecl_co_max;
8674 break;
8675 case GFC_ISYM_CO_MIN:
8676 fndecl = gfor_fndecl_co_min;
8677 break;
8678 case GFC_ISYM_CO_REDUCE:
8679 fndecl = gfor_fndecl_co_reduce;
8680 break;
8681 case GFC_ISYM_CO_SUM:
8682 fndecl = gfor_fndecl_co_sum;
8683 break;
8684 default:
8685 gcc_unreachable ();
8688 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
8689 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
8690 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
8691 image_index, stat, errmsg, errmsg_len);
8692 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
8693 fndecl = build_call_expr_loc (input_location, fndecl, 6, array, image_index,
8694 stat, errmsg, strlen, errmsg_len);
8695 else
8697 tree opr, opr_flags;
8699 // FIXME: Handle TS29113's bind(C) strings with descriptor.
8700 int opr_flag_int;
8701 if (gfc_is_proc_ptr_comp (opr_expr))
8703 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
8704 opr_flag_int = sym->attr.dimension
8705 || (sym->ts.type == BT_CHARACTER
8706 && !sym->attr.is_bind_c)
8707 ? GFC_CAF_BYREF : 0;
8708 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
8709 && !sym->attr.is_bind_c
8710 ? GFC_CAF_HIDDENLEN : 0;
8711 opr_flag_int |= sym->formal->sym->attr.value ? GFC_CAF_ARG_VALUE : 0;
8713 else
8715 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
8716 ? GFC_CAF_BYREF : 0;
8717 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
8718 && !opr_expr->symtree->n.sym->attr.is_bind_c
8719 ? GFC_CAF_HIDDENLEN : 0;
8720 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
8721 ? GFC_CAF_ARG_VALUE : 0;
8723 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
8724 gfc_conv_expr (&argse, opr_expr);
8725 opr = gfc_build_addr_expr (NULL_TREE, argse.expr);
8726 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr, opr_flags,
8727 image_index, stat, errmsg, strlen, errmsg_len);
8730 gfc_add_expr_to_block (&block, fndecl);
8731 gfc_add_block_to_block (&block, &post_block);
8733 return gfc_finish_block (&block);
8737 static tree
8738 conv_intrinsic_atomic_op (gfc_code *code)
8740 gfc_se argse;
8741 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
8742 stmtblock_t block, post_block;
8743 gfc_expr *atom_expr = code->ext.actual->expr;
8744 gfc_expr *stat_expr;
8745 built_in_function fn;
8747 if (atom_expr->expr_type == EXPR_FUNCTION
8748 && atom_expr->value.function.isym
8749 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
8750 atom_expr = atom_expr->value.function.actual->expr;
8752 gfc_start_block (&block);
8753 gfc_init_block (&post_block);
8755 gfc_init_se (&argse, NULL);
8756 argse.want_pointer = 1;
8757 gfc_conv_expr (&argse, atom_expr);
8758 gfc_add_block_to_block (&block, &argse.pre);
8759 gfc_add_block_to_block (&post_block, &argse.post);
8760 atom = argse.expr;
8762 gfc_init_se (&argse, NULL);
8763 if (gfc_option.coarray == GFC_FCOARRAY_LIB
8764 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
8765 argse.want_pointer = 1;
8766 gfc_conv_expr (&argse, code->ext.actual->next->expr);
8767 gfc_add_block_to_block (&block, &argse.pre);
8768 gfc_add_block_to_block (&post_block, &argse.post);
8769 value = argse.expr;
8771 switch (code->resolved_isym->id)
8773 case GFC_ISYM_ATOMIC_ADD:
8774 case GFC_ISYM_ATOMIC_AND:
8775 case GFC_ISYM_ATOMIC_DEF:
8776 case GFC_ISYM_ATOMIC_OR:
8777 case GFC_ISYM_ATOMIC_XOR:
8778 stat_expr = code->ext.actual->next->next->expr;
8779 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
8780 old = null_pointer_node;
8781 break;
8782 default:
8783 gfc_init_se (&argse, NULL);
8784 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
8785 argse.want_pointer = 1;
8786 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
8787 gfc_add_block_to_block (&block, &argse.pre);
8788 gfc_add_block_to_block (&post_block, &argse.post);
8789 old = argse.expr;
8790 stat_expr = code->ext.actual->next->next->next->expr;
8793 /* STAT= */
8794 if (stat_expr != NULL)
8796 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
8797 gfc_init_se (&argse, NULL);
8798 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
8799 argse.want_pointer = 1;
8800 gfc_conv_expr_val (&argse, stat_expr);
8801 gfc_add_block_to_block (&block, &argse.pre);
8802 gfc_add_block_to_block (&post_block, &argse.post);
8803 stat = argse.expr;
8805 else if (gfc_option.coarray == GFC_FCOARRAY_LIB)
8806 stat = null_pointer_node;
8808 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
8810 tree image_index, caf_decl, offset, token;
8811 int op;
8813 switch (code->resolved_isym->id)
8815 case GFC_ISYM_ATOMIC_ADD:
8816 case GFC_ISYM_ATOMIC_FETCH_ADD:
8817 op = (int) GFC_CAF_ATOMIC_ADD;
8818 break;
8819 case GFC_ISYM_ATOMIC_AND:
8820 case GFC_ISYM_ATOMIC_FETCH_AND:
8821 op = (int) GFC_CAF_ATOMIC_AND;
8822 break;
8823 case GFC_ISYM_ATOMIC_OR:
8824 case GFC_ISYM_ATOMIC_FETCH_OR:
8825 op = (int) GFC_CAF_ATOMIC_OR;
8826 break;
8827 case GFC_ISYM_ATOMIC_XOR:
8828 case GFC_ISYM_ATOMIC_FETCH_XOR:
8829 op = (int) GFC_CAF_ATOMIC_XOR;
8830 break;
8831 case GFC_ISYM_ATOMIC_DEF:
8832 op = 0; /* Unused. */
8833 break;
8834 default:
8835 gcc_unreachable ();
8838 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
8839 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
8840 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
8842 if (gfc_is_coindexed (atom_expr))
8843 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
8844 else
8845 image_index = integer_zero_node;
8847 if (!POINTER_TYPE_P (TREE_TYPE (value)))
8849 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
8850 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
8851 value = gfc_build_addr_expr (NULL_TREE, tmp);
8854 gfc_get_caf_token_offset (&token, &offset, caf_decl, atom, atom_expr);
8856 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
8857 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
8858 token, offset, image_index, value, stat,
8859 build_int_cst (integer_type_node,
8860 (int) atom_expr->ts.type),
8861 build_int_cst (integer_type_node,
8862 (int) atom_expr->ts.kind));
8863 else
8864 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
8865 build_int_cst (integer_type_node, op),
8866 token, offset, image_index, value, old, stat,
8867 build_int_cst (integer_type_node,
8868 (int) atom_expr->ts.type),
8869 build_int_cst (integer_type_node,
8870 (int) atom_expr->ts.kind));
8872 gfc_add_expr_to_block (&block, tmp);
8873 gfc_add_block_to_block (&block, &post_block);
8874 return gfc_finish_block (&block);
8878 switch (code->resolved_isym->id)
8880 case GFC_ISYM_ATOMIC_ADD:
8881 case GFC_ISYM_ATOMIC_FETCH_ADD:
8882 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
8883 break;
8884 case GFC_ISYM_ATOMIC_AND:
8885 case GFC_ISYM_ATOMIC_FETCH_AND:
8886 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
8887 break;
8888 case GFC_ISYM_ATOMIC_DEF:
8889 fn = BUILT_IN_ATOMIC_STORE_N;
8890 break;
8891 case GFC_ISYM_ATOMIC_OR:
8892 case GFC_ISYM_ATOMIC_FETCH_OR:
8893 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
8894 break;
8895 case GFC_ISYM_ATOMIC_XOR:
8896 case GFC_ISYM_ATOMIC_FETCH_XOR:
8897 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
8898 break;
8899 default:
8900 gcc_unreachable ();
8903 tmp = TREE_TYPE (TREE_TYPE (atom));
8904 fn = (built_in_function) ((int) fn
8905 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
8906 + 1);
8907 tmp = builtin_decl_explicit (fn);
8908 tree itype = TREE_TYPE (TREE_TYPE (atom));
8909 tmp = builtin_decl_explicit (fn);
8911 switch (code->resolved_isym->id)
8913 case GFC_ISYM_ATOMIC_ADD:
8914 case GFC_ISYM_ATOMIC_AND:
8915 case GFC_ISYM_ATOMIC_DEF:
8916 case GFC_ISYM_ATOMIC_OR:
8917 case GFC_ISYM_ATOMIC_XOR:
8918 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
8919 fold_convert (itype, value),
8920 build_int_cst (NULL, MEMMODEL_RELAXED));
8921 gfc_add_expr_to_block (&block, tmp);
8922 break;
8923 default:
8924 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
8925 fold_convert (itype, value),
8926 build_int_cst (NULL, MEMMODEL_RELAXED));
8927 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
8928 break;
8931 if (stat != NULL_TREE)
8932 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
8933 gfc_add_block_to_block (&block, &post_block);
8934 return gfc_finish_block (&block);
8938 static tree
8939 conv_intrinsic_atomic_ref (gfc_code *code)
8941 gfc_se argse;
8942 tree tmp, atom, value, stat = NULL_TREE;
8943 stmtblock_t block, post_block;
8944 built_in_function fn;
8945 gfc_expr *atom_expr = code->ext.actual->next->expr;
8947 if (atom_expr->expr_type == EXPR_FUNCTION
8948 && atom_expr->value.function.isym
8949 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
8950 atom_expr = atom_expr->value.function.actual->expr;
8952 gfc_start_block (&block);
8953 gfc_init_block (&post_block);
8954 gfc_init_se (&argse, NULL);
8955 argse.want_pointer = 1;
8956 gfc_conv_expr (&argse, atom_expr);
8957 gfc_add_block_to_block (&block, &argse.pre);
8958 gfc_add_block_to_block (&post_block, &argse.post);
8959 atom = argse.expr;
8961 gfc_init_se (&argse, NULL);
8962 if (gfc_option.coarray == GFC_FCOARRAY_LIB
8963 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
8964 argse.want_pointer = 1;
8965 gfc_conv_expr (&argse, code->ext.actual->expr);
8966 gfc_add_block_to_block (&block, &argse.pre);
8967 gfc_add_block_to_block (&post_block, &argse.post);
8968 value = argse.expr;
8970 /* STAT= */
8971 if (code->ext.actual->next->next->expr != NULL)
8973 gcc_assert (code->ext.actual->next->next->expr->expr_type
8974 == EXPR_VARIABLE);
8975 gfc_init_se (&argse, NULL);
8976 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
8977 argse.want_pointer = 1;
8978 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
8979 gfc_add_block_to_block (&block, &argse.pre);
8980 gfc_add_block_to_block (&post_block, &argse.post);
8981 stat = argse.expr;
8983 else if (gfc_option.coarray == GFC_FCOARRAY_LIB)
8984 stat = null_pointer_node;
8986 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
8988 tree image_index, caf_decl, offset, token;
8989 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
8991 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
8992 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
8993 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
8995 if (gfc_is_coindexed (atom_expr))
8996 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
8997 else
8998 image_index = integer_zero_node;
9000 gfc_get_caf_token_offset (&token, &offset, caf_decl, atom, atom_expr);
9002 /* Different type, need type conversion. */
9003 if (!POINTER_TYPE_P (TREE_TYPE (value)))
9005 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
9006 orig_value = value;
9007 value = gfc_build_addr_expr (NULL_TREE, vardecl);
9010 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
9011 token, offset, image_index, value, stat,
9012 build_int_cst (integer_type_node,
9013 (int) atom_expr->ts.type),
9014 build_int_cst (integer_type_node,
9015 (int) atom_expr->ts.kind));
9016 gfc_add_expr_to_block (&block, tmp);
9017 if (vardecl != NULL_TREE)
9018 gfc_add_modify (&block, orig_value,
9019 fold_convert (TREE_TYPE (orig_value), vardecl));
9020 gfc_add_block_to_block (&block, &post_block);
9021 return gfc_finish_block (&block);
9024 tmp = TREE_TYPE (TREE_TYPE (atom));
9025 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
9026 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
9027 + 1);
9028 tmp = builtin_decl_explicit (fn);
9029 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
9030 build_int_cst (integer_type_node,
9031 MEMMODEL_RELAXED));
9032 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
9034 if (stat != NULL_TREE)
9035 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
9036 gfc_add_block_to_block (&block, &post_block);
9037 return gfc_finish_block (&block);
9041 static tree
9042 conv_intrinsic_atomic_cas (gfc_code *code)
9044 gfc_se argse;
9045 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
9046 stmtblock_t block, post_block;
9047 built_in_function fn;
9048 gfc_expr *atom_expr = code->ext.actual->expr;
9050 if (atom_expr->expr_type == EXPR_FUNCTION
9051 && atom_expr->value.function.isym
9052 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
9053 atom_expr = atom_expr->value.function.actual->expr;
9055 gfc_init_block (&block);
9056 gfc_init_block (&post_block);
9057 gfc_init_se (&argse, NULL);
9058 argse.want_pointer = 1;
9059 gfc_conv_expr (&argse, atom_expr);
9060 atom = argse.expr;
9062 gfc_init_se (&argse, NULL);
9063 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
9064 argse.want_pointer = 1;
9065 gfc_conv_expr (&argse, code->ext.actual->next->expr);
9066 gfc_add_block_to_block (&block, &argse.pre);
9067 gfc_add_block_to_block (&post_block, &argse.post);
9068 old = argse.expr;
9070 gfc_init_se (&argse, NULL);
9071 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
9072 argse.want_pointer = 1;
9073 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
9074 gfc_add_block_to_block (&block, &argse.pre);
9075 gfc_add_block_to_block (&post_block, &argse.post);
9076 comp = argse.expr;
9078 gfc_init_se (&argse, NULL);
9079 if (gfc_option.coarray == GFC_FCOARRAY_LIB
9080 && code->ext.actual->next->next->next->expr->ts.kind
9081 == atom_expr->ts.kind)
9082 argse.want_pointer = 1;
9083 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
9084 gfc_add_block_to_block (&block, &argse.pre);
9085 gfc_add_block_to_block (&post_block, &argse.post);
9086 new_val = argse.expr;
9088 /* STAT= */
9089 if (code->ext.actual->next->next->next->next->expr != NULL)
9091 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
9092 == EXPR_VARIABLE);
9093 gfc_init_se (&argse, NULL);
9094 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
9095 argse.want_pointer = 1;
9096 gfc_conv_expr_val (&argse,
9097 code->ext.actual->next->next->next->next->expr);
9098 gfc_add_block_to_block (&block, &argse.pre);
9099 gfc_add_block_to_block (&post_block, &argse.post);
9100 stat = argse.expr;
9102 else if (gfc_option.coarray == GFC_FCOARRAY_LIB)
9103 stat = null_pointer_node;
9105 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
9107 tree image_index, caf_decl, offset, token;
9109 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
9110 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
9111 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
9113 if (gfc_is_coindexed (atom_expr))
9114 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
9115 else
9116 image_index = integer_zero_node;
9118 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
9120 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
9121 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
9122 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
9125 /* Convert a constant to a pointer. */
9126 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
9128 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
9129 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
9130 comp = gfc_build_addr_expr (NULL_TREE, tmp);
9133 gfc_get_caf_token_offset (&token, &offset, caf_decl, atom, atom_expr);
9135 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
9136 token, offset, image_index, old, comp, new_val,
9137 stat, build_int_cst (integer_type_node,
9138 (int) atom_expr->ts.type),
9139 build_int_cst (integer_type_node,
9140 (int) atom_expr->ts.kind));
9141 gfc_add_expr_to_block (&block, tmp);
9142 gfc_add_block_to_block (&block, &post_block);
9143 return gfc_finish_block (&block);
9146 tmp = TREE_TYPE (TREE_TYPE (atom));
9147 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
9148 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
9149 + 1);
9150 tmp = builtin_decl_explicit (fn);
9152 gfc_add_modify (&block, old, comp);
9153 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
9154 gfc_build_addr_expr (NULL, old),
9155 fold_convert (TREE_TYPE (old), new_val),
9156 boolean_false_node,
9157 build_int_cst (NULL, MEMMODEL_RELAXED),
9158 build_int_cst (NULL, MEMMODEL_RELAXED));
9159 gfc_add_expr_to_block (&block, tmp);
9161 if (stat != NULL_TREE)
9162 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
9163 gfc_add_block_to_block (&block, &post_block);
9164 return gfc_finish_block (&block);
9168 static tree
9169 conv_intrinsic_move_alloc (gfc_code *code)
9171 stmtblock_t block;
9172 gfc_expr *from_expr, *to_expr;
9173 gfc_expr *to_expr2, *from_expr2 = NULL;
9174 gfc_se from_se, to_se;
9175 tree tmp;
9176 bool coarray;
9178 gfc_start_block (&block);
9180 from_expr = code->ext.actual->expr;
9181 to_expr = code->ext.actual->next->expr;
9183 gfc_init_se (&from_se, NULL);
9184 gfc_init_se (&to_se, NULL);
9186 gcc_assert (from_expr->ts.type != BT_CLASS
9187 || to_expr->ts.type == BT_CLASS);
9188 coarray = gfc_get_corank (from_expr) != 0;
9190 if (from_expr->rank == 0 && !coarray)
9192 if (from_expr->ts.type != BT_CLASS)
9193 from_expr2 = from_expr;
9194 else
9196 from_expr2 = gfc_copy_expr (from_expr);
9197 gfc_add_data_component (from_expr2);
9200 if (to_expr->ts.type != BT_CLASS)
9201 to_expr2 = to_expr;
9202 else
9204 to_expr2 = gfc_copy_expr (to_expr);
9205 gfc_add_data_component (to_expr2);
9208 from_se.want_pointer = 1;
9209 to_se.want_pointer = 1;
9210 gfc_conv_expr (&from_se, from_expr2);
9211 gfc_conv_expr (&to_se, to_expr2);
9212 gfc_add_block_to_block (&block, &from_se.pre);
9213 gfc_add_block_to_block (&block, &to_se.pre);
9215 /* Deallocate "to". */
9216 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, true,
9217 to_expr, to_expr->ts);
9218 gfc_add_expr_to_block (&block, tmp);
9220 /* Assign (_data) pointers. */
9221 gfc_add_modify_loc (input_location, &block, to_se.expr,
9222 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
9224 /* Set "from" to NULL. */
9225 gfc_add_modify_loc (input_location, &block, from_se.expr,
9226 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
9228 gfc_add_block_to_block (&block, &from_se.post);
9229 gfc_add_block_to_block (&block, &to_se.post);
9231 /* Set _vptr. */
9232 if (to_expr->ts.type == BT_CLASS)
9234 gfc_symbol *vtab;
9236 gfc_free_expr (to_expr2);
9237 gfc_init_se (&to_se, NULL);
9238 to_se.want_pointer = 1;
9239 gfc_add_vptr_component (to_expr);
9240 gfc_conv_expr (&to_se, to_expr);
9242 if (from_expr->ts.type == BT_CLASS)
9244 if (UNLIMITED_POLY (from_expr))
9245 vtab = NULL;
9246 else
9248 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
9249 gcc_assert (vtab);
9252 gfc_free_expr (from_expr2);
9253 gfc_init_se (&from_se, NULL);
9254 from_se.want_pointer = 1;
9255 gfc_add_vptr_component (from_expr);
9256 gfc_conv_expr (&from_se, from_expr);
9257 gfc_add_modify_loc (input_location, &block, to_se.expr,
9258 fold_convert (TREE_TYPE (to_se.expr),
9259 from_se.expr));
9261 /* Reset _vptr component to declared type. */
9262 if (vtab == NULL)
9263 /* Unlimited polymorphic. */
9264 gfc_add_modify_loc (input_location, &block, from_se.expr,
9265 fold_convert (TREE_TYPE (from_se.expr),
9266 null_pointer_node));
9267 else
9269 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
9270 gfc_add_modify_loc (input_location, &block, from_se.expr,
9271 fold_convert (TREE_TYPE (from_se.expr), tmp));
9274 else
9276 vtab = gfc_find_vtab (&from_expr->ts);
9277 gcc_assert (vtab);
9278 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
9279 gfc_add_modify_loc (input_location, &block, to_se.expr,
9280 fold_convert (TREE_TYPE (to_se.expr), tmp));
9284 return gfc_finish_block (&block);
9287 /* Update _vptr component. */
9288 if (to_expr->ts.type == BT_CLASS)
9290 gfc_symbol *vtab;
9292 to_se.want_pointer = 1;
9293 to_expr2 = gfc_copy_expr (to_expr);
9294 gfc_add_vptr_component (to_expr2);
9295 gfc_conv_expr (&to_se, to_expr2);
9297 if (from_expr->ts.type == BT_CLASS)
9299 if (UNLIMITED_POLY (from_expr))
9300 vtab = NULL;
9301 else
9303 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
9304 gcc_assert (vtab);
9307 from_se.want_pointer = 1;
9308 from_expr2 = gfc_copy_expr (from_expr);
9309 gfc_add_vptr_component (from_expr2);
9310 gfc_conv_expr (&from_se, from_expr2);
9311 gfc_add_modify_loc (input_location, &block, to_se.expr,
9312 fold_convert (TREE_TYPE (to_se.expr),
9313 from_se.expr));
9315 /* Reset _vptr component to declared type. */
9316 if (vtab == NULL)
9317 /* Unlimited polymorphic. */
9318 gfc_add_modify_loc (input_location, &block, from_se.expr,
9319 fold_convert (TREE_TYPE (from_se.expr),
9320 null_pointer_node));
9321 else
9323 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
9324 gfc_add_modify_loc (input_location, &block, from_se.expr,
9325 fold_convert (TREE_TYPE (from_se.expr), tmp));
9328 else
9330 vtab = gfc_find_vtab (&from_expr->ts);
9331 gcc_assert (vtab);
9332 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
9333 gfc_add_modify_loc (input_location, &block, to_se.expr,
9334 fold_convert (TREE_TYPE (to_se.expr), tmp));
9337 gfc_free_expr (to_expr2);
9338 gfc_init_se (&to_se, NULL);
9340 if (from_expr->ts.type == BT_CLASS)
9342 gfc_free_expr (from_expr2);
9343 gfc_init_se (&from_se, NULL);
9348 /* Deallocate "to". */
9349 if (from_expr->rank == 0)
9351 to_se.want_coarray = 1;
9352 from_se.want_coarray = 1;
9354 gfc_conv_expr_descriptor (&to_se, to_expr);
9355 gfc_conv_expr_descriptor (&from_se, from_expr);
9357 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
9358 is an image control "statement", cf. IR F08/0040 in 12-006A. */
9359 if (coarray && gfc_option.coarray == GFC_FCOARRAY_LIB)
9361 tree cond;
9363 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
9364 NULL_TREE, NULL_TREE, true, to_expr,
9365 true);
9366 gfc_add_expr_to_block (&block, tmp);
9368 tmp = gfc_conv_descriptor_data_get (to_se.expr);
9369 cond = fold_build2_loc (input_location, EQ_EXPR,
9370 boolean_type_node, tmp,
9371 fold_convert (TREE_TYPE (tmp),
9372 null_pointer_node));
9373 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
9374 3, null_pointer_node, null_pointer_node,
9375 build_int_cst (integer_type_node, 0));
9377 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
9378 tmp, build_empty_stmt (input_location));
9379 gfc_add_expr_to_block (&block, tmp);
9381 else
9383 tmp = gfc_conv_descriptor_data_get (to_se.expr);
9384 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
9385 NULL_TREE, true, to_expr, false);
9386 gfc_add_expr_to_block (&block, tmp);
9389 /* Move the pointer and update the array descriptor data. */
9390 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
9392 /* Set "from" to NULL. */
9393 tmp = gfc_conv_descriptor_data_get (from_se.expr);
9394 gfc_add_modify_loc (input_location, &block, tmp,
9395 fold_convert (TREE_TYPE (tmp), null_pointer_node));
9397 return gfc_finish_block (&block);
9401 tree
9402 gfc_conv_intrinsic_subroutine (gfc_code *code)
9404 tree res;
9406 gcc_assert (code->resolved_isym);
9408 switch (code->resolved_isym->id)
9410 case GFC_ISYM_MOVE_ALLOC:
9411 res = conv_intrinsic_move_alloc (code);
9412 break;
9414 case GFC_ISYM_ATOMIC_CAS:
9415 res = conv_intrinsic_atomic_cas (code);
9416 break;
9418 case GFC_ISYM_ATOMIC_ADD:
9419 case GFC_ISYM_ATOMIC_AND:
9420 case GFC_ISYM_ATOMIC_DEF:
9421 case GFC_ISYM_ATOMIC_OR:
9422 case GFC_ISYM_ATOMIC_XOR:
9423 case GFC_ISYM_ATOMIC_FETCH_ADD:
9424 case GFC_ISYM_ATOMIC_FETCH_AND:
9425 case GFC_ISYM_ATOMIC_FETCH_OR:
9426 case GFC_ISYM_ATOMIC_FETCH_XOR:
9427 res = conv_intrinsic_atomic_op (code);
9428 break;
9430 case GFC_ISYM_ATOMIC_REF:
9431 res = conv_intrinsic_atomic_ref (code);
9432 break;
9434 case GFC_ISYM_C_F_POINTER:
9435 case GFC_ISYM_C_F_PROCPOINTER:
9436 res = conv_isocbinding_subroutine (code);
9437 break;
9439 case GFC_ISYM_CAF_SEND:
9440 res = conv_caf_send (code);
9441 break;
9443 case GFC_ISYM_CO_BROADCAST:
9444 case GFC_ISYM_CO_MIN:
9445 case GFC_ISYM_CO_MAX:
9446 case GFC_ISYM_CO_REDUCE:
9447 case GFC_ISYM_CO_SUM:
9448 res = conv_co_collective (code);
9449 break;
9451 case GFC_ISYM_SYSTEM_CLOCK:
9452 res = conv_intrinsic_system_clock (code);
9453 break;
9455 default:
9456 res = NULL_TREE;
9457 break;
9460 return res;
9463 #include "gt-fortran-trans-intrinsic.h"