libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / fortran / trans-intrinsic.cc
blob80d75f26b0959737db7cb32bccf63afdd2e0d72d
1 /* Intrinsic translation
2 Copyright (C) 2002-2024 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.cc-- generate GENERIC trees for calls to intrinsics. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "memmodel.h"
28 #include "tm.h" /* For UNITS_PER_WORD. */
29 #include "tree.h"
30 #include "gfortran.h"
31 #include "trans.h"
32 #include "stringpool.h"
33 #include "fold-const.h"
34 #include "internal-fn.h"
35 #include "tree-nested.h"
36 #include "stor-layout.h"
37 #include "toplev.h" /* For rest_of_decl_compilation. */
38 #include "arith.h"
39 #include "trans-const.h"
40 #include "trans-types.h"
41 #include "trans-array.h"
42 #include "dependency.h" /* For CAF array alias analysis. */
43 #include "attribs.h"
44 #include "realmpfr.h"
46 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
48 /* This maps Fortran intrinsic math functions to external library or GCC
49 builtin functions. */
50 typedef struct GTY(()) gfc_intrinsic_map_t {
51 /* The explicit enum is required to work around inadequacies in the
52 garbage collection/gengtype parsing mechanism. */
53 enum gfc_isym_id id;
55 /* Enum value from the "language-independent", aka C-centric, part
56 of gcc, or END_BUILTINS of no such value set. */
57 enum built_in_function float_built_in;
58 enum built_in_function double_built_in;
59 enum built_in_function long_double_built_in;
60 enum built_in_function complex_float_built_in;
61 enum built_in_function complex_double_built_in;
62 enum built_in_function complex_long_double_built_in;
64 /* True if the naming pattern is to prepend "c" for complex and
65 append "f" for kind=4. False if the naming pattern is to
66 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
67 bool libm_name;
69 /* True if a complex version of the function exists. */
70 bool complex_available;
72 /* True if the function should be marked const. */
73 bool is_constant;
75 /* The base library name of this function. */
76 const char *name;
78 /* Cache decls created for the various operand types. */
79 tree real4_decl;
80 tree real8_decl;
81 tree real10_decl;
82 tree real16_decl;
83 tree complex4_decl;
84 tree complex8_decl;
85 tree complex10_decl;
86 tree complex16_decl;
88 gfc_intrinsic_map_t;
90 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
91 defines complex variants of all of the entries in mathbuiltins.def
92 except for atan2. */
93 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
94 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
95 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
96 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
97 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
99 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
100 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
101 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
102 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
103 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
105 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
106 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
107 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
108 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
109 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
111 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
112 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
113 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
114 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
115 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
117 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
119 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
120 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
121 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
122 #include "mathbuiltins.def"
124 /* Functions in libgfortran. */
125 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
126 LIB_FUNCTION (SIND, "sind", false),
127 LIB_FUNCTION (COSD, "cosd", false),
128 LIB_FUNCTION (TAND, "tand", false),
130 /* End the list. */
131 LIB_FUNCTION (NONE, NULL, false)
134 #undef OTHER_BUILTIN
135 #undef LIB_FUNCTION
136 #undef DEFINE_MATH_BUILTIN
137 #undef DEFINE_MATH_BUILTIN_C
140 enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
143 /* Find the correct variant of a given builtin from its argument. */
144 static tree
145 builtin_decl_for_precision (enum built_in_function base_built_in,
146 int precision)
148 enum built_in_function i = END_BUILTINS;
150 gfc_intrinsic_map_t *m;
151 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
154 if (precision == TYPE_PRECISION (float_type_node))
155 i = m->float_built_in;
156 else if (precision == TYPE_PRECISION (double_type_node))
157 i = m->double_built_in;
158 else if (precision == TYPE_PRECISION (long_double_type_node)
159 && (!gfc_real16_is_float128
160 || long_double_type_node != gfc_float128_type_node))
161 i = m->long_double_built_in;
162 else if (precision == TYPE_PRECISION (gfc_float128_type_node))
164 /* Special treatment, because it is not exactly a built-in, but
165 a library function. */
166 return m->real16_decl;
169 return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
173 tree
174 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
175 int kind)
177 int i = gfc_validate_kind (BT_REAL, kind, false);
179 if (gfc_real_kinds[i].c_float128)
181 /* For _Float128, the story is a bit different, because we return
182 a decl to a library function rather than a built-in. */
183 gfc_intrinsic_map_t *m;
184 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
187 return m->real16_decl;
190 return builtin_decl_for_precision (double_built_in,
191 gfc_real_kinds[i].mode_precision);
195 /* Evaluate the arguments to an intrinsic function. The value
196 of NARGS may be less than the actual number of arguments in EXPR
197 to allow optional "KIND" arguments that are not included in the
198 generated code to be ignored. */
200 static void
201 gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
202 tree *argarray, int nargs)
204 gfc_actual_arglist *actual;
205 gfc_expr *e;
206 gfc_intrinsic_arg *formal;
207 gfc_se argse;
208 int curr_arg;
210 formal = expr->value.function.isym->formal;
211 actual = expr->value.function.actual;
213 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
214 actual = actual->next,
215 formal = formal ? formal->next : NULL)
217 gcc_assert (actual);
218 e = actual->expr;
219 /* Skip omitted optional arguments. */
220 if (!e)
222 --curr_arg;
223 continue;
226 /* Evaluate the parameter. This will substitute scalarized
227 references automatically. */
228 gfc_init_se (&argse, se);
230 if (e->ts.type == BT_CHARACTER)
232 gfc_conv_expr (&argse, e);
233 gfc_conv_string_parameter (&argse);
234 argarray[curr_arg++] = argse.string_length;
235 gcc_assert (curr_arg < nargs);
237 else
238 gfc_conv_expr_val (&argse, e);
240 /* If an optional argument is itself an optional dummy argument,
241 check its presence and substitute a null if absent. */
242 if (e->expr_type == EXPR_VARIABLE
243 && e->symtree->n.sym->attr.optional
244 && formal
245 && formal->optional)
246 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
248 gfc_add_block_to_block (&se->pre, &argse.pre);
249 gfc_add_block_to_block (&se->post, &argse.post);
250 argarray[curr_arg] = argse.expr;
254 /* Count the number of actual arguments to the intrinsic function EXPR
255 including any "hidden" string length arguments. */
257 static unsigned int
258 gfc_intrinsic_argument_list_length (gfc_expr *expr)
260 int n = 0;
261 gfc_actual_arglist *actual;
263 for (actual = expr->value.function.actual; actual; actual = actual->next)
265 if (!actual->expr)
266 continue;
268 if (actual->expr->ts.type == BT_CHARACTER)
269 n += 2;
270 else
271 n++;
274 return n;
278 /* Conversions between different types are output by the frontend as
279 intrinsic functions. We implement these directly with inline code. */
281 static void
282 gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
284 tree type;
285 tree *args;
286 int nargs;
288 nargs = gfc_intrinsic_argument_list_length (expr);
289 args = XALLOCAVEC (tree, nargs);
291 /* Evaluate all the arguments passed. Whilst we're only interested in the
292 first one here, there are other parts of the front-end that assume this
293 and will trigger an ICE if it's not the case. */
294 type = gfc_typenode_for_spec (&expr->ts);
295 gcc_assert (expr->value.function.actual->expr);
296 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
298 /* Conversion between character kinds involves a call to a library
299 function. */
300 if (expr->ts.type == BT_CHARACTER)
302 tree fndecl, var, addr, tmp;
304 if (expr->ts.kind == 1
305 && expr->value.function.actual->expr->ts.kind == 4)
306 fndecl = gfor_fndecl_convert_char4_to_char1;
307 else if (expr->ts.kind == 4
308 && expr->value.function.actual->expr->ts.kind == 1)
309 fndecl = gfor_fndecl_convert_char1_to_char4;
310 else
311 gcc_unreachable ();
313 /* Create the variable storing the converted value. */
314 type = gfc_get_pchar_type (expr->ts.kind);
315 var = gfc_create_var (type, "str");
316 addr = gfc_build_addr_expr (build_pointer_type (type), var);
318 /* Call the library function that will perform the conversion. */
319 gcc_assert (nargs >= 2);
320 tmp = build_call_expr_loc (input_location,
321 fndecl, 3, addr, args[0], args[1]);
322 gfc_add_expr_to_block (&se->pre, tmp);
324 /* Free the temporary afterwards. */
325 tmp = gfc_call_free (var);
326 gfc_add_expr_to_block (&se->post, tmp);
328 se->expr = var;
329 se->string_length = args[0];
331 return;
334 /* Conversion from complex to non-complex involves taking the real
335 component of the value. */
336 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
337 && expr->ts.type != BT_COMPLEX)
339 tree artype;
341 artype = TREE_TYPE (TREE_TYPE (args[0]));
342 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
343 args[0]);
346 se->expr = convert (type, args[0]);
349 /* This is needed because the gcc backend only implements
350 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
351 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
352 Similarly for CEILING. */
354 static tree
355 build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
357 tree tmp;
358 tree cond;
359 tree argtype;
360 tree intval;
362 argtype = TREE_TYPE (arg);
363 arg = gfc_evaluate_now (arg, pblock);
365 intval = convert (type, arg);
366 intval = gfc_evaluate_now (intval, pblock);
368 tmp = convert (argtype, intval);
369 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
370 logical_type_node, tmp, arg);
372 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
373 intval, build_int_cst (type, 1));
374 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
375 return tmp;
379 /* Round to nearest integer, away from zero. */
381 static tree
382 build_round_expr (tree arg, tree restype)
384 tree argtype;
385 tree fn;
386 int argprec, resprec;
388 argtype = TREE_TYPE (arg);
389 argprec = TYPE_PRECISION (argtype);
390 resprec = TYPE_PRECISION (restype);
392 /* Depending on the type of the result, choose the int intrinsic (iround,
393 available only as a builtin, therefore cannot use it for _Float128), long
394 int intrinsic (lround family) or long long intrinsic (llround). If we
395 don't have an appropriate function that converts directly to the integer
396 type (such as kind == 16), just use ROUND, and then convert the result to
397 an integer. We might also need to convert the result afterwards. */
398 if (resprec <= INT_TYPE_SIZE
399 && argprec <= TYPE_PRECISION (long_double_type_node))
400 fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
401 else if (resprec <= LONG_TYPE_SIZE)
402 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
403 else if (resprec <= LONG_LONG_TYPE_SIZE)
404 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
405 else if (resprec >= argprec)
406 fn = builtin_decl_for_precision (BUILT_IN_ROUND, argprec);
407 else
408 gcc_unreachable ();
410 return convert (restype, build_call_expr_loc (input_location,
411 fn, 1, arg));
415 /* Convert a real to an integer using a specific rounding mode.
416 Ideally we would just build the corresponding GENERIC node,
417 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
419 static tree
420 build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
421 enum rounding_mode op)
423 switch (op)
425 case RND_FLOOR:
426 return build_fixbound_expr (pblock, arg, type, 0);
428 case RND_CEIL:
429 return build_fixbound_expr (pblock, arg, type, 1);
431 case RND_ROUND:
432 return build_round_expr (arg, type);
434 case RND_TRUNC:
435 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
437 default:
438 gcc_unreachable ();
443 /* Round a real value using the specified rounding mode.
444 We use a temporary integer of that same kind size as the result.
445 Values larger than those that can be represented by this kind are
446 unchanged, as they will not be accurate enough to represent the
447 rounding.
448 huge = HUGE (KIND (a))
449 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
452 static void
453 gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
455 tree type;
456 tree itype;
457 tree arg[2];
458 tree tmp;
459 tree cond;
460 tree decl;
461 mpfr_t huge;
462 int n, nargs;
463 int kind;
465 kind = expr->ts.kind;
466 nargs = gfc_intrinsic_argument_list_length (expr);
468 decl = NULL_TREE;
469 /* We have builtin functions for some cases. */
470 switch (op)
472 case RND_ROUND:
473 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
474 break;
476 case RND_TRUNC:
477 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
478 break;
480 default:
481 gcc_unreachable ();
484 /* Evaluate the argument. */
485 gcc_assert (expr->value.function.actual->expr);
486 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
488 /* Use a builtin function if one exists. */
489 if (decl != NULL_TREE)
491 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
492 return;
495 /* This code is probably redundant, but we'll keep it lying around just
496 in case. */
497 type = gfc_typenode_for_spec (&expr->ts);
498 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
500 /* Test if the value is too large to handle sensibly. */
501 gfc_set_model_kind (kind);
502 mpfr_init (huge);
503 n = gfc_validate_kind (BT_INTEGER, kind, false);
504 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
505 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
506 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, arg[0],
507 tmp);
509 mpfr_neg (huge, huge, GFC_RND_MODE);
510 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
511 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, arg[0],
512 tmp);
513 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node,
514 cond, tmp);
515 itype = gfc_get_int_type (kind);
517 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
518 tmp = convert (type, tmp);
519 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
520 arg[0]);
521 mpfr_clear (huge);
525 /* Convert to an integer using the specified rounding mode. */
527 static void
528 gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
530 tree type;
531 tree *args;
532 int nargs;
534 nargs = gfc_intrinsic_argument_list_length (expr);
535 args = XALLOCAVEC (tree, nargs);
537 /* Evaluate the argument, we process all arguments even though we only
538 use the first one for code generation purposes. */
539 type = gfc_typenode_for_spec (&expr->ts);
540 gcc_assert (expr->value.function.actual->expr);
541 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
543 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
545 /* Conversion to a different integer kind. */
546 se->expr = convert (type, args[0]);
548 else
550 /* Conversion from complex to non-complex involves taking the real
551 component of the value. */
552 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
553 && expr->ts.type != BT_COMPLEX)
555 tree artype;
557 artype = TREE_TYPE (TREE_TYPE (args[0]));
558 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
559 args[0]);
562 se->expr = build_fix_expr (&se->pre, args[0], type, op);
567 /* Get the imaginary component of a value. */
569 static void
570 gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
572 tree arg;
574 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
575 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
576 TREE_TYPE (TREE_TYPE (arg)), arg);
580 /* Get the complex conjugate of a value. */
582 static void
583 gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
585 tree arg;
587 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
588 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
593 static tree
594 define_quad_builtin (const char *name, tree type, bool is_const)
596 tree fndecl;
597 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
598 type);
600 /* Mark the decl as external. */
601 DECL_EXTERNAL (fndecl) = 1;
602 TREE_PUBLIC (fndecl) = 1;
604 /* Mark it __attribute__((const)). */
605 TREE_READONLY (fndecl) = is_const;
607 rest_of_decl_compilation (fndecl, 1, 0);
609 return fndecl;
612 /* Add SIMD attribute for FNDECL built-in if the built-in
613 name is in VECTORIZED_BUILTINS. */
615 static void
616 add_simd_flag_for_built_in (tree fndecl)
618 if (gfc_vectorized_builtins == NULL
619 || fndecl == NULL_TREE)
620 return;
622 const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
623 int *clauses = gfc_vectorized_builtins->get (name);
624 if (clauses)
626 for (unsigned i = 0; i < 3; i++)
627 if (*clauses & (1 << i))
629 gfc_simd_clause simd_type = (gfc_simd_clause)*clauses;
630 tree omp_clause = NULL_TREE;
631 if (simd_type == SIMD_NONE)
632 ; /* No SIMD clause. */
633 else
635 omp_clause_code code
636 = (simd_type == SIMD_INBRANCH
637 ? OMP_CLAUSE_INBRANCH : OMP_CLAUSE_NOTINBRANCH);
638 omp_clause = build_omp_clause (UNKNOWN_LOCATION, code);
639 omp_clause = build_tree_list (NULL_TREE, omp_clause);
642 DECL_ATTRIBUTES (fndecl)
643 = tree_cons (get_identifier ("omp declare simd"), omp_clause,
644 DECL_ATTRIBUTES (fndecl));
649 /* Set SIMD attribute to all built-in functions that are mentioned
650 in gfc_vectorized_builtins vector. */
652 void
653 gfc_adjust_builtins (void)
655 gfc_intrinsic_map_t *m;
656 for (m = gfc_intrinsic_map;
657 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
659 add_simd_flag_for_built_in (m->real4_decl);
660 add_simd_flag_for_built_in (m->complex4_decl);
661 add_simd_flag_for_built_in (m->real8_decl);
662 add_simd_flag_for_built_in (m->complex8_decl);
663 add_simd_flag_for_built_in (m->real10_decl);
664 add_simd_flag_for_built_in (m->complex10_decl);
665 add_simd_flag_for_built_in (m->real16_decl);
666 add_simd_flag_for_built_in (m->complex16_decl);
667 add_simd_flag_for_built_in (m->real16_decl);
668 add_simd_flag_for_built_in (m->complex16_decl);
671 /* Release all strings. */
672 if (gfc_vectorized_builtins != NULL)
674 for (hash_map<nofree_string_hash, int>::iterator it
675 = gfc_vectorized_builtins->begin ();
676 it != gfc_vectorized_builtins->end (); ++it)
677 free (CONST_CAST (char *, (*it).first));
679 delete gfc_vectorized_builtins;
680 gfc_vectorized_builtins = NULL;
684 /* Initialize function decls for library functions. The external functions
685 are created as required. Builtin functions are added here. */
687 void
688 gfc_build_intrinsic_lib_fndecls (void)
690 gfc_intrinsic_map_t *m;
691 tree quad_decls[END_BUILTINS + 1];
693 if (gfc_real16_is_float128)
695 /* If we have soft-float types, we create the decls for their
696 C99-like library functions. For now, we only handle _Float128
697 q-suffixed or IEC 60559 f128-suffixed functions. */
699 tree type, complex_type, func_1, func_2, func_3, func_cabs, func_frexp;
700 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
702 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
704 type = gfc_float128_type_node;
705 complex_type = gfc_complex_float128_type_node;
706 /* type (*) (type) */
707 func_1 = build_function_type_list (type, type, NULL_TREE);
708 /* int (*) (type) */
709 func_iround = build_function_type_list (integer_type_node,
710 type, NULL_TREE);
711 /* long (*) (type) */
712 func_lround = build_function_type_list (long_integer_type_node,
713 type, NULL_TREE);
714 /* long long (*) (type) */
715 func_llround = build_function_type_list (long_long_integer_type_node,
716 type, NULL_TREE);
717 /* type (*) (type, type) */
718 func_2 = build_function_type_list (type, type, type, NULL_TREE);
719 /* type (*) (type, type, type) */
720 func_3 = build_function_type_list (type, type, type, type, NULL_TREE);
721 /* type (*) (type, &int) */
722 func_frexp
723 = build_function_type_list (type,
724 type,
725 build_pointer_type (integer_type_node),
726 NULL_TREE);
727 /* type (*) (type, int) */
728 func_scalbn = build_function_type_list (type,
729 type, integer_type_node, NULL_TREE);
730 /* type (*) (complex type) */
731 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
732 /* complex type (*) (complex type, complex type) */
733 func_cpow
734 = build_function_type_list (complex_type,
735 complex_type, complex_type, NULL_TREE);
737 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
738 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
739 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
741 /* Only these built-ins are actually needed here. These are used directly
742 from the code, when calling builtin_decl_for_precision() or
743 builtin_decl_for_float_type(). The others are all constructed by
744 gfc_get_intrinsic_lib_fndecl(). */
745 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
746 quad_decls[BUILT_IN_ ## ID] \
747 = define_quad_builtin (gfc_real16_use_iec_60559 \
748 ? NAME "f128" : NAME "q", func_ ## TYPE, \
749 CONST);
751 #include "mathbuiltins.def"
753 #undef OTHER_BUILTIN
754 #undef LIB_FUNCTION
755 #undef DEFINE_MATH_BUILTIN
756 #undef DEFINE_MATH_BUILTIN_C
758 /* There is one built-in we defined manually, because it gets called
759 with builtin_decl_for_precision() or builtin_decl_for_float_type()
760 even though it is not an OTHER_BUILTIN: it is SQRT. */
761 quad_decls[BUILT_IN_SQRT]
762 = define_quad_builtin (gfc_real16_use_iec_60559
763 ? "sqrtf128" : "sqrtq", func_1, true);
766 /* Add GCC builtin functions. */
767 for (m = gfc_intrinsic_map;
768 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
770 if (m->float_built_in != END_BUILTINS)
771 m->real4_decl = builtin_decl_explicit (m->float_built_in);
772 if (m->complex_float_built_in != END_BUILTINS)
773 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
774 if (m->double_built_in != END_BUILTINS)
775 m->real8_decl = builtin_decl_explicit (m->double_built_in);
776 if (m->complex_double_built_in != END_BUILTINS)
777 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
779 /* If real(kind=10) exists, it is always long double. */
780 if (m->long_double_built_in != END_BUILTINS)
781 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
782 if (m->complex_long_double_built_in != END_BUILTINS)
783 m->complex10_decl
784 = builtin_decl_explicit (m->complex_long_double_built_in);
786 if (!gfc_real16_is_float128)
788 if (m->long_double_built_in != END_BUILTINS)
789 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
790 if (m->complex_long_double_built_in != END_BUILTINS)
791 m->complex16_decl
792 = builtin_decl_explicit (m->complex_long_double_built_in);
794 else if (quad_decls[m->double_built_in] != NULL_TREE)
796 /* Quad-precision function calls are constructed when first
797 needed by builtin_decl_for_precision(), except for those
798 that will be used directly (define by OTHER_BUILTIN). */
799 m->real16_decl = quad_decls[m->double_built_in];
801 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
803 /* Same thing for the complex ones. */
804 m->complex16_decl = quad_decls[m->double_built_in];
810 /* Create a fndecl for a simple intrinsic library function. */
812 static tree
813 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
815 tree type;
816 vec<tree, va_gc> *argtypes;
817 tree fndecl;
818 gfc_actual_arglist *actual;
819 tree *pdecl;
820 gfc_typespec *ts;
821 char name[GFC_MAX_SYMBOL_LEN + 3];
823 ts = &expr->ts;
824 if (ts->type == BT_REAL)
826 switch (ts->kind)
828 case 4:
829 pdecl = &m->real4_decl;
830 break;
831 case 8:
832 pdecl = &m->real8_decl;
833 break;
834 case 10:
835 pdecl = &m->real10_decl;
836 break;
837 case 16:
838 pdecl = &m->real16_decl;
839 break;
840 default:
841 gcc_unreachable ();
844 else if (ts->type == BT_COMPLEX)
846 gcc_assert (m->complex_available);
848 switch (ts->kind)
850 case 4:
851 pdecl = &m->complex4_decl;
852 break;
853 case 8:
854 pdecl = &m->complex8_decl;
855 break;
856 case 10:
857 pdecl = &m->complex10_decl;
858 break;
859 case 16:
860 pdecl = &m->complex16_decl;
861 break;
862 default:
863 gcc_unreachable ();
866 else
867 gcc_unreachable ();
869 if (*pdecl)
870 return *pdecl;
872 if (m->libm_name)
874 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
875 if (gfc_real_kinds[n].c_float)
876 snprintf (name, sizeof (name), "%s%s%s",
877 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
878 else if (gfc_real_kinds[n].c_double)
879 snprintf (name, sizeof (name), "%s%s",
880 ts->type == BT_COMPLEX ? "c" : "", m->name);
881 else if (gfc_real_kinds[n].c_long_double)
882 snprintf (name, sizeof (name), "%s%s%s",
883 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
884 else if (gfc_real_kinds[n].c_float128)
885 snprintf (name, sizeof (name), "%s%s%s",
886 ts->type == BT_COMPLEX ? "c" : "", m->name,
887 gfc_real_kinds[n].use_iec_60559 ? "f128" : "q");
888 else
889 gcc_unreachable ();
891 else
893 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
894 ts->type == BT_COMPLEX ? 'c' : 'r',
895 gfc_type_abi_kind (ts));
898 argtypes = NULL;
899 for (actual = expr->value.function.actual; actual; actual = actual->next)
901 type = gfc_typenode_for_spec (&actual->expr->ts);
902 vec_safe_push (argtypes, type);
904 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
905 fndecl = build_decl (input_location,
906 FUNCTION_DECL, get_identifier (name), type);
908 /* Mark the decl as external. */
909 DECL_EXTERNAL (fndecl) = 1;
910 TREE_PUBLIC (fndecl) = 1;
912 /* Mark it __attribute__((const)), if possible. */
913 TREE_READONLY (fndecl) = m->is_constant;
915 rest_of_decl_compilation (fndecl, 1, 0);
917 (*pdecl) = fndecl;
918 return fndecl;
922 /* Convert an intrinsic function into an external or builtin call. */
924 static void
925 gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
927 gfc_intrinsic_map_t *m;
928 tree fndecl;
929 tree rettype;
930 tree *args;
931 unsigned int num_args;
932 gfc_isym_id id;
934 id = expr->value.function.isym->id;
935 /* Find the entry for this function. */
936 for (m = gfc_intrinsic_map;
937 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
939 if (id == m->id)
940 break;
943 if (m->id == GFC_ISYM_NONE)
945 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
946 expr->value.function.name, id);
949 /* Get the decl and generate the call. */
950 num_args = gfc_intrinsic_argument_list_length (expr);
951 args = XALLOCAVEC (tree, num_args);
953 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
954 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
955 rettype = TREE_TYPE (TREE_TYPE (fndecl));
957 fndecl = build_addr (fndecl);
958 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
962 /* If bounds-checking is enabled, create code to verify at runtime that the
963 string lengths for both expressions are the same (needed for e.g. MERGE).
964 If bounds-checking is not enabled, does nothing. */
966 void
967 gfc_trans_same_strlen_check (const char* intr_name, locus* where,
968 tree a, tree b, stmtblock_t* target)
970 tree cond;
971 tree name;
973 /* If bounds-checking is disabled, do nothing. */
974 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
975 return;
977 /* Compare the two string lengths. */
978 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, a, b);
980 /* Output the runtime-check. */
981 name = gfc_build_cstring_const (intr_name);
982 name = gfc_build_addr_expr (pchar_type_node, name);
983 gfc_trans_runtime_check (true, false, cond, target, where,
984 "Unequal character lengths (%ld/%ld) in %s",
985 fold_convert (long_integer_type_node, a),
986 fold_convert (long_integer_type_node, b), name);
990 /* The EXPONENT(X) intrinsic function is translated into
991 int ret;
992 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
993 so that if X is a NaN or infinity, the result is HUGE(0).
996 static void
997 gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
999 tree arg, type, res, tmp, frexp, cond, huge;
1000 int i;
1002 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
1003 expr->value.function.actual->expr->ts.kind);
1005 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
1006 arg = gfc_evaluate_now (arg, &se->pre);
1008 i = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
1009 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_c_int_kind);
1010 cond = build_call_expr_loc (input_location,
1011 builtin_decl_explicit (BUILT_IN_ISFINITE),
1012 1, arg);
1014 res = gfc_create_var (integer_type_node, NULL);
1015 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
1016 gfc_build_addr_expr (NULL_TREE, res));
1017 tmp = fold_build2_loc (input_location, COMPOUND_EXPR, integer_type_node,
1018 tmp, res);
1019 se->expr = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
1020 cond, tmp, huge);
1022 type = gfc_typenode_for_spec (&expr->ts);
1023 se->expr = fold_convert (type, se->expr);
1027 /* Fill in the following structure
1028 struct caf_vector_t {
1029 size_t nvec; // size of the vector
1030 union {
1031 struct {
1032 void *vector;
1033 int kind;
1034 } v;
1035 struct {
1036 ptrdiff_t lower_bound;
1037 ptrdiff_t upper_bound;
1038 ptrdiff_t stride;
1039 } triplet;
1040 } u;
1041 } */
1043 static void
1044 conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
1045 tree lower, tree upper, tree stride,
1046 tree vector, int kind, tree nvec)
1048 tree field, type, tmp;
1050 desc = gfc_build_array_ref (desc, gfc_rank_cst[i], NULL_TREE);
1051 type = TREE_TYPE (desc);
1053 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1054 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1055 desc, field, NULL_TREE);
1056 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), nvec));
1058 /* Access union. */
1059 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1060 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1061 desc, field, NULL_TREE);
1062 type = TREE_TYPE (desc);
1064 /* Access the inner struct. */
1065 field = gfc_advance_chain (TYPE_FIELDS (type), vector != NULL_TREE ? 0 : 1);
1066 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1067 desc, field, NULL_TREE);
1068 type = TREE_TYPE (desc);
1070 if (vector != NULL_TREE)
1072 /* Set vector and kind. */
1073 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1074 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1075 desc, field, NULL_TREE);
1076 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), vector));
1077 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1078 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1079 desc, field, NULL_TREE);
1080 gfc_add_modify (block, tmp, build_int_cst (integer_type_node, kind));
1082 else
1084 /* Set dim.lower/upper/stride. */
1085 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1086 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1087 desc, field, NULL_TREE);
1088 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), lower));
1090 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1091 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1092 desc, field, NULL_TREE);
1093 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), upper));
1095 field = gfc_advance_chain (TYPE_FIELDS (type), 2);
1096 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1097 desc, field, NULL_TREE);
1098 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), stride));
1103 static tree
1104 conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
1106 gfc_se argse;
1107 tree var, lower, upper = NULL_TREE, stride = NULL_TREE, vector, nvec;
1108 tree lbound, ubound, tmp;
1109 int i;
1111 var = gfc_create_var (gfc_get_caf_vector_type (ar->dimen), "vector");
1113 for (i = 0; i < ar->dimen; i++)
1114 switch (ar->dimen_type[i])
1116 case DIMEN_RANGE:
1117 if (ar->end[i])
1119 gfc_init_se (&argse, NULL);
1120 gfc_conv_expr (&argse, ar->end[i]);
1121 gfc_add_block_to_block (block, &argse.pre);
1122 upper = gfc_evaluate_now (argse.expr, block);
1124 else
1125 upper = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1126 if (ar->stride[i])
1128 gfc_init_se (&argse, NULL);
1129 gfc_conv_expr (&argse, ar->stride[i]);
1130 gfc_add_block_to_block (block, &argse.pre);
1131 stride = gfc_evaluate_now (argse.expr, block);
1133 else
1134 stride = gfc_index_one_node;
1136 /* Fall through. */
1137 case DIMEN_ELEMENT:
1138 if (ar->start[i])
1140 gfc_init_se (&argse, NULL);
1141 gfc_conv_expr (&argse, ar->start[i]);
1142 gfc_add_block_to_block (block, &argse.pre);
1143 lower = gfc_evaluate_now (argse.expr, block);
1145 else
1146 lower = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1147 if (ar->dimen_type[i] == DIMEN_ELEMENT)
1149 upper = lower;
1150 stride = gfc_index_one_node;
1152 vector = NULL_TREE;
1153 nvec = size_zero_node;
1154 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1155 vector, 0, nvec);
1156 break;
1158 case DIMEN_VECTOR:
1159 gfc_init_se (&argse, NULL);
1160 argse.descriptor_only = 1;
1161 gfc_conv_expr_descriptor (&argse, ar->start[i]);
1162 gfc_add_block_to_block (block, &argse.pre);
1163 vector = argse.expr;
1164 lbound = gfc_conv_descriptor_lbound_get (vector, gfc_rank_cst[0]);
1165 ubound = gfc_conv_descriptor_ubound_get (vector, gfc_rank_cst[0]);
1166 nvec = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1167 tmp = gfc_conv_descriptor_stride_get (vector, gfc_rank_cst[0]);
1168 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1169 TREE_TYPE (nvec), nvec, tmp);
1170 lower = gfc_index_zero_node;
1171 upper = gfc_index_zero_node;
1172 stride = gfc_index_zero_node;
1173 vector = gfc_conv_descriptor_data_get (vector);
1174 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1175 vector, ar->start[i]->ts.kind, nvec);
1176 break;
1177 default:
1178 gcc_unreachable();
1180 return gfc_build_addr_expr (NULL_TREE, var);
1184 static tree
1185 compute_component_offset (tree field, tree type)
1187 tree tmp;
1188 if (DECL_FIELD_BIT_OFFSET (field) != NULL_TREE
1189 && !integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
1191 tmp = fold_build2 (TRUNC_DIV_EXPR, type,
1192 DECL_FIELD_BIT_OFFSET (field),
1193 bitsize_unit_node);
1194 return fold_build2 (PLUS_EXPR, type, DECL_FIELD_OFFSET (field), tmp);
1196 else
1197 return DECL_FIELD_OFFSET (field);
1201 static tree
1202 conv_expr_ref_to_caf_ref (stmtblock_t *block, gfc_expr *expr)
1204 gfc_ref *ref = expr->ref, *last_comp_ref;
1205 tree caf_ref = NULL_TREE, prev_caf_ref = NULL_TREE, reference_type, tmp, tmp2,
1206 field, last_type, inner_struct, mode, mode_rhs, dim_array, dim, dim_type,
1207 start, end, stride, vector, nvec;
1208 gfc_se se;
1209 bool ref_static_array = false;
1210 tree last_component_ref_tree = NULL_TREE;
1211 int i, last_type_n;
1213 if (expr->symtree)
1215 last_component_ref_tree = expr->symtree->n.sym->backend_decl;
1216 ref_static_array = !expr->symtree->n.sym->attr.allocatable
1217 && !expr->symtree->n.sym->attr.pointer;
1220 /* Prevent uninit-warning. */
1221 reference_type = NULL_TREE;
1223 /* Skip refs upto the first coarray-ref. */
1224 last_comp_ref = NULL;
1225 while (ref && (ref->type != REF_ARRAY || ref->u.ar.codimen == 0))
1227 /* Remember the type of components skipped. */
1228 if (ref->type == REF_COMPONENT)
1229 last_comp_ref = ref;
1230 ref = ref->next;
1232 /* When a component was skipped, get the type information of the last
1233 component ref, else get the type from the symbol. */
1234 if (last_comp_ref)
1236 last_type = gfc_typenode_for_spec (&last_comp_ref->u.c.component->ts);
1237 last_type_n = last_comp_ref->u.c.component->ts.type;
1239 else
1241 last_type = gfc_typenode_for_spec (&expr->symtree->n.sym->ts);
1242 last_type_n = expr->symtree->n.sym->ts.type;
1245 while (ref)
1247 if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0
1248 && ref->u.ar.dimen == 0)
1250 /* Skip pure coindexes. */
1251 ref = ref->next;
1252 continue;
1254 tmp = gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
1255 reference_type = TREE_TYPE (tmp);
1257 if (caf_ref == NULL_TREE)
1258 caf_ref = tmp;
1260 /* Construct the chain of refs. */
1261 if (prev_caf_ref != NULL_TREE)
1263 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1264 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1265 TREE_TYPE (field), prev_caf_ref, field,
1266 NULL_TREE);
1267 gfc_add_modify (block, tmp2, gfc_build_addr_expr (TREE_TYPE (field),
1268 tmp));
1270 prev_caf_ref = tmp;
1272 switch (ref->type)
1274 case REF_COMPONENT:
1275 last_type = gfc_typenode_for_spec (&ref->u.c.component->ts);
1276 last_type_n = ref->u.c.component->ts.type;
1277 /* Set the type of the ref. */
1278 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1279 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1280 TREE_TYPE (field), prev_caf_ref, field,
1281 NULL_TREE);
1282 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1283 GFC_CAF_REF_COMPONENT));
1285 /* Ref the c in union u. */
1286 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1287 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1288 TREE_TYPE (field), prev_caf_ref, field,
1289 NULL_TREE);
1290 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 0);
1291 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1292 TREE_TYPE (field), tmp, field,
1293 NULL_TREE);
1295 /* Set the offset. */
1296 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1297 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1298 TREE_TYPE (field), inner_struct, field,
1299 NULL_TREE);
1300 /* Computing the offset is somewhat harder. The bit_offset has to be
1301 taken into account. When the bit_offset in the field_decl is non-
1302 null, divide it by the bitsize_unit and add it to the regular
1303 offset. */
1304 tmp2 = compute_component_offset (ref->u.c.component->backend_decl,
1305 TREE_TYPE (tmp));
1306 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1308 /* Set caf_token_offset. */
1309 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 1);
1310 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1311 TREE_TYPE (field), inner_struct, field,
1312 NULL_TREE);
1313 if ((ref->u.c.component->attr.allocatable
1314 || ref->u.c.component->attr.pointer)
1315 && ref->u.c.component->attr.dimension)
1317 tree arr_desc_token_offset;
1318 /* Get the token field from the descriptor. */
1319 arr_desc_token_offset = TREE_OPERAND (
1320 gfc_conv_descriptor_token (ref->u.c.component->backend_decl), 1);
1321 arr_desc_token_offset
1322 = compute_component_offset (arr_desc_token_offset,
1323 TREE_TYPE (tmp));
1324 tmp2 = fold_build2_loc (input_location, PLUS_EXPR,
1325 TREE_TYPE (tmp2), tmp2,
1326 arr_desc_token_offset);
1328 else if (ref->u.c.component->caf_token)
1329 tmp2 = compute_component_offset (ref->u.c.component->caf_token,
1330 TREE_TYPE (tmp));
1331 else
1332 tmp2 = integer_zero_node;
1333 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1335 /* Remember whether this ref was to a non-allocatable/non-pointer
1336 component so the next array ref can be tailored correctly. */
1337 ref_static_array = !ref->u.c.component->attr.allocatable
1338 && !ref->u.c.component->attr.pointer;
1339 last_component_ref_tree = ref_static_array
1340 ? ref->u.c.component->backend_decl : NULL_TREE;
1341 break;
1342 case REF_ARRAY:
1343 if (ref_static_array && ref->u.ar.as->type == AS_DEFERRED)
1344 ref_static_array = false;
1345 /* Set the type of the ref. */
1346 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1347 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1348 TREE_TYPE (field), prev_caf_ref, field,
1349 NULL_TREE);
1350 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1351 ref_static_array
1352 ? GFC_CAF_REF_STATIC_ARRAY
1353 : GFC_CAF_REF_ARRAY));
1355 /* Ref the a in union u. */
1356 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1357 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1358 TREE_TYPE (field), prev_caf_ref, field,
1359 NULL_TREE);
1360 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 1);
1361 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1362 TREE_TYPE (field), tmp, field,
1363 NULL_TREE);
1365 /* Set the static_array_type in a for static arrays. */
1366 if (ref_static_array)
1368 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)),
1370 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1371 TREE_TYPE (field), inner_struct, field,
1372 NULL_TREE);
1373 gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (tmp),
1374 last_type_n));
1376 /* Ref the mode in the inner_struct. */
1377 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1378 mode = fold_build3_loc (input_location, COMPONENT_REF,
1379 TREE_TYPE (field), inner_struct, field,
1380 NULL_TREE);
1381 /* Ref the dim in the inner_struct. */
1382 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 2);
1383 dim_array = fold_build3_loc (input_location, COMPONENT_REF,
1384 TREE_TYPE (field), inner_struct, field,
1385 NULL_TREE);
1386 for (i = 0; i < ref->u.ar.dimen; ++i)
1388 /* Ref dim i. */
1389 dim = gfc_build_array_ref (dim_array, gfc_rank_cst[i], NULL_TREE);
1390 dim_type = TREE_TYPE (dim);
1391 mode_rhs = start = end = stride = NULL_TREE;
1392 switch (ref->u.ar.dimen_type[i])
1394 case DIMEN_RANGE:
1395 if (ref->u.ar.end[i])
1397 gfc_init_se (&se, NULL);
1398 gfc_conv_expr (&se, ref->u.ar.end[i]);
1399 gfc_add_block_to_block (block, &se.pre);
1400 if (ref_static_array)
1402 /* Make the index zero-based, when reffing a static
1403 array. */
1404 end = se.expr;
1405 gfc_init_se (&se, NULL);
1406 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1407 gfc_add_block_to_block (block, &se.pre);
1408 se.expr = fold_build2 (MINUS_EXPR,
1409 gfc_array_index_type,
1410 end, fold_convert (
1411 gfc_array_index_type,
1412 se.expr));
1414 end = gfc_evaluate_now (fold_convert (
1415 gfc_array_index_type,
1416 se.expr),
1417 block);
1419 else if (ref_static_array)
1420 end = fold_build2 (MINUS_EXPR,
1421 gfc_array_index_type,
1422 gfc_conv_array_ubound (
1423 last_component_ref_tree, i),
1424 gfc_conv_array_lbound (
1425 last_component_ref_tree, i));
1426 else
1428 end = NULL_TREE;
1429 mode_rhs = build_int_cst (unsigned_char_type_node,
1430 GFC_CAF_ARR_REF_OPEN_END);
1432 if (ref->u.ar.stride[i])
1434 gfc_init_se (&se, NULL);
1435 gfc_conv_expr (&se, ref->u.ar.stride[i]);
1436 gfc_add_block_to_block (block, &se.pre);
1437 stride = gfc_evaluate_now (fold_convert (
1438 gfc_array_index_type,
1439 se.expr),
1440 block);
1441 if (ref_static_array)
1443 /* Make the index zero-based, when reffing a static
1444 array. */
1445 stride = fold_build2 (MULT_EXPR,
1446 gfc_array_index_type,
1447 gfc_conv_array_stride (
1448 last_component_ref_tree,
1450 stride);
1451 gcc_assert (end != NULL_TREE);
1452 /* Multiply with the product of array's stride and
1453 the step of the ref to a virtual upper bound.
1454 We cannot compute the actual upper bound here or
1455 the caflib would compute the extend
1456 incorrectly. */
1457 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1458 end, gfc_conv_array_stride (
1459 last_component_ref_tree,
1460 i));
1461 end = gfc_evaluate_now (end, block);
1462 stride = gfc_evaluate_now (stride, block);
1465 else if (ref_static_array)
1467 stride = gfc_conv_array_stride (last_component_ref_tree,
1469 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1470 end, stride);
1471 end = gfc_evaluate_now (end, block);
1473 else
1474 /* Always set a ref stride of one to make caflib's
1475 handling easier. */
1476 stride = gfc_index_one_node;
1478 /* Fall through. */
1479 case DIMEN_ELEMENT:
1480 if (ref->u.ar.start[i])
1482 gfc_init_se (&se, NULL);
1483 gfc_conv_expr (&se, ref->u.ar.start[i]);
1484 gfc_add_block_to_block (block, &se.pre);
1485 if (ref_static_array)
1487 /* Make the index zero-based, when reffing a static
1488 array. */
1489 start = fold_convert (gfc_array_index_type, se.expr);
1490 gfc_init_se (&se, NULL);
1491 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1492 gfc_add_block_to_block (block, &se.pre);
1493 se.expr = fold_build2 (MINUS_EXPR,
1494 gfc_array_index_type,
1495 start, fold_convert (
1496 gfc_array_index_type,
1497 se.expr));
1498 /* Multiply with the stride. */
1499 se.expr = fold_build2 (MULT_EXPR,
1500 gfc_array_index_type,
1501 se.expr,
1502 gfc_conv_array_stride (
1503 last_component_ref_tree,
1504 i));
1506 start = gfc_evaluate_now (fold_convert (
1507 gfc_array_index_type,
1508 se.expr),
1509 block);
1510 if (mode_rhs == NULL_TREE)
1511 mode_rhs = build_int_cst (unsigned_char_type_node,
1512 ref->u.ar.dimen_type[i]
1513 == DIMEN_ELEMENT
1514 ? GFC_CAF_ARR_REF_SINGLE
1515 : GFC_CAF_ARR_REF_RANGE);
1517 else if (ref_static_array)
1519 start = integer_zero_node;
1520 mode_rhs = build_int_cst (unsigned_char_type_node,
1521 ref->u.ar.start[i] == NULL
1522 ? GFC_CAF_ARR_REF_FULL
1523 : GFC_CAF_ARR_REF_RANGE);
1525 else if (end == NULL_TREE)
1526 mode_rhs = build_int_cst (unsigned_char_type_node,
1527 GFC_CAF_ARR_REF_FULL);
1528 else
1529 mode_rhs = build_int_cst (unsigned_char_type_node,
1530 GFC_CAF_ARR_REF_OPEN_START);
1532 /* Ref the s in dim. */
1533 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 0);
1534 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1535 TREE_TYPE (field), dim, field,
1536 NULL_TREE);
1538 /* Set start in s. */
1539 if (start != NULL_TREE)
1541 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1543 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1544 TREE_TYPE (field), tmp, field,
1545 NULL_TREE);
1546 gfc_add_modify (block, tmp2,
1547 fold_convert (TREE_TYPE (tmp2), start));
1550 /* Set end in s. */
1551 if (end != NULL_TREE)
1553 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1555 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1556 TREE_TYPE (field), tmp, field,
1557 NULL_TREE);
1558 gfc_add_modify (block, tmp2,
1559 fold_convert (TREE_TYPE (tmp2), end));
1562 /* Set end in s. */
1563 if (stride != NULL_TREE)
1565 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1567 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1568 TREE_TYPE (field), tmp, field,
1569 NULL_TREE);
1570 gfc_add_modify (block, tmp2,
1571 fold_convert (TREE_TYPE (tmp2), stride));
1573 break;
1574 case DIMEN_VECTOR:
1575 /* TODO: In case of static array. */
1576 gcc_assert (!ref_static_array);
1577 mode_rhs = build_int_cst (unsigned_char_type_node,
1578 GFC_CAF_ARR_REF_VECTOR);
1579 gfc_init_se (&se, NULL);
1580 se.descriptor_only = 1;
1581 gfc_conv_expr_descriptor (&se, ref->u.ar.start[i]);
1582 gfc_add_block_to_block (block, &se.pre);
1583 vector = se.expr;
1584 tmp = gfc_conv_descriptor_lbound_get (vector,
1585 gfc_rank_cst[0]);
1586 tmp2 = gfc_conv_descriptor_ubound_get (vector,
1587 gfc_rank_cst[0]);
1588 nvec = gfc_conv_array_extent_dim (tmp, tmp2, NULL);
1589 tmp = gfc_conv_descriptor_stride_get (vector,
1590 gfc_rank_cst[0]);
1591 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1592 TREE_TYPE (nvec), nvec, tmp);
1593 vector = gfc_conv_descriptor_data_get (vector);
1595 /* Ref the v in dim. */
1596 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 1);
1597 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1598 TREE_TYPE (field), dim, field,
1599 NULL_TREE);
1601 /* Set vector in v. */
1602 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 0);
1603 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1604 TREE_TYPE (field), tmp, field,
1605 NULL_TREE);
1606 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1607 vector));
1609 /* Set nvec in v. */
1610 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 1);
1611 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1612 TREE_TYPE (field), tmp, field,
1613 NULL_TREE);
1614 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1615 nvec));
1617 /* Set kind in v. */
1618 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 2);
1619 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1620 TREE_TYPE (field), tmp, field,
1621 NULL_TREE);
1622 gfc_add_modify (block, tmp2, build_int_cst (integer_type_node,
1623 ref->u.ar.start[i]->ts.kind));
1624 break;
1625 default:
1626 gcc_unreachable ();
1628 /* Set the mode for dim i. */
1629 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1630 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp),
1631 mode_rhs));
1634 /* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
1635 if (i < GFC_MAX_DIMENSIONS)
1637 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1638 gfc_add_modify (block, tmp,
1639 build_int_cst (unsigned_char_type_node,
1640 GFC_CAF_ARR_REF_NONE));
1642 break;
1643 default:
1644 gcc_unreachable ();
1647 /* Set the size of the current type. */
1648 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 2);
1649 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1650 prev_caf_ref, field, NULL_TREE);
1651 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1652 TYPE_SIZE_UNIT (last_type)));
1654 ref = ref->next;
1657 if (prev_caf_ref != NULL_TREE)
1659 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1660 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1661 prev_caf_ref, field, NULL_TREE);
1662 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1663 null_pointer_node));
1665 return caf_ref != NULL_TREE ? gfc_build_addr_expr (NULL_TREE, caf_ref)
1666 : NULL_TREE;
1669 /* Get data from a remote coarray. */
1671 static void
1672 gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
1673 tree may_require_tmp, bool may_realloc,
1674 symbol_attribute *caf_attr)
1676 gfc_expr *array_expr, *tmp_stat;
1677 gfc_se argse;
1678 tree caf_decl, token, offset, image_index, tmp;
1679 tree res_var, dst_var, type, kind, vec, stat;
1680 tree caf_reference;
1681 symbol_attribute caf_attr_store;
1683 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1685 if (se->ss && se->ss->info->useflags)
1687 /* Access the previously obtained result. */
1688 gfc_conv_tmp_array_ref (se);
1689 return;
1692 /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1693 array_expr = (lhs == NULL_TREE) ? expr->value.function.actual->expr : expr;
1694 type = gfc_typenode_for_spec (&array_expr->ts);
1696 if (caf_attr == NULL)
1698 caf_attr_store = gfc_caf_attr (array_expr);
1699 caf_attr = &caf_attr_store;
1702 res_var = lhs;
1703 dst_var = lhs;
1705 vec = null_pointer_node;
1706 tmp_stat = gfc_find_stat_co (expr);
1708 if (tmp_stat)
1710 gfc_se stat_se;
1711 gfc_init_se (&stat_se, NULL);
1712 gfc_conv_expr_reference (&stat_se, tmp_stat);
1713 stat = stat_se.expr;
1714 gfc_add_block_to_block (&se->pre, &stat_se.pre);
1715 gfc_add_block_to_block (&se->post, &stat_se.post);
1717 else
1718 stat = null_pointer_node;
1720 /* Only use the new get_by_ref () where it is necessary. I.e., when the lhs
1721 is reallocatable or the right-hand side has allocatable components. */
1722 if (caf_attr->alloc_comp || caf_attr->pointer_comp || may_realloc)
1724 /* Get using caf_get_by_ref. */
1725 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, array_expr);
1727 if (caf_reference != NULL_TREE)
1729 if (lhs == NULL_TREE)
1731 if (array_expr->ts.type == BT_CHARACTER)
1732 gfc_init_se (&argse, NULL);
1733 if (array_expr->rank == 0)
1735 symbol_attribute attr;
1736 gfc_clear_attr (&attr);
1737 if (array_expr->ts.type == BT_CHARACTER)
1739 res_var = gfc_conv_string_tmp (se,
1740 build_pointer_type (type),
1741 array_expr->ts.u.cl->backend_decl);
1742 argse.string_length = array_expr->ts.u.cl->backend_decl;
1744 else
1745 res_var = gfc_create_var (type, "caf_res");
1746 dst_var = gfc_conv_scalar_to_descriptor (se, res_var, attr);
1747 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1749 else
1751 /* Create temporary. */
1752 if (array_expr->ts.type == BT_CHARACTER)
1753 gfc_conv_expr_descriptor (&argse, array_expr);
1754 may_realloc = gfc_trans_create_temp_array (&se->pre,
1755 &se->post,
1756 se->ss, type,
1757 NULL_TREE, false,
1758 false, false,
1759 &array_expr->where)
1760 == NULL_TREE;
1761 res_var = se->ss->info->data.array.descriptor;
1762 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1763 if (may_realloc)
1765 tmp = gfc_conv_descriptor_data_get (res_var);
1766 tmp = gfc_deallocate_with_status (tmp, NULL_TREE,
1767 NULL_TREE, NULL_TREE,
1768 NULL_TREE, true,
1769 NULL,
1770 GFC_CAF_COARRAY_NOCOARRAY);
1771 gfc_add_expr_to_block (&se->post, tmp);
1776 kind = build_int_cst (integer_type_node, expr->ts.kind);
1777 if (lhs_kind == NULL_TREE)
1778 lhs_kind = kind;
1780 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1781 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1782 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1783 image_index = gfc_caf_get_image_index (&se->pre, array_expr,
1784 caf_decl);
1785 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
1786 array_expr);
1788 /* No overlap possible as we have generated a temporary. */
1789 if (lhs == NULL_TREE)
1790 may_require_tmp = boolean_false_node;
1792 /* It guarantees memory consistency within the same segment. */
1793 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1794 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1795 gfc_build_string_const (1, ""), NULL_TREE,
1796 NULL_TREE, tree_cons (NULL_TREE, tmp, NULL_TREE),
1797 NULL_TREE);
1798 ASM_VOLATILE_P (tmp) = 1;
1799 gfc_add_expr_to_block (&se->pre, tmp);
1801 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get_by_ref,
1802 10, token, image_index, dst_var,
1803 caf_reference, lhs_kind, kind,
1804 may_require_tmp,
1805 may_realloc ? boolean_true_node :
1806 boolean_false_node,
1807 stat, build_int_cst (integer_type_node,
1808 array_expr->ts.type));
1810 gfc_add_expr_to_block (&se->pre, tmp);
1812 if (se->ss)
1813 gfc_advance_se_ss_chain (se);
1815 se->expr = res_var;
1816 if (array_expr->ts.type == BT_CHARACTER)
1817 se->string_length = argse.string_length;
1819 return;
1823 gfc_init_se (&argse, NULL);
1824 if (array_expr->rank == 0)
1826 symbol_attribute attr;
1828 gfc_clear_attr (&attr);
1829 gfc_conv_expr (&argse, array_expr);
1831 if (lhs == NULL_TREE)
1833 gfc_clear_attr (&attr);
1834 if (array_expr->ts.type == BT_CHARACTER)
1835 res_var = gfc_conv_string_tmp (se, build_pointer_type (type),
1836 argse.string_length);
1837 else
1838 res_var = gfc_create_var (type, "caf_res");
1839 dst_var = gfc_conv_scalar_to_descriptor (&argse, res_var, attr);
1840 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1842 argse.expr = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
1843 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1845 else
1847 /* If has_vector, pass descriptor for whole array and the
1848 vector bounds separately. */
1849 gfc_array_ref *ar, ar2;
1850 bool has_vector = false;
1852 if (gfc_is_coindexed (expr) && gfc_has_vector_subscript (expr))
1854 has_vector = true;
1855 ar = gfc_find_array_ref (expr);
1856 ar2 = *ar;
1857 memset (ar, '\0', sizeof (*ar));
1858 ar->as = ar2.as;
1859 ar->type = AR_FULL;
1861 // TODO: Check whether argse.want_coarray = 1 can help with the below.
1862 gfc_conv_expr_descriptor (&argse, array_expr);
1863 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1864 has the wrong type if component references are done. */
1865 gfc_add_modify (&argse.pre, gfc_conv_descriptor_dtype (argse.expr),
1866 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1867 : array_expr->rank,
1868 type));
1869 if (has_vector)
1871 vec = conv_caf_vector_subscript (&argse.pre, argse.expr, &ar2);
1872 *ar = ar2;
1875 if (lhs == NULL_TREE)
1877 /* Create temporary. */
1878 for (int n = 0; n < se->ss->loop->dimen; n++)
1879 if (se->loop->to[n] == NULL_TREE)
1881 se->loop->from[n] = gfc_conv_descriptor_lbound_get (argse.expr,
1882 gfc_rank_cst[n]);
1883 se->loop->to[n] = gfc_conv_descriptor_ubound_get (argse.expr,
1884 gfc_rank_cst[n]);
1886 gfc_trans_create_temp_array (&argse.pre, &argse.post, se->ss, type,
1887 NULL_TREE, false, true, false,
1888 &array_expr->where);
1889 res_var = se->ss->info->data.array.descriptor;
1890 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1892 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1895 kind = build_int_cst (integer_type_node, expr->ts.kind);
1896 if (lhs_kind == NULL_TREE)
1897 lhs_kind = kind;
1899 gfc_add_block_to_block (&se->pre, &argse.pre);
1900 gfc_add_block_to_block (&se->post, &argse.post);
1902 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1903 if (POINTER_TYPE_P (TREE_TYPE (caf_decl)))
1904 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1905 image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
1906 gfc_get_caf_token_offset (se, &token, &offset, caf_decl, argse.expr,
1907 array_expr);
1909 /* No overlap possible as we have generated a temporary. */
1910 if (lhs == NULL_TREE)
1911 may_require_tmp = boolean_false_node;
1913 /* It guarantees memory consistency within the same segment. */
1914 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1915 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1916 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1917 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1918 ASM_VOLATILE_P (tmp) = 1;
1919 gfc_add_expr_to_block (&se->pre, tmp);
1921 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 10,
1922 token, offset, image_index, argse.expr, vec,
1923 dst_var, kind, lhs_kind, may_require_tmp, stat);
1925 gfc_add_expr_to_block (&se->pre, tmp);
1927 if (se->ss)
1928 gfc_advance_se_ss_chain (se);
1930 se->expr = res_var;
1931 if (array_expr->ts.type == BT_CHARACTER)
1932 se->string_length = argse.string_length;
1936 /* Send data to a remote coarray. */
1938 static tree
1939 conv_caf_send (gfc_code *code) {
1940 gfc_expr *lhs_expr, *rhs_expr, *tmp_stat, *tmp_team;
1941 gfc_se lhs_se, rhs_se;
1942 stmtblock_t block;
1943 tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
1944 tree may_require_tmp, src_stat, dst_stat, dst_team;
1945 tree lhs_type = NULL_TREE;
1946 tree vec = null_pointer_node, rhs_vec = null_pointer_node;
1947 symbol_attribute lhs_caf_attr, rhs_caf_attr;
1948 bool lhs_is_coindexed, rhs_is_coindexed;
1950 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1952 lhs_expr = code->ext.actual->expr;
1953 rhs_expr = code->ext.actual->next->expr;
1954 lhs_is_coindexed = gfc_is_coindexed (lhs_expr);
1955 rhs_is_coindexed = gfc_is_coindexed (rhs_expr);
1956 may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, true) == 0
1957 ? boolean_false_node : boolean_true_node;
1958 gfc_init_block (&block);
1960 lhs_caf_attr = gfc_caf_attr (lhs_expr);
1961 rhs_caf_attr = gfc_caf_attr (rhs_expr);
1962 src_stat = dst_stat = null_pointer_node;
1963 dst_team = null_pointer_node;
1965 /* LHS. */
1966 gfc_init_se (&lhs_se, NULL);
1967 if (lhs_expr->rank == 0)
1969 if (lhs_expr->ts.type == BT_CHARACTER && lhs_expr->ts.deferred)
1971 lhs_se.expr = gfc_get_tree_for_caf_expr (lhs_expr);
1972 if (!POINTER_TYPE_P (TREE_TYPE (lhs_se.expr)))
1973 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1975 else
1977 symbol_attribute attr;
1978 gfc_clear_attr (&attr);
1979 gfc_conv_expr (&lhs_se, lhs_expr);
1980 lhs_type = TREE_TYPE (lhs_se.expr);
1981 lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr,
1982 attr);
1983 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1986 else if ((lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
1987 && lhs_caf_attr.codimension)
1989 lhs_se.want_pointer = 1;
1990 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1991 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1992 has the wrong type if component references are done. */
1993 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1994 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1995 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1996 gfc_get_dtype_rank_type (
1997 gfc_has_vector_subscript (lhs_expr)
1998 ? gfc_find_array_ref (lhs_expr)->dimen
1999 : lhs_expr->rank,
2000 lhs_type));
2002 else
2004 bool has_vector = gfc_has_vector_subscript (lhs_expr);
2006 if (lhs_is_coindexed || !has_vector)
2008 /* If has_vector, pass descriptor for whole array and the
2009 vector bounds separately. */
2010 gfc_array_ref *ar, ar2;
2011 bool has_tmp_lhs_array = false;
2012 if (has_vector)
2014 has_tmp_lhs_array = true;
2015 ar = gfc_find_array_ref (lhs_expr);
2016 ar2 = *ar;
2017 memset (ar, '\0', sizeof (*ar));
2018 ar->as = ar2.as;
2019 ar->type = AR_FULL;
2021 lhs_se.want_pointer = 1;
2022 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
2023 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but
2024 that has the wrong type if component references are done. */
2025 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2026 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
2027 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2028 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2029 : lhs_expr->rank,
2030 lhs_type));
2031 if (has_tmp_lhs_array)
2033 vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
2034 *ar = ar2;
2037 else if (rhs_is_coindexed)
2039 /* Special casing for arr1 ([...]) = arr2[...], i.e. caf_get to
2040 indexed array expression. This is rewritten to:
2042 tmp_array = arr2[...]
2043 arr1 ([...]) = tmp_array
2045 because using the standard gfc_conv_expr (lhs_expr) did the
2046 assignment with lhs and rhs exchanged. */
2048 gfc_ss *lss_for_tmparray, *lss_real;
2049 gfc_loopinfo loop;
2050 gfc_se se;
2051 stmtblock_t body;
2052 tree tmparr_desc, src;
2053 tree index = gfc_index_zero_node;
2054 tree stride = gfc_index_zero_node;
2055 int n;
2057 /* Walk both sides of the assignment, once to get the shape of the
2058 temporary array to create right. */
2059 lss_for_tmparray = gfc_walk_expr (lhs_expr);
2060 /* And a second time to be able to create an assignment of the
2061 temporary to the lhs_expr. gfc_trans_create_temp_array replaces
2062 the tree in the descriptor with the one for the temporary
2063 array. */
2064 lss_real = gfc_walk_expr (lhs_expr);
2065 gfc_init_loopinfo (&loop);
2066 gfc_add_ss_to_loop (&loop, lss_for_tmparray);
2067 gfc_add_ss_to_loop (&loop, lss_real);
2068 gfc_conv_ss_startstride (&loop);
2069 gfc_conv_loop_setup (&loop, &lhs_expr->where);
2070 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2071 gfc_trans_create_temp_array (&lhs_se.pre, &lhs_se.post,
2072 lss_for_tmparray, lhs_type, NULL_TREE,
2073 false, true, false,
2074 &lhs_expr->where);
2075 tmparr_desc = lss_for_tmparray->info->data.array.descriptor;
2076 gfc_start_scalarized_body (&loop, &body);
2077 gfc_init_se (&se, NULL);
2078 gfc_copy_loopinfo_to_se (&se, &loop);
2079 se.ss = lss_real;
2080 gfc_conv_expr (&se, lhs_expr);
2081 gfc_add_block_to_block (&body, &se.pre);
2083 /* Walk over all indexes of the loop. */
2084 for (n = loop.dimen - 1; n > 0; --n)
2086 tmp = loop.loopvar[n];
2087 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2088 gfc_array_index_type, tmp, loop.from[n]);
2089 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2090 gfc_array_index_type, tmp, index);
2092 stride = fold_build2_loc (input_location, MINUS_EXPR,
2093 gfc_array_index_type,
2094 loop.to[n - 1], loop.from[n - 1]);
2095 stride = fold_build2_loc (input_location, PLUS_EXPR,
2096 gfc_array_index_type,
2097 stride, gfc_index_one_node);
2099 index = fold_build2_loc (input_location, MULT_EXPR,
2100 gfc_array_index_type, tmp, stride);
2103 index = fold_build2_loc (input_location, MINUS_EXPR,
2104 gfc_array_index_type,
2105 index, loop.from[0]);
2107 index = fold_build2_loc (input_location, PLUS_EXPR,
2108 gfc_array_index_type,
2109 loop.loopvar[0], index);
2111 src = build_fold_indirect_ref (gfc_conv_array_data (tmparr_desc));
2112 src = gfc_build_array_ref (src, index, NULL);
2113 /* Now create the assignment of lhs_expr = tmp_array. */
2114 gfc_add_modify (&body, se.expr, src);
2115 gfc_add_block_to_block (&body, &se.post);
2116 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, tmparr_desc);
2117 gfc_trans_scalarizing_loops (&loop, &body);
2118 gfc_add_block_to_block (&loop.pre, &loop.post);
2119 gfc_add_expr_to_block (&lhs_se.post, gfc_finish_block (&loop.pre));
2120 gfc_free_ss (lss_for_tmparray);
2121 gfc_free_ss (lss_real);
2125 lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
2127 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
2128 temporary and a loop. */
2129 if (!lhs_is_coindexed && rhs_is_coindexed
2130 && (!lhs_caf_attr.codimension
2131 || !(lhs_expr->rank > 0
2132 && (lhs_caf_attr.allocatable || lhs_caf_attr.pointer))))
2134 bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
2135 gfc_init_se (&rhs_se, NULL);
2136 if (lhs_expr->rank == 0 && lhs_caf_attr.allocatable)
2138 gfc_se scal_se;
2139 gfc_init_se (&scal_se, NULL);
2140 scal_se.want_pointer = 1;
2141 gfc_conv_expr (&scal_se, lhs_expr);
2142 /* Ensure scalar on lhs is allocated. */
2143 gfc_add_block_to_block (&block, &scal_se.pre);
2145 gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
2146 TYPE_SIZE_UNIT (
2147 gfc_typenode_for_spec (&lhs_expr->ts)),
2148 NULL_TREE);
2149 tmp = fold_build2 (EQ_EXPR, logical_type_node, scal_se.expr,
2150 null_pointer_node);
2151 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2152 tmp, gfc_finish_block (&scal_se.pre),
2153 build_empty_stmt (input_location));
2154 gfc_add_expr_to_block (&block, tmp);
2156 else
2157 lhs_may_realloc = lhs_may_realloc
2158 && gfc_full_array_ref_p (lhs_expr->ref, NULL);
2159 gfc_add_block_to_block (&block, &lhs_se.pre);
2160 gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
2161 may_require_tmp, lhs_may_realloc,
2162 &rhs_caf_attr);
2163 gfc_add_block_to_block (&block, &rhs_se.pre);
2164 gfc_add_block_to_block (&block, &rhs_se.post);
2165 gfc_add_block_to_block (&block, &lhs_se.post);
2166 return gfc_finish_block (&block);
2169 gfc_add_block_to_block (&block, &lhs_se.pre);
2171 /* Obtain token, offset and image index for the LHS. */
2172 caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
2173 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2174 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2175 image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
2176 tmp = lhs_se.expr;
2177 if (lhs_caf_attr.alloc_comp)
2178 gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL_TREE,
2179 NULL);
2180 else
2181 gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
2182 lhs_expr);
2183 lhs_se.expr = tmp;
2185 /* RHS. */
2186 gfc_init_se (&rhs_se, NULL);
2187 if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
2188 && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
2189 rhs_expr = rhs_expr->value.function.actual->expr;
2190 if (rhs_expr->rank == 0)
2192 symbol_attribute attr;
2193 gfc_clear_attr (&attr);
2194 gfc_conv_expr (&rhs_se, rhs_expr);
2195 rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
2196 rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
2198 else if ((rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2199 && rhs_caf_attr.codimension)
2201 tree tmp2;
2202 rhs_se.want_pointer = 1;
2203 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2204 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2205 has the wrong type if component references are done. */
2206 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2207 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2208 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2209 gfc_get_dtype_rank_type (
2210 gfc_has_vector_subscript (rhs_expr)
2211 ? gfc_find_array_ref (rhs_expr)->dimen
2212 : rhs_expr->rank,
2213 tmp2));
2215 else
2217 /* If has_vector, pass descriptor for whole array and the
2218 vector bounds separately. */
2219 gfc_array_ref *ar, ar2;
2220 bool has_vector = false;
2221 tree tmp2;
2223 if (rhs_is_coindexed && gfc_has_vector_subscript (rhs_expr))
2225 has_vector = true;
2226 ar = gfc_find_array_ref (rhs_expr);
2227 ar2 = *ar;
2228 memset (ar, '\0', sizeof (*ar));
2229 ar->as = ar2.as;
2230 ar->type = AR_FULL;
2232 rhs_se.want_pointer = 1;
2233 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2234 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2235 has the wrong type if component references are done. */
2236 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2237 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2238 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2239 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2240 : rhs_expr->rank,
2241 tmp2));
2242 if (has_vector)
2244 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
2245 *ar = ar2;
2249 gfc_add_block_to_block (&block, &rhs_se.pre);
2251 rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
2253 tmp_stat = gfc_find_stat_co (lhs_expr);
2255 if (tmp_stat)
2257 gfc_se stat_se;
2258 gfc_init_se (&stat_se, NULL);
2259 gfc_conv_expr_reference (&stat_se, tmp_stat);
2260 dst_stat = stat_se.expr;
2261 gfc_add_block_to_block (&block, &stat_se.pre);
2262 gfc_add_block_to_block (&block, &stat_se.post);
2265 tmp_team = gfc_find_team_co (lhs_expr);
2267 if (tmp_team)
2269 gfc_se team_se;
2270 gfc_init_se (&team_se, NULL);
2271 gfc_conv_expr_reference (&team_se, tmp_team);
2272 dst_team = team_se.expr;
2273 gfc_add_block_to_block (&block, &team_se.pre);
2274 gfc_add_block_to_block (&block, &team_se.post);
2277 if (!rhs_is_coindexed)
2279 if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
2281 tree reference, dst_realloc;
2282 reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2283 dst_realloc = lhs_caf_attr.allocatable ? boolean_true_node
2284 : boolean_false_node;
2285 tmp = build_call_expr_loc (input_location,
2286 gfor_fndecl_caf_send_by_ref,
2287 10, token, image_index, rhs_se.expr,
2288 reference, lhs_kind, rhs_kind,
2289 may_require_tmp, dst_realloc, src_stat,
2290 build_int_cst (integer_type_node,
2291 lhs_expr->ts.type));
2293 else
2294 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 11,
2295 token, offset, image_index, lhs_se.expr, vec,
2296 rhs_se.expr, lhs_kind, rhs_kind,
2297 may_require_tmp, src_stat, dst_team);
2299 else
2301 tree rhs_token, rhs_offset, rhs_image_index;
2303 /* It guarantees memory consistency within the same segment. */
2304 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2305 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2306 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2307 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2308 ASM_VOLATILE_P (tmp) = 1;
2309 gfc_add_expr_to_block (&block, tmp);
2311 caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
2312 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2313 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2314 rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
2315 tmp = rhs_se.expr;
2316 if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2318 tmp_stat = gfc_find_stat_co (lhs_expr);
2320 if (tmp_stat)
2322 gfc_se stat_se;
2323 gfc_init_se (&stat_se, NULL);
2324 gfc_conv_expr_reference (&stat_se, tmp_stat);
2325 src_stat = stat_se.expr;
2326 gfc_add_block_to_block (&block, &stat_se.pre);
2327 gfc_add_block_to_block (&block, &stat_se.post);
2330 gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL, caf_decl,
2331 NULL_TREE, NULL);
2332 tree lhs_reference, rhs_reference;
2333 lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2334 rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
2335 tmp = build_call_expr_loc (input_location,
2336 gfor_fndecl_caf_sendget_by_ref, 13,
2337 token, image_index, lhs_reference,
2338 rhs_token, rhs_image_index, rhs_reference,
2339 lhs_kind, rhs_kind, may_require_tmp,
2340 dst_stat, src_stat,
2341 build_int_cst (integer_type_node,
2342 lhs_expr->ts.type),
2343 build_int_cst (integer_type_node,
2344 rhs_expr->ts.type));
2346 else
2348 gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
2349 tmp, rhs_expr);
2350 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
2351 14, token, offset, image_index,
2352 lhs_se.expr, vec, rhs_token, rhs_offset,
2353 rhs_image_index, tmp, rhs_vec, lhs_kind,
2354 rhs_kind, may_require_tmp, src_stat);
2357 gfc_add_expr_to_block (&block, tmp);
2358 gfc_add_block_to_block (&block, &lhs_se.post);
2359 gfc_add_block_to_block (&block, &rhs_se.post);
2361 /* It guarantees memory consistency within the same segment. */
2362 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2363 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2364 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2365 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2366 ASM_VOLATILE_P (tmp) = 1;
2367 gfc_add_expr_to_block (&block, tmp);
2369 return gfc_finish_block (&block);
2373 static void
2374 trans_this_image (gfc_se * se, gfc_expr *expr)
2376 stmtblock_t loop;
2377 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
2378 lbound, ubound, extent, ml;
2379 gfc_se argse;
2380 int rank, corank;
2381 gfc_expr *distance = expr->value.function.actual->next->next->expr;
2383 if (expr->value.function.actual->expr
2384 && !gfc_is_coarray (expr->value.function.actual->expr))
2385 distance = expr->value.function.actual->expr;
2387 /* The case -fcoarray=single is handled elsewhere. */
2388 gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
2390 /* Argument-free version: THIS_IMAGE(). */
2391 if (distance || expr->value.function.actual->expr == NULL)
2393 if (distance)
2395 gfc_init_se (&argse, NULL);
2396 gfc_conv_expr_val (&argse, distance);
2397 gfc_add_block_to_block (&se->pre, &argse.pre);
2398 gfc_add_block_to_block (&se->post, &argse.post);
2399 tmp = fold_convert (integer_type_node, argse.expr);
2401 else
2402 tmp = integer_zero_node;
2403 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2404 tmp);
2405 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2406 tmp);
2407 return;
2410 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2412 type = gfc_get_int_type (gfc_default_integer_kind);
2413 corank = expr->value.function.actual->expr->corank;
2414 rank = expr->value.function.actual->expr->rank;
2416 /* Obtain the descriptor of the COARRAY. */
2417 gfc_init_se (&argse, NULL);
2418 argse.want_coarray = 1;
2419 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2420 gfc_add_block_to_block (&se->pre, &argse.pre);
2421 gfc_add_block_to_block (&se->post, &argse.post);
2422 desc = argse.expr;
2424 if (se->ss)
2426 /* Create an implicit second parameter from the loop variable. */
2427 gcc_assert (!expr->value.function.actual->next->expr);
2428 gcc_assert (corank > 0);
2429 gcc_assert (se->loop->dimen == 1);
2430 gcc_assert (se->ss->info->expr == expr);
2432 dim_arg = se->loop->loopvar[0];
2433 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
2434 gfc_array_index_type, dim_arg,
2435 build_int_cst (TREE_TYPE (dim_arg), 1));
2436 gfc_advance_se_ss_chain (se);
2438 else
2440 /* Use the passed DIM= argument. */
2441 gcc_assert (expr->value.function.actual->next->expr);
2442 gfc_init_se (&argse, NULL);
2443 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
2444 gfc_array_index_type);
2445 gfc_add_block_to_block (&se->pre, &argse.pre);
2446 dim_arg = argse.expr;
2448 if (INTEGER_CST_P (dim_arg))
2450 if (wi::ltu_p (wi::to_wide (dim_arg), 1)
2451 || wi::gtu_p (wi::to_wide (dim_arg),
2452 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2453 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2454 "dimension index", expr->value.function.isym->name,
2455 &expr->where);
2457 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2459 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
2460 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2461 dim_arg,
2462 build_int_cst (TREE_TYPE (dim_arg), 1));
2463 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2464 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2465 dim_arg, tmp);
2466 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2467 logical_type_node, cond, tmp);
2468 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2469 gfc_msg_fault);
2473 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2474 one always has a dim_arg argument.
2476 m = this_image() - 1
2477 if (corank == 1)
2479 sub(1) = m + lcobound(corank)
2480 return;
2482 i = rank
2483 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2484 for (;;)
2486 extent = gfc_extent(i)
2487 ml = m
2488 m = m/extent
2489 if (i >= min_var)
2490 goto exit_label
2493 exit_label:
2494 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2495 : m + lcobound(corank)
2498 /* this_image () - 1. */
2499 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2500 integer_zero_node);
2501 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
2502 fold_convert (type, tmp), build_int_cst (type, 1));
2503 if (corank == 1)
2505 /* sub(1) = m + lcobound(corank). */
2506 lbound = gfc_conv_descriptor_lbound_get (desc,
2507 build_int_cst (TREE_TYPE (gfc_array_index_type),
2508 corank+rank-1));
2509 lbound = fold_convert (type, lbound);
2510 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2512 se->expr = tmp;
2513 return;
2516 m = gfc_create_var (type, NULL);
2517 ml = gfc_create_var (type, NULL);
2518 loop_var = gfc_create_var (integer_type_node, NULL);
2519 min_var = gfc_create_var (integer_type_node, NULL);
2521 /* m = this_image () - 1. */
2522 gfc_add_modify (&se->pre, m, tmp);
2524 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2525 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2526 fold_convert (integer_type_node, dim_arg),
2527 build_int_cst (integer_type_node, rank - 1));
2528 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
2529 build_int_cst (integer_type_node, rank + corank - 2),
2530 tmp);
2531 gfc_add_modify (&se->pre, min_var, tmp);
2533 /* i = rank. */
2534 tmp = build_int_cst (integer_type_node, rank);
2535 gfc_add_modify (&se->pre, loop_var, tmp);
2537 exit_label = gfc_build_label_decl (NULL_TREE);
2538 TREE_USED (exit_label) = 1;
2540 /* Loop body. */
2541 gfc_init_block (&loop);
2543 /* ml = m. */
2544 gfc_add_modify (&loop, ml, m);
2546 /* extent = ... */
2547 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
2548 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
2549 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2550 extent = fold_convert (type, extent);
2552 /* m = m/extent. */
2553 gfc_add_modify (&loop, m,
2554 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
2555 m, extent));
2557 /* Exit condition: if (i >= min_var) goto exit_label. */
2558 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, loop_var,
2559 min_var);
2560 tmp = build1_v (GOTO_EXPR, exit_label);
2561 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
2562 build_empty_stmt (input_location));
2563 gfc_add_expr_to_block (&loop, tmp);
2565 /* Increment loop variable: i++. */
2566 gfc_add_modify (&loop, loop_var,
2567 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2568 loop_var,
2569 integer_one_node));
2571 /* Making the loop... actually loop! */
2572 tmp = gfc_finish_block (&loop);
2573 tmp = build1_v (LOOP_EXPR, tmp);
2574 gfc_add_expr_to_block (&se->pre, tmp);
2576 /* The exit label. */
2577 tmp = build1_v (LABEL_EXPR, exit_label);
2578 gfc_add_expr_to_block (&se->pre, tmp);
2580 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2581 : m + lcobound(corank) */
2583 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, dim_arg,
2584 build_int_cst (TREE_TYPE (dim_arg), corank));
2586 lbound = gfc_conv_descriptor_lbound_get (desc,
2587 fold_build2_loc (input_location, PLUS_EXPR,
2588 gfc_array_index_type, dim_arg,
2589 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
2590 lbound = fold_convert (type, lbound);
2592 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
2593 fold_build2_loc (input_location, MULT_EXPR, type,
2594 m, extent));
2595 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2597 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
2598 fold_build2_loc (input_location, PLUS_EXPR, type,
2599 m, lbound));
2603 /* Convert a call to image_status. */
2605 static void
2606 conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
2608 unsigned int num_args;
2609 tree *args, tmp;
2611 num_args = gfc_intrinsic_argument_list_length (expr);
2612 args = XALLOCAVEC (tree, num_args);
2613 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2614 /* In args[0] the number of the image the status is desired for has to be
2615 given. */
2617 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2619 tree arg;
2620 arg = gfc_evaluate_now (args[0], &se->pre);
2621 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2622 fold_convert (integer_type_node, arg),
2623 integer_one_node);
2624 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2625 tmp, integer_zero_node,
2626 build_int_cst (integer_type_node,
2627 GFC_STAT_STOPPED_IMAGE));
2629 else if (flag_coarray == GFC_FCOARRAY_LIB)
2630 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
2631 args[0], build_int_cst (integer_type_node, -1));
2632 else
2633 gcc_unreachable ();
2635 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2638 static void
2639 conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
2641 unsigned int num_args;
2643 tree *args, tmp;
2645 num_args = gfc_intrinsic_argument_list_length (expr);
2646 args = XALLOCAVEC (tree, num_args);
2647 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2649 if (flag_coarray ==
2650 GFC_FCOARRAY_SINGLE && expr->value.function.actual->expr)
2652 tree arg;
2654 arg = gfc_evaluate_now (args[0], &se->pre);
2655 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2656 fold_convert (integer_type_node, arg),
2657 integer_one_node);
2658 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2659 tmp, integer_zero_node,
2660 build_int_cst (integer_type_node,
2661 GFC_STAT_STOPPED_IMAGE));
2663 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
2665 // the value -1 represents that no team has been created yet
2666 tmp = build_int_cst (integer_type_node, -1);
2668 else if (flag_coarray == GFC_FCOARRAY_LIB && expr->value.function.actual->expr)
2669 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2670 args[0], build_int_cst (integer_type_node, -1));
2671 else if (flag_coarray == GFC_FCOARRAY_LIB)
2672 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2673 integer_zero_node, build_int_cst (integer_type_node, -1));
2674 else
2675 gcc_unreachable ();
2677 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2681 static void
2682 trans_image_index (gfc_se * se, gfc_expr *expr)
2684 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
2685 tmp, invalid_bound;
2686 gfc_se argse, subse;
2687 int rank, corank, codim;
2689 type = gfc_get_int_type (gfc_default_integer_kind);
2690 corank = expr->value.function.actual->expr->corank;
2691 rank = expr->value.function.actual->expr->rank;
2693 /* Obtain the descriptor of the COARRAY. */
2694 gfc_init_se (&argse, NULL);
2695 argse.want_coarray = 1;
2696 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2697 gfc_add_block_to_block (&se->pre, &argse.pre);
2698 gfc_add_block_to_block (&se->post, &argse.post);
2699 desc = argse.expr;
2701 /* Obtain a handle to the SUB argument. */
2702 gfc_init_se (&subse, NULL);
2703 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
2704 gfc_add_block_to_block (&se->pre, &subse.pre);
2705 gfc_add_block_to_block (&se->post, &subse.post);
2706 subdesc = build_fold_indirect_ref_loc (input_location,
2707 gfc_conv_descriptor_data_get (subse.expr));
2709 /* Fortran 2008 does not require that the values remain in the cobounds,
2710 thus we need explicitly check this - and return 0 if they are exceeded. */
2712 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2713 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
2714 invalid_bound = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2715 fold_convert (gfc_array_index_type, tmp),
2716 lbound);
2718 for (codim = corank + rank - 2; codim >= rank; codim--)
2720 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2721 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2722 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2723 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2724 fold_convert (gfc_array_index_type, tmp),
2725 lbound);
2726 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2727 logical_type_node, invalid_bound, cond);
2728 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2729 fold_convert (gfc_array_index_type, tmp),
2730 ubound);
2731 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2732 logical_type_node, invalid_bound, cond);
2735 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
2737 /* See Fortran 2008, C.10 for the following algorithm. */
2739 /* coindex = sub(corank) - lcobound(n). */
2740 coindex = fold_convert (gfc_array_index_type,
2741 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
2742 NULL));
2743 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2744 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2745 fold_convert (gfc_array_index_type, coindex),
2746 lbound);
2748 for (codim = corank + rank - 2; codim >= rank; codim--)
2750 tree extent, ubound;
2752 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2753 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2754 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2755 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2757 /* coindex *= extent. */
2758 coindex = fold_build2_loc (input_location, MULT_EXPR,
2759 gfc_array_index_type, coindex, extent);
2761 /* coindex += sub(codim). */
2762 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2763 coindex = fold_build2_loc (input_location, PLUS_EXPR,
2764 gfc_array_index_type, coindex,
2765 fold_convert (gfc_array_index_type, tmp));
2767 /* coindex -= lbound(codim). */
2768 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2769 coindex = fold_build2_loc (input_location, MINUS_EXPR,
2770 gfc_array_index_type, coindex, lbound);
2773 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
2774 fold_convert(type, coindex),
2775 build_int_cst (type, 1));
2777 /* Return 0 if "coindex" exceeds num_images(). */
2779 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2780 num_images = build_int_cst (type, 1);
2781 else
2783 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2784 integer_zero_node,
2785 build_int_cst (integer_type_node, -1));
2786 num_images = fold_convert (type, tmp);
2789 tmp = gfc_create_var (type, NULL);
2790 gfc_add_modify (&se->pre, tmp, coindex);
2792 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, tmp,
2793 num_images);
2794 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
2795 cond,
2796 fold_convert (logical_type_node, invalid_bound));
2797 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
2798 build_int_cst (type, 0), tmp);
2801 static void
2802 trans_num_images (gfc_se * se, gfc_expr *expr)
2804 tree tmp, distance, failed;
2805 gfc_se argse;
2807 if (expr->value.function.actual->expr)
2809 gfc_init_se (&argse, NULL);
2810 gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
2811 gfc_add_block_to_block (&se->pre, &argse.pre);
2812 gfc_add_block_to_block (&se->post, &argse.post);
2813 distance = fold_convert (integer_type_node, argse.expr);
2815 else
2816 distance = integer_zero_node;
2818 if (expr->value.function.actual->next->expr)
2820 gfc_init_se (&argse, NULL);
2821 gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
2822 gfc_add_block_to_block (&se->pre, &argse.pre);
2823 gfc_add_block_to_block (&se->post, &argse.post);
2824 failed = fold_convert (integer_type_node, argse.expr);
2826 else
2827 failed = build_int_cst (integer_type_node, -1);
2828 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2829 distance, failed);
2830 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2834 static void
2835 gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
2837 gfc_se argse;
2839 gfc_init_se (&argse, NULL);
2840 argse.data_not_needed = 1;
2841 argse.descriptor_only = 1;
2843 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2844 gfc_add_block_to_block (&se->pre, &argse.pre);
2845 gfc_add_block_to_block (&se->post, &argse.post);
2847 se->expr = gfc_conv_descriptor_rank (argse.expr);
2848 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2849 se->expr);
2853 static void
2854 gfc_conv_intrinsic_is_contiguous (gfc_se * se, gfc_expr * expr)
2856 gfc_expr *arg;
2857 arg = expr->value.function.actual->expr;
2858 gfc_conv_is_contiguous_expr (se, arg);
2859 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
2862 /* This function does the work for gfc_conv_intrinsic_is_contiguous,
2863 plus it can be called directly. */
2865 void
2866 gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg)
2868 gfc_ss *ss;
2869 gfc_se argse;
2870 tree desc, tmp, stride, extent, cond;
2871 int i;
2872 tree fncall0;
2873 gfc_array_spec *as;
2875 if (arg->ts.type == BT_CLASS)
2876 gfc_add_class_array_ref (arg);
2878 ss = gfc_walk_expr (arg);
2879 gcc_assert (ss != gfc_ss_terminator);
2880 gfc_init_se (&argse, NULL);
2881 argse.data_not_needed = 1;
2882 gfc_conv_expr_descriptor (&argse, arg);
2884 as = gfc_get_full_arrayspec_from_expr (arg);
2886 /* Create: stride[0] == 1 && stride[1] == extend[0]*stride[0] && ...
2887 Note in addition that zero-sized arrays don't count as contiguous. */
2889 if (as && as->type == AS_ASSUMED_RANK)
2891 /* Build the call to is_contiguous0. */
2892 argse.want_pointer = 1;
2893 gfc_conv_expr_descriptor (&argse, arg);
2894 gfc_add_block_to_block (&se->pre, &argse.pre);
2895 gfc_add_block_to_block (&se->post, &argse.post);
2896 desc = gfc_evaluate_now (argse.expr, &se->pre);
2897 fncall0 = build_call_expr_loc (input_location,
2898 gfor_fndecl_is_contiguous0, 1, desc);
2899 se->expr = fncall0;
2900 se->expr = convert (logical_type_node, se->expr);
2902 else
2904 gfc_add_block_to_block (&se->pre, &argse.pre);
2905 gfc_add_block_to_block (&se->post, &argse.post);
2906 desc = gfc_evaluate_now (argse.expr, &se->pre);
2908 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[0]);
2909 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2910 stride, build_int_cst (TREE_TYPE (stride), 1));
2912 for (i = 0; i < arg->rank - 1; i++)
2914 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
2915 extent = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
2916 extent = fold_build2_loc (input_location, MINUS_EXPR,
2917 gfc_array_index_type, extent, tmp);
2918 extent = fold_build2_loc (input_location, PLUS_EXPR,
2919 gfc_array_index_type, extent,
2920 gfc_index_one_node);
2921 tmp = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i]);
2922 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
2923 tmp, extent);
2924 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i+1]);
2925 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2926 stride, tmp);
2927 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2928 boolean_type_node, cond, tmp);
2930 se->expr = cond;
2935 /* Evaluate a single upper or lower bound. */
2936 /* TODO: bound intrinsic generates way too much unnecessary code. */
2938 static void
2939 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, enum gfc_isym_id op)
2941 gfc_actual_arglist *arg;
2942 gfc_actual_arglist *arg2;
2943 tree desc;
2944 tree type;
2945 tree bound;
2946 tree tmp;
2947 tree cond, cond1;
2948 tree ubound;
2949 tree lbound;
2950 tree size;
2951 gfc_se argse;
2952 gfc_array_spec * as;
2953 bool assumed_rank_lb_one;
2955 arg = expr->value.function.actual;
2956 arg2 = arg->next;
2958 if (se->ss)
2960 /* Create an implicit second parameter from the loop variable. */
2961 gcc_assert (!arg2->expr || op == GFC_ISYM_SHAPE);
2962 gcc_assert (se->loop->dimen == 1);
2963 gcc_assert (se->ss->info->expr == expr);
2964 gfc_advance_se_ss_chain (se);
2965 bound = se->loop->loopvar[0];
2966 bound = fold_build2_loc (input_location, MINUS_EXPR,
2967 gfc_array_index_type, bound,
2968 se->loop->from[0]);
2970 else
2972 /* use the passed argument. */
2973 gcc_assert (arg2->expr);
2974 gfc_init_se (&argse, NULL);
2975 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2976 gfc_add_block_to_block (&se->pre, &argse.pre);
2977 bound = argse.expr;
2978 /* Convert from one based to zero based. */
2979 bound = fold_build2_loc (input_location, MINUS_EXPR,
2980 gfc_array_index_type, bound,
2981 gfc_index_one_node);
2984 /* TODO: don't re-evaluate the descriptor on each iteration. */
2985 /* Get a descriptor for the first parameter. */
2986 gfc_init_se (&argse, NULL);
2987 gfc_conv_expr_descriptor (&argse, arg->expr);
2988 gfc_add_block_to_block (&se->pre, &argse.pre);
2989 gfc_add_block_to_block (&se->post, &argse.post);
2991 desc = argse.expr;
2993 as = gfc_get_full_arrayspec_from_expr (arg->expr);
2995 if (INTEGER_CST_P (bound))
2997 gcc_assert (op != GFC_ISYM_SHAPE);
2998 if (((!as || as->type != AS_ASSUMED_RANK)
2999 && wi::geu_p (wi::to_wide (bound),
3000 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
3001 || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS))
3002 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3003 "dimension index",
3004 (op == GFC_ISYM_UBOUND) ? "UBOUND" : "LBOUND",
3005 &expr->where);
3008 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
3010 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3012 bound = gfc_evaluate_now (bound, &se->pre);
3013 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3014 bound, build_int_cst (TREE_TYPE (bound), 0));
3015 if (as && as->type == AS_ASSUMED_RANK)
3016 tmp = gfc_conv_descriptor_rank (desc);
3017 else
3018 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
3019 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
3020 bound, fold_convert(TREE_TYPE (bound), tmp));
3021 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3022 logical_type_node, cond, tmp);
3023 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3024 gfc_msg_fault);
3028 /* Take care of the lbound shift for assumed-rank arrays that are
3029 nonallocatable and nonpointers. Those have a lbound of 1. */
3030 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
3031 && ((arg->expr->ts.type != BT_CLASS
3032 && !arg->expr->symtree->n.sym->attr.allocatable
3033 && !arg->expr->symtree->n.sym->attr.pointer)
3034 || (arg->expr->ts.type == BT_CLASS
3035 && !CLASS_DATA (arg->expr)->attr.allocatable
3036 && !CLASS_DATA (arg->expr)->attr.class_pointer));
3038 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
3039 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
3040 size = fold_build2_loc (input_location, MINUS_EXPR,
3041 gfc_array_index_type, ubound, lbound);
3042 size = fold_build2_loc (input_location, PLUS_EXPR,
3043 gfc_array_index_type, size, gfc_index_one_node);
3045 /* 13.14.53: Result value for LBOUND
3047 Case (i): For an array section or for an array expression other than a
3048 whole array or array structure component, LBOUND(ARRAY, DIM)
3049 has the value 1. For a whole array or array structure
3050 component, LBOUND(ARRAY, DIM) has the value:
3051 (a) equal to the lower bound for subscript DIM of ARRAY if
3052 dimension DIM of ARRAY does not have extent zero
3053 or if ARRAY is an assumed-size array of rank DIM,
3054 or (b) 1 otherwise.
3056 13.14.113: Result value for UBOUND
3058 Case (i): For an array section or for an array expression other than a
3059 whole array or array structure component, UBOUND(ARRAY, DIM)
3060 has the value equal to the number of elements in the given
3061 dimension; otherwise, it has a value equal to the upper bound
3062 for subscript DIM of ARRAY if dimension DIM of ARRAY does
3063 not have size zero and has value zero if dimension DIM has
3064 size zero. */
3066 if (op == GFC_ISYM_LBOUND && assumed_rank_lb_one)
3067 se->expr = gfc_index_one_node;
3068 else if (as)
3070 if (op == GFC_ISYM_UBOUND)
3072 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3073 size, gfc_index_zero_node);
3074 se->expr = fold_build3_loc (input_location, COND_EXPR,
3075 gfc_array_index_type, cond,
3076 (assumed_rank_lb_one ? size : ubound),
3077 gfc_index_zero_node);
3079 else if (op == GFC_ISYM_LBOUND)
3081 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3082 size, gfc_index_zero_node);
3083 if (as->type == AS_ASSUMED_SIZE)
3085 cond1 = fold_build2_loc (input_location, EQ_EXPR,
3086 logical_type_node, bound,
3087 build_int_cst (TREE_TYPE (bound),
3088 arg->expr->rank - 1));
3089 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3090 logical_type_node, cond, cond1);
3092 se->expr = fold_build3_loc (input_location, COND_EXPR,
3093 gfc_array_index_type, cond,
3094 lbound, gfc_index_one_node);
3096 else if (op == GFC_ISYM_SHAPE)
3097 se->expr = fold_build2_loc (input_location, MAX_EXPR,
3098 gfc_array_index_type, size,
3099 gfc_index_zero_node);
3100 else
3101 gcc_unreachable ();
3103 /* According to F2018 16.9.172, para 5, an assumed rank object,
3104 argument associated with and assumed size array, has the ubound
3105 of the final dimension set to -1 and UBOUND must return this.
3106 Similarly for the SHAPE intrinsic. */
3107 if (op != GFC_ISYM_LBOUND && assumed_rank_lb_one)
3109 tree minus_one = build_int_cst (gfc_array_index_type, -1);
3110 tree rank = fold_convert (gfc_array_index_type,
3111 gfc_conv_descriptor_rank (desc));
3112 rank = fold_build2_loc (input_location, PLUS_EXPR,
3113 gfc_array_index_type, rank, minus_one);
3115 /* Fix the expression to stop it from becoming even more
3116 complicated. */
3117 se->expr = gfc_evaluate_now (se->expr, &se->pre);
3119 /* Descriptors for assumed-size arrays have ubound = -1
3120 in the last dimension. */
3121 cond1 = fold_build2_loc (input_location, EQ_EXPR,
3122 logical_type_node, ubound, minus_one);
3123 cond = fold_build2_loc (input_location, EQ_EXPR,
3124 logical_type_node, bound, rank);
3125 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3126 logical_type_node, cond, cond1);
3127 se->expr = fold_build3_loc (input_location, COND_EXPR,
3128 gfc_array_index_type, cond,
3129 minus_one, se->expr);
3132 else /* as is null; this is an old-fashioned 1-based array. */
3134 if (op != GFC_ISYM_LBOUND)
3136 se->expr = fold_build2_loc (input_location, MAX_EXPR,
3137 gfc_array_index_type, size,
3138 gfc_index_zero_node);
3140 else
3141 se->expr = gfc_index_one_node;
3145 type = gfc_typenode_for_spec (&expr->ts);
3146 se->expr = convert (type, se->expr);
3150 static void
3151 conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
3153 gfc_actual_arglist *arg;
3154 gfc_actual_arglist *arg2;
3155 gfc_se argse;
3156 tree bound, resbound, resbound2, desc, cond, tmp;
3157 tree type;
3158 int corank;
3160 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
3161 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
3162 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
3164 arg = expr->value.function.actual;
3165 arg2 = arg->next;
3167 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
3168 corank = arg->expr->corank;
3170 gfc_init_se (&argse, NULL);
3171 argse.want_coarray = 1;
3173 gfc_conv_expr_descriptor (&argse, arg->expr);
3174 gfc_add_block_to_block (&se->pre, &argse.pre);
3175 gfc_add_block_to_block (&se->post, &argse.post);
3176 desc = argse.expr;
3178 if (se->ss)
3180 /* Create an implicit second parameter from the loop variable. */
3181 gcc_assert (!arg2->expr);
3182 gcc_assert (corank > 0);
3183 gcc_assert (se->loop->dimen == 1);
3184 gcc_assert (se->ss->info->expr == expr);
3186 bound = se->loop->loopvar[0];
3187 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3188 bound, gfc_rank_cst[arg->expr->rank]);
3189 gfc_advance_se_ss_chain (se);
3191 else
3193 /* use the passed argument. */
3194 gcc_assert (arg2->expr);
3195 gfc_init_se (&argse, NULL);
3196 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
3197 gfc_add_block_to_block (&se->pre, &argse.pre);
3198 bound = argse.expr;
3200 if (INTEGER_CST_P (bound))
3202 if (wi::ltu_p (wi::to_wide (bound), 1)
3203 || wi::gtu_p (wi::to_wide (bound),
3204 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
3205 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3206 "dimension index", expr->value.function.isym->name,
3207 &expr->where);
3209 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3211 bound = gfc_evaluate_now (bound, &se->pre);
3212 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3213 bound, build_int_cst (TREE_TYPE (bound), 1));
3214 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
3215 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3216 bound, tmp);
3217 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3218 logical_type_node, cond, tmp);
3219 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3220 gfc_msg_fault);
3224 /* Subtract 1 to get to zero based and add dimensions. */
3225 switch (arg->expr->rank)
3227 case 0:
3228 bound = fold_build2_loc (input_location, MINUS_EXPR,
3229 gfc_array_index_type, bound,
3230 gfc_index_one_node);
3231 case 1:
3232 break;
3233 default:
3234 bound = fold_build2_loc (input_location, PLUS_EXPR,
3235 gfc_array_index_type, bound,
3236 gfc_rank_cst[arg->expr->rank - 1]);
3240 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
3242 /* Handle UCOBOUND with special handling of the last codimension. */
3243 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
3245 /* Last codimension: For -fcoarray=single just return
3246 the lcobound - otherwise add
3247 ceiling (real (num_images ()) / real (size)) - 1
3248 = (num_images () + size - 1) / size - 1
3249 = (num_images - 1) / size(),
3250 where size is the product of the extent of all but the last
3251 codimension. */
3253 if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
3255 tree cosize;
3257 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
3258 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3259 2, integer_zero_node,
3260 build_int_cst (integer_type_node, -1));
3261 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3262 gfc_array_index_type,
3263 fold_convert (gfc_array_index_type, tmp),
3264 build_int_cst (gfc_array_index_type, 1));
3265 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
3266 gfc_array_index_type, tmp,
3267 fold_convert (gfc_array_index_type, cosize));
3268 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3269 gfc_array_index_type, resbound, tmp);
3271 else if (flag_coarray != GFC_FCOARRAY_SINGLE)
3273 /* ubound = lbound + num_images() - 1. */
3274 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3275 2, integer_zero_node,
3276 build_int_cst (integer_type_node, -1));
3277 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3278 gfc_array_index_type,
3279 fold_convert (gfc_array_index_type, tmp),
3280 build_int_cst (gfc_array_index_type, 1));
3281 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3282 gfc_array_index_type, resbound, tmp);
3285 if (corank > 1)
3287 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3288 bound,
3289 build_int_cst (TREE_TYPE (bound),
3290 arg->expr->rank + corank - 1));
3292 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
3293 se->expr = fold_build3_loc (input_location, COND_EXPR,
3294 gfc_array_index_type, cond,
3295 resbound, resbound2);
3297 else
3298 se->expr = resbound;
3300 else
3301 se->expr = resbound;
3303 type = gfc_typenode_for_spec (&expr->ts);
3304 se->expr = convert (type, se->expr);
3308 static void
3309 conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
3311 gfc_actual_arglist *array_arg;
3312 gfc_actual_arglist *dim_arg;
3313 gfc_se argse;
3314 tree desc, tmp;
3316 array_arg = expr->value.function.actual;
3317 dim_arg = array_arg->next;
3319 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
3321 gfc_init_se (&argse, NULL);
3322 gfc_conv_expr_descriptor (&argse, array_arg->expr);
3323 gfc_add_block_to_block (&se->pre, &argse.pre);
3324 gfc_add_block_to_block (&se->post, &argse.post);
3325 desc = argse.expr;
3327 gcc_assert (dim_arg->expr);
3328 gfc_init_se (&argse, NULL);
3329 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
3330 gfc_add_block_to_block (&se->pre, &argse.pre);
3331 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3332 argse.expr, gfc_index_one_node);
3333 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
3336 static void
3337 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
3339 tree arg, cabs;
3341 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3343 switch (expr->value.function.actual->expr->ts.type)
3345 case BT_INTEGER:
3346 case BT_REAL:
3347 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
3348 arg);
3349 break;
3351 case BT_COMPLEX:
3352 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
3353 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
3354 break;
3356 default:
3357 gcc_unreachable ();
3362 /* Create a complex value from one or two real components. */
3364 static void
3365 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
3367 tree real;
3368 tree imag;
3369 tree type;
3370 tree *args;
3371 unsigned int num_args;
3373 num_args = gfc_intrinsic_argument_list_length (expr);
3374 args = XALLOCAVEC (tree, num_args);
3376 type = gfc_typenode_for_spec (&expr->ts);
3377 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3378 real = convert (TREE_TYPE (type), args[0]);
3379 if (both)
3380 imag = convert (TREE_TYPE (type), args[1]);
3381 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
3383 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
3384 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
3385 imag = convert (TREE_TYPE (type), imag);
3387 else
3388 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
3390 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
3394 /* Remainder function MOD(A, P) = A - INT(A / P) * P
3395 MODULO(A, P) = A - FLOOR (A / P) * P
3397 The obvious algorithms above are numerically instable for large
3398 arguments, hence these intrinsics are instead implemented via calls
3399 to the fmod family of functions. It is the responsibility of the
3400 user to ensure that the second argument is non-zero. */
3402 static void
3403 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
3405 tree type;
3406 tree tmp;
3407 tree test;
3408 tree test2;
3409 tree fmod;
3410 tree zero;
3411 tree args[2];
3413 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3415 switch (expr->ts.type)
3417 case BT_INTEGER:
3418 /* Integer case is easy, we've got a builtin op. */
3419 type = TREE_TYPE (args[0]);
3421 if (modulo)
3422 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
3423 args[0], args[1]);
3424 else
3425 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3426 args[0], args[1]);
3427 break;
3429 case BT_UNSIGNED:
3430 /* Even easier, we only need one. */
3431 type = TREE_TYPE (args[0]);
3432 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3433 args[0], args[1]);
3434 break;
3436 case BT_REAL:
3437 fmod = NULL_TREE;
3438 /* Check if we have a builtin fmod. */
3439 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
3441 /* The builtin should always be available. */
3442 gcc_assert (fmod != NULL_TREE);
3444 tmp = build_addr (fmod);
3445 se->expr = build_call_array_loc (input_location,
3446 TREE_TYPE (TREE_TYPE (fmod)),
3447 tmp, 2, args);
3448 if (modulo == 0)
3449 return;
3451 type = TREE_TYPE (args[0]);
3453 args[0] = gfc_evaluate_now (args[0], &se->pre);
3454 args[1] = gfc_evaluate_now (args[1], &se->pre);
3456 /* Definition:
3457 modulo = arg - floor (arg/arg2) * arg2
3459 In order to calculate the result accurately, we use the fmod
3460 function as follows.
3462 res = fmod (arg, arg2);
3463 if (res)
3465 if ((arg < 0) xor (arg2 < 0))
3466 res += arg2;
3468 else
3469 res = copysign (0., arg2);
3471 => As two nested ternary exprs:
3473 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3474 : copysign (0., arg2);
3478 zero = gfc_build_const (type, integer_zero_node);
3479 tmp = gfc_evaluate_now (se->expr, &se->pre);
3480 if (!flag_signed_zeros)
3482 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3483 args[0], zero);
3484 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3485 args[1], zero);
3486 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3487 logical_type_node, test, test2);
3488 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3489 tmp, zero);
3490 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3491 logical_type_node, test, test2);
3492 test = gfc_evaluate_now (test, &se->pre);
3493 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3494 fold_build2_loc (input_location,
3495 PLUS_EXPR,
3496 type, tmp, args[1]),
3497 tmp);
3499 else
3501 tree expr1, copysign, cscall;
3502 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
3503 expr->ts.kind);
3504 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3505 args[0], zero);
3506 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3507 args[1], zero);
3508 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3509 logical_type_node, test, test2);
3510 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
3511 fold_build2_loc (input_location,
3512 PLUS_EXPR,
3513 type, tmp, args[1]),
3514 tmp);
3515 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3516 tmp, zero);
3517 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
3518 args[1]);
3519 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3520 expr1, cscall);
3522 return;
3524 default:
3525 gcc_unreachable ();
3529 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3530 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3531 where the right shifts are logical (i.e. 0's are shifted in).
3532 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3533 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3534 DSHIFTL(I,J,0) = I
3535 DSHIFTL(I,J,BITSIZE) = J
3536 DSHIFTR(I,J,0) = J
3537 DSHIFTR(I,J,BITSIZE) = I. */
3539 static void
3540 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
3542 tree type, utype, stype, arg1, arg2, shift, res, left, right;
3543 tree args[3], cond, tmp;
3544 int bitsize;
3546 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3548 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
3549 type = TREE_TYPE (args[0]);
3550 bitsize = TYPE_PRECISION (type);
3551 utype = unsigned_type_for (type);
3552 stype = TREE_TYPE (args[2]);
3554 arg1 = gfc_evaluate_now (args[0], &se->pre);
3555 arg2 = gfc_evaluate_now (args[1], &se->pre);
3556 shift = gfc_evaluate_now (args[2], &se->pre);
3558 /* The generic case. */
3559 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
3560 build_int_cst (stype, bitsize), shift);
3561 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3562 arg1, dshiftl ? shift : tmp);
3564 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
3565 fold_convert (utype, arg2), dshiftl ? tmp : shift);
3566 right = fold_convert (type, right);
3568 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
3570 /* Special cases. */
3571 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3572 build_int_cst (stype, 0));
3573 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3574 dshiftl ? arg1 : arg2, res);
3576 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3577 build_int_cst (stype, bitsize));
3578 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3579 dshiftl ? arg2 : arg1, res);
3581 se->expr = res;
3585 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3587 static void
3588 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
3590 tree val;
3591 tree tmp;
3592 tree type;
3593 tree zero;
3594 tree args[2];
3596 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3597 type = TREE_TYPE (args[0]);
3599 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
3600 val = gfc_evaluate_now (val, &se->pre);
3602 zero = gfc_build_const (type, integer_zero_node);
3603 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node, val, zero);
3604 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
3608 /* SIGN(A, B) is absolute value of A times sign of B.
3609 The real value versions use library functions to ensure the correct
3610 handling of negative zero. Integer case implemented as:
3611 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3614 static void
3615 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
3617 tree tmp;
3618 tree type;
3619 tree args[2];
3621 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3622 if (expr->ts.type == BT_REAL)
3624 tree abs;
3626 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
3627 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
3629 /* We explicitly have to ignore the minus sign. We do so by using
3630 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3631 if (!flag_sign_zero
3632 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
3634 tree cond, zero;
3635 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
3636 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3637 args[1], zero);
3638 se->expr = fold_build3_loc (input_location, COND_EXPR,
3639 TREE_TYPE (args[0]), cond,
3640 build_call_expr_loc (input_location, abs, 1,
3641 args[0]),
3642 build_call_expr_loc (input_location, tmp, 2,
3643 args[0], args[1]));
3645 else
3646 se->expr = build_call_expr_loc (input_location, tmp, 2,
3647 args[0], args[1]);
3648 return;
3651 /* Having excluded floating point types, we know we are now dealing
3652 with signed integer types. */
3653 type = TREE_TYPE (args[0]);
3655 /* Args[0] is used multiple times below. */
3656 args[0] = gfc_evaluate_now (args[0], &se->pre);
3658 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3659 the signs of A and B are the same, and of all ones if they differ. */
3660 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
3661 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
3662 build_int_cst (type, TYPE_PRECISION (type) - 1));
3663 tmp = gfc_evaluate_now (tmp, &se->pre);
3665 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3666 is all ones (i.e. -1). */
3667 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
3668 fold_build2_loc (input_location, PLUS_EXPR,
3669 type, args[0], tmp), tmp);
3673 /* Test for the presence of an optional argument. */
3675 static void
3676 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
3678 gfc_expr *arg;
3680 arg = expr->value.function.actual->expr;
3681 gcc_assert (arg->expr_type == EXPR_VARIABLE);
3682 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
3683 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3687 /* Calculate the double precision product of two single precision values. */
3689 static void
3690 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
3692 tree type;
3693 tree args[2];
3695 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3697 /* Convert the args to double precision before multiplying. */
3698 type = gfc_typenode_for_spec (&expr->ts);
3699 args[0] = convert (type, args[0]);
3700 args[1] = convert (type, args[1]);
3701 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
3702 args[1]);
3706 /* Return a length one character string containing an ascii character. */
3708 static void
3709 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
3711 tree arg[2];
3712 tree var;
3713 tree type;
3714 unsigned int num_args;
3716 num_args = gfc_intrinsic_argument_list_length (expr);
3717 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
3719 type = gfc_get_char_type (expr->ts.kind);
3720 var = gfc_create_var (type, "char");
3722 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
3723 gfc_add_modify (&se->pre, var, arg[0]);
3724 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
3725 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
3729 static void
3730 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
3732 tree var;
3733 tree len;
3734 tree tmp;
3735 tree cond;
3736 tree fndecl;
3737 tree *args;
3738 unsigned int num_args;
3740 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3741 args = XALLOCAVEC (tree, num_args);
3743 var = gfc_create_var (pchar_type_node, "pstr");
3744 len = gfc_create_var (gfc_charlen_type_node, "len");
3746 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3747 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3748 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3750 fndecl = build_addr (gfor_fndecl_ctime);
3751 tmp = build_call_array_loc (input_location,
3752 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
3753 fndecl, num_args, args);
3754 gfc_add_expr_to_block (&se->pre, tmp);
3756 /* Free the temporary afterwards, if necessary. */
3757 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3758 len, build_int_cst (TREE_TYPE (len), 0));
3759 tmp = gfc_call_free (var);
3760 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3761 gfc_add_expr_to_block (&se->post, tmp);
3763 se->expr = var;
3764 se->string_length = len;
3768 static void
3769 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
3771 tree var;
3772 tree len;
3773 tree tmp;
3774 tree cond;
3775 tree fndecl;
3776 tree *args;
3777 unsigned int num_args;
3779 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3780 args = XALLOCAVEC (tree, num_args);
3782 var = gfc_create_var (pchar_type_node, "pstr");
3783 len = gfc_create_var (gfc_charlen_type_node, "len");
3785 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3786 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3787 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3789 fndecl = build_addr (gfor_fndecl_fdate);
3790 tmp = build_call_array_loc (input_location,
3791 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
3792 fndecl, num_args, args);
3793 gfc_add_expr_to_block (&se->pre, tmp);
3795 /* Free the temporary afterwards, if necessary. */
3796 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3797 len, build_int_cst (TREE_TYPE (len), 0));
3798 tmp = gfc_call_free (var);
3799 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3800 gfc_add_expr_to_block (&se->post, tmp);
3802 se->expr = var;
3803 se->string_length = len;
3807 /* Generate a direct call to free() for the FREE subroutine. */
3809 static tree
3810 conv_intrinsic_free (gfc_code *code)
3812 stmtblock_t block;
3813 gfc_se argse;
3814 tree arg, call;
3816 gfc_init_se (&argse, NULL);
3817 gfc_conv_expr (&argse, code->ext.actual->expr);
3818 arg = fold_convert (ptr_type_node, argse.expr);
3820 gfc_init_block (&block);
3821 call = build_call_expr_loc (input_location,
3822 builtin_decl_explicit (BUILT_IN_FREE), 1, arg);
3823 gfc_add_expr_to_block (&block, call);
3824 return gfc_finish_block (&block);
3828 /* Call the RANDOM_INIT library subroutine with a hidden argument for
3829 handling seeding on coarray images. */
3831 static tree
3832 conv_intrinsic_random_init (gfc_code *code)
3834 stmtblock_t block;
3835 gfc_se se;
3836 tree arg1, arg2, tmp;
3837 /* On none coarray == lib compiles use LOGICAL(4) else regular LOGICAL. */
3838 tree used_bool_type_node = flag_coarray == GFC_FCOARRAY_LIB
3839 ? logical_type_node
3840 : gfc_get_logical_type (4);
3842 /* Make the function call. */
3843 gfc_init_block (&block);
3844 gfc_init_se (&se, NULL);
3846 /* Convert REPEATABLE to the desired LOGICAL entity. */
3847 gfc_conv_expr (&se, code->ext.actual->expr);
3848 gfc_add_block_to_block (&block, &se.pre);
3849 arg1 = fold_convert (used_bool_type_node, gfc_evaluate_now (se.expr, &block));
3850 gfc_add_block_to_block (&block, &se.post);
3852 /* Convert IMAGE_DISTINCT to the desired LOGICAL entity. */
3853 gfc_conv_expr (&se, code->ext.actual->next->expr);
3854 gfc_add_block_to_block (&block, &se.pre);
3855 arg2 = fold_convert (used_bool_type_node, gfc_evaluate_now (se.expr, &block));
3856 gfc_add_block_to_block (&block, &se.post);
3858 if (flag_coarray == GFC_FCOARRAY_LIB)
3860 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_random_init,
3861 2, arg1, arg2);
3863 else
3865 /* The ABI for libgfortran needs to be maintained, so a hidden
3866 argument must be include if code is compiled with -fcoarray=single
3867 or without the option. Set to 0. */
3868 tree arg3 = build_int_cst (gfc_get_int_type (4), 0);
3869 tmp = build_call_expr_loc (input_location, gfor_fndecl_random_init,
3870 3, arg1, arg2, arg3);
3873 gfc_add_expr_to_block (&block, tmp);
3875 return gfc_finish_block (&block);
3879 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3880 conversions. */
3882 static tree
3883 conv_intrinsic_system_clock (gfc_code *code)
3885 stmtblock_t block;
3886 gfc_se count_se, count_rate_se, count_max_se;
3887 tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
3888 tree tmp;
3889 int least;
3891 gfc_expr *count = code->ext.actual->expr;
3892 gfc_expr *count_rate = code->ext.actual->next->expr;
3893 gfc_expr *count_max = code->ext.actual->next->next->expr;
3895 /* Evaluate our arguments. */
3896 if (count)
3898 gfc_init_se (&count_se, NULL);
3899 gfc_conv_expr (&count_se, count);
3902 if (count_rate)
3904 gfc_init_se (&count_rate_se, NULL);
3905 gfc_conv_expr (&count_rate_se, count_rate);
3908 if (count_max)
3910 gfc_init_se (&count_max_se, NULL);
3911 gfc_conv_expr (&count_max_se, count_max);
3914 /* Find the smallest kind found of the arguments. */
3915 least = 16;
3916 least = (count && count->ts.kind < least) ? count->ts.kind : least;
3917 least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
3918 : least;
3919 least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
3920 : least;
3922 /* Prepare temporary variables. */
3924 if (count)
3926 if (least >= 8)
3927 arg1 = gfc_create_var (gfc_get_int_type (8), "count");
3928 else if (least == 4)
3929 arg1 = gfc_create_var (gfc_get_int_type (4), "count");
3930 else if (count->ts.kind == 1)
3931 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
3932 count->ts.kind);
3933 else
3934 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
3935 count->ts.kind);
3938 if (count_rate)
3940 if (least >= 8)
3941 arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
3942 else if (least == 4)
3943 arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
3944 else
3945 arg2 = integer_zero_node;
3948 if (count_max)
3950 if (least >= 8)
3951 arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
3952 else if (least == 4)
3953 arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
3954 else
3955 arg3 = integer_zero_node;
3958 /* Make the function call. */
3959 gfc_init_block (&block);
3961 if (least <= 2)
3963 if (least == 1)
3965 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3966 : null_pointer_node;
3967 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3968 : null_pointer_node;
3969 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3970 : null_pointer_node;
3973 if (least == 2)
3975 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3976 : null_pointer_node;
3977 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3978 : null_pointer_node;
3979 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3980 : null_pointer_node;
3983 else
3985 if (least == 4)
3987 tmp = build_call_expr_loc (input_location,
3988 gfor_fndecl_system_clock4, 3,
3989 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3990 : null_pointer_node,
3991 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3992 : null_pointer_node,
3993 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3994 : null_pointer_node);
3995 gfc_add_expr_to_block (&block, tmp);
3997 /* Handle kind>=8, 10, or 16 arguments */
3998 if (least >= 8)
4000 tmp = build_call_expr_loc (input_location,
4001 gfor_fndecl_system_clock8, 3,
4002 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
4003 : null_pointer_node,
4004 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
4005 : null_pointer_node,
4006 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
4007 : null_pointer_node);
4008 gfc_add_expr_to_block (&block, tmp);
4012 /* And store values back if needed. */
4013 if (arg1 && arg1 != count_se.expr)
4014 gfc_add_modify (&block, count_se.expr,
4015 fold_convert (TREE_TYPE (count_se.expr), arg1));
4016 if (arg2 && arg2 != count_rate_se.expr)
4017 gfc_add_modify (&block, count_rate_se.expr,
4018 fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
4019 if (arg3 && arg3 != count_max_se.expr)
4020 gfc_add_modify (&block, count_max_se.expr,
4021 fold_convert (TREE_TYPE (count_max_se.expr), arg3));
4023 return gfc_finish_block (&block);
4027 /* Return a character string containing the tty name. */
4029 static void
4030 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
4032 tree var;
4033 tree len;
4034 tree tmp;
4035 tree cond;
4036 tree fndecl;
4037 tree *args;
4038 unsigned int num_args;
4040 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
4041 args = XALLOCAVEC (tree, num_args);
4043 var = gfc_create_var (pchar_type_node, "pstr");
4044 len = gfc_create_var (gfc_charlen_type_node, "len");
4046 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
4047 args[0] = gfc_build_addr_expr (NULL_TREE, var);
4048 args[1] = gfc_build_addr_expr (NULL_TREE, len);
4050 fndecl = build_addr (gfor_fndecl_ttynam);
4051 tmp = build_call_array_loc (input_location,
4052 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
4053 fndecl, num_args, args);
4054 gfc_add_expr_to_block (&se->pre, tmp);
4056 /* Free the temporary afterwards, if necessary. */
4057 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4058 len, build_int_cst (TREE_TYPE (len), 0));
4059 tmp = gfc_call_free (var);
4060 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4061 gfc_add_expr_to_block (&se->post, tmp);
4063 se->expr = var;
4064 se->string_length = len;
4068 /* Get the minimum/maximum value of all the parameters.
4069 minmax (a1, a2, a3, ...)
4071 mvar = a1;
4072 mvar = COMP (mvar, a2)
4073 mvar = COMP (mvar, a3)
4075 return mvar;
4077 Where COMP is MIN/MAX_EXPR for integral types or when we don't
4078 care about NaNs, or IFN_FMIN/MAX when the target has support for
4079 fast NaN-honouring min/max. When neither holds expand a sequence
4080 of explicit comparisons. */
4082 /* TODO: Mismatching types can occur when specific names are used.
4083 These should be handled during resolution. */
4084 static void
4085 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
4087 tree tmp;
4088 tree mvar;
4089 tree val;
4090 tree *args;
4091 tree type;
4092 tree argtype;
4093 gfc_actual_arglist *argexpr;
4094 unsigned int i, nargs;
4096 nargs = gfc_intrinsic_argument_list_length (expr);
4097 args = XALLOCAVEC (tree, nargs);
4099 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
4100 type = gfc_typenode_for_spec (&expr->ts);
4102 /* Only evaluate the argument once. */
4103 if (!VAR_P (args[0]) && !TREE_CONSTANT (args[0]))
4104 args[0] = gfc_evaluate_now (args[0], &se->pre);
4106 /* Determine suitable type of temporary, as a GNU extension allows
4107 different argument kinds. */
4108 argtype = TREE_TYPE (args[0]);
4109 argexpr = expr->value.function.actual;
4110 for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
4112 tree tmptype = TREE_TYPE (args[i]);
4113 if (TYPE_PRECISION (tmptype) > TYPE_PRECISION (argtype))
4114 argtype = tmptype;
4116 mvar = gfc_create_var (argtype, "M");
4117 gfc_add_modify (&se->pre, mvar, convert (argtype, args[0]));
4119 argexpr = expr->value.function.actual;
4120 for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
4122 tree cond = NULL_TREE;
4123 val = args[i];
4125 /* Handle absent optional arguments by ignoring the comparison. */
4126 if (argexpr->expr->expr_type == EXPR_VARIABLE
4127 && argexpr->expr->symtree->n.sym->attr.optional
4128 && INDIRECT_REF_P (val))
4130 cond = fold_build2_loc (input_location,
4131 NE_EXPR, logical_type_node,
4132 TREE_OPERAND (val, 0),
4133 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
4135 else if (!VAR_P (val) && !TREE_CONSTANT (val))
4136 /* Only evaluate the argument once. */
4137 val = gfc_evaluate_now (val, &se->pre);
4139 tree calc;
4140 /* For floating point types, the question is what MAX(a, NaN) or
4141 MIN(a, NaN) should return (where "a" is a normal number).
4142 There are valid use case for returning either one, but the
4143 Fortran standard doesn't specify which one should be chosen.
4144 Also, there is no consensus among other tested compilers. In
4145 short, it's a mess. So lets just do whatever is fastest. */
4146 tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR;
4147 calc = fold_build2_loc (input_location, code, argtype,
4148 convert (argtype, val), mvar);
4149 tmp = build2_v (MODIFY_EXPR, mvar, calc);
4151 if (cond != NULL_TREE)
4152 tmp = build3_v (COND_EXPR, cond, tmp,
4153 build_empty_stmt (input_location));
4154 gfc_add_expr_to_block (&se->pre, tmp);
4156 se->expr = convert (type, mvar);
4160 /* Generate library calls for MIN and MAX intrinsics for character
4161 variables. */
4162 static void
4163 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
4165 tree *args;
4166 tree var, len, fndecl, tmp, cond, function;
4167 unsigned int nargs;
4169 nargs = gfc_intrinsic_argument_list_length (expr);
4170 args = XALLOCAVEC (tree, nargs + 4);
4171 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
4173 /* Create the result variables. */
4174 len = gfc_create_var (gfc_charlen_type_node, "len");
4175 args[0] = gfc_build_addr_expr (NULL_TREE, len);
4176 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
4177 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
4178 args[2] = build_int_cst (integer_type_node, op);
4179 args[3] = build_int_cst (integer_type_node, nargs / 2);
4181 if (expr->ts.kind == 1)
4182 function = gfor_fndecl_string_minmax;
4183 else if (expr->ts.kind == 4)
4184 function = gfor_fndecl_string_minmax_char4;
4185 else
4186 gcc_unreachable ();
4188 /* Make the function call. */
4189 fndecl = build_addr (function);
4190 tmp = build_call_array_loc (input_location,
4191 TREE_TYPE (TREE_TYPE (function)), fndecl,
4192 nargs + 4, args);
4193 gfc_add_expr_to_block (&se->pre, tmp);
4195 /* Free the temporary afterwards, if necessary. */
4196 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4197 len, build_int_cst (TREE_TYPE (len), 0));
4198 tmp = gfc_call_free (var);
4199 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4200 gfc_add_expr_to_block (&se->post, tmp);
4202 se->expr = var;
4203 se->string_length = len;
4207 /* Create a symbol node for this intrinsic. The symbol from the frontend
4208 has the generic name. */
4210 static gfc_symbol *
4211 gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
4213 gfc_symbol *sym;
4215 /* TODO: Add symbols for intrinsic function to the global namespace. */
4216 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
4217 sym = gfc_new_symbol (expr->value.function.name, NULL);
4219 sym->ts = expr->ts;
4220 sym->attr.external = 1;
4221 sym->attr.function = 1;
4222 sym->attr.always_explicit = 1;
4223 sym->attr.proc = PROC_INTRINSIC;
4224 sym->attr.flavor = FL_PROCEDURE;
4225 sym->result = sym;
4226 if (expr->rank > 0)
4228 sym->attr.dimension = 1;
4229 sym->as = gfc_get_array_spec ();
4230 sym->as->type = AS_ASSUMED_SHAPE;
4231 sym->as->rank = expr->rank;
4234 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4235 ignore_optional ? expr->value.function.actual
4236 : NULL);
4238 return sym;
4241 /* Remove empty actual arguments. */
4243 static void
4244 remove_empty_actual_arguments (gfc_actual_arglist **ap)
4246 while (*ap)
4248 if ((*ap)->expr == NULL)
4250 gfc_actual_arglist *r = *ap;
4251 *ap = r->next;
4252 r->next = NULL;
4253 gfc_free_actual_arglist (r);
4255 else
4256 ap = &((*ap)->next);
4260 #define MAX_SPEC_ARG 12
4262 /* Make up an fn spec that's right for intrinsic functions that we
4263 want to call. */
4265 static char *
4266 intrinsic_fnspec (gfc_expr *expr)
4268 static char fnspec_buf[MAX_SPEC_ARG*2+1];
4269 char *fp;
4270 int i;
4271 int num_char_args;
4273 #define ADD_CHAR(c) do { *fp++ = c; *fp++ = ' '; } while(0)
4275 /* Set the fndecl. */
4276 fp = fnspec_buf;
4277 /* Function return value. FIXME: Check if the second letter could
4278 be something other than a space, for further optimization. */
4279 ADD_CHAR ('.');
4280 if (expr->rank == 0)
4282 if (expr->ts.type == BT_CHARACTER)
4284 ADD_CHAR ('w'); /* Address of character. */
4285 ADD_CHAR ('.'); /* Length of character. */
4288 else
4289 ADD_CHAR ('w'); /* Return value is a descriptor. */
4291 num_char_args = 0;
4292 for (gfc_actual_arglist *a = expr->value.function.actual; a; a = a->next)
4294 if (a->expr == NULL)
4295 continue;
4297 if (a->name && strcmp (a->name,"%VAL") == 0)
4298 ADD_CHAR ('.');
4299 else
4301 if (a->expr->rank > 0)
4302 ADD_CHAR ('r');
4303 else
4304 ADD_CHAR ('R');
4306 num_char_args += a->expr->ts.type == BT_CHARACTER;
4307 gcc_assert (fp - fnspec_buf + num_char_args <= MAX_SPEC_ARG*2);
4310 for (i = 0; i < num_char_args; i++)
4311 ADD_CHAR ('.');
4313 *fp = '\0';
4314 return fnspec_buf;
4317 #undef MAX_SPEC_ARG
4318 #undef ADD_CHAR
4320 /* Generate the right symbol for the specific intrinsic function and
4321 modify the expr accordingly. This assumes that absent optional
4322 arguments should be removed. */
4324 gfc_symbol *
4325 specific_intrinsic_symbol (gfc_expr *expr)
4327 gfc_symbol *sym;
4329 sym = gfc_find_intrinsic_symbol (expr);
4330 if (sym == NULL)
4332 sym = gfc_get_intrinsic_function_symbol (expr);
4333 sym->ts = expr->ts;
4334 if (sym->ts.type == BT_CHARACTER && sym->ts.u.cl)
4335 sym->ts.u.cl = gfc_new_charlen (sym->ns, NULL);
4337 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4338 expr->value.function.actual, true);
4339 sym->backend_decl
4340 = gfc_get_extern_function_decl (sym, expr->value.function.actual,
4341 intrinsic_fnspec (expr));
4344 remove_empty_actual_arguments (&(expr->value.function.actual));
4346 return sym;
4349 /* Generate a call to an external intrinsic function. FIXME: So far,
4350 this only works for functions which are called with well-defined
4351 types; CSHIFT and friends will come later. */
4353 static void
4354 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
4356 gfc_symbol *sym;
4357 vec<tree, va_gc> *append_args;
4358 bool specific_symbol;
4360 gcc_assert (!se->ss || se->ss->info->expr == expr);
4362 if (se->ss)
4363 gcc_assert (expr->rank > 0);
4364 else
4365 gcc_assert (expr->rank == 0);
4367 switch (expr->value.function.isym->id)
4369 case GFC_ISYM_ANY:
4370 case GFC_ISYM_ALL:
4371 case GFC_ISYM_FINDLOC:
4372 case GFC_ISYM_MAXLOC:
4373 case GFC_ISYM_MINLOC:
4374 case GFC_ISYM_MAXVAL:
4375 case GFC_ISYM_MINVAL:
4376 case GFC_ISYM_NORM2:
4377 case GFC_ISYM_PRODUCT:
4378 case GFC_ISYM_SUM:
4379 specific_symbol = true;
4380 break;
4381 default:
4382 specific_symbol = false;
4385 if (specific_symbol)
4387 /* Need to copy here because specific_intrinsic_symbol modifies
4388 expr to omit the absent optional arguments. */
4389 expr = gfc_copy_expr (expr);
4390 sym = specific_intrinsic_symbol (expr);
4392 else
4393 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
4395 /* Calls to libgfortran_matmul need to be appended special arguments,
4396 to be able to call the BLAS ?gemm functions if required and possible. */
4397 append_args = NULL;
4398 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
4399 && !expr->external_blas
4400 && sym->ts.type != BT_LOGICAL)
4402 tree cint = gfc_get_int_type (gfc_c_int_kind);
4404 if (flag_external_blas
4405 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
4406 && (sym->ts.kind == 4 || sym->ts.kind == 8))
4408 tree gemm_fndecl;
4410 if (sym->ts.type == BT_REAL)
4412 if (sym->ts.kind == 4)
4413 gemm_fndecl = gfor_fndecl_sgemm;
4414 else
4415 gemm_fndecl = gfor_fndecl_dgemm;
4417 else
4419 if (sym->ts.kind == 4)
4420 gemm_fndecl = gfor_fndecl_cgemm;
4421 else
4422 gemm_fndecl = gfor_fndecl_zgemm;
4425 vec_alloc (append_args, 3);
4426 append_args->quick_push (build_int_cst (cint, 1));
4427 append_args->quick_push (build_int_cst (cint,
4428 flag_blas_matmul_limit));
4429 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
4430 gemm_fndecl));
4432 else
4434 vec_alloc (append_args, 3);
4435 append_args->quick_push (build_int_cst (cint, 0));
4436 append_args->quick_push (build_int_cst (cint, 0));
4437 append_args->quick_push (null_pointer_node);
4441 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4442 append_args);
4444 if (specific_symbol)
4445 gfc_free_expr (expr);
4446 else
4447 gfc_free_symbol (sym);
4450 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4451 Implemented as
4452 any(a)
4454 forall (i=...)
4455 if (a[i] != 0)
4456 return 1
4457 end forall
4458 return 0
4460 all(a)
4462 forall (i=...)
4463 if (a[i] == 0)
4464 return 0
4465 end forall
4466 return 1
4469 static void
4470 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
4472 tree resvar;
4473 stmtblock_t block;
4474 stmtblock_t body;
4475 tree type;
4476 tree tmp;
4477 tree found;
4478 gfc_loopinfo loop;
4479 gfc_actual_arglist *actual;
4480 gfc_ss *arrayss;
4481 gfc_se arrayse;
4482 tree exit_label;
4484 if (se->ss)
4486 gfc_conv_intrinsic_funcall (se, expr);
4487 return;
4490 actual = expr->value.function.actual;
4491 type = gfc_typenode_for_spec (&expr->ts);
4492 /* Initialize the result. */
4493 resvar = gfc_create_var (type, "test");
4494 if (op == EQ_EXPR)
4495 tmp = convert (type, boolean_true_node);
4496 else
4497 tmp = convert (type, boolean_false_node);
4498 gfc_add_modify (&se->pre, resvar, tmp);
4500 /* Walk the arguments. */
4501 arrayss = gfc_walk_expr (actual->expr);
4502 gcc_assert (arrayss != gfc_ss_terminator);
4504 /* Initialize the scalarizer. */
4505 gfc_init_loopinfo (&loop);
4506 exit_label = gfc_build_label_decl (NULL_TREE);
4507 TREE_USED (exit_label) = 1;
4508 gfc_add_ss_to_loop (&loop, arrayss);
4510 /* Initialize the loop. */
4511 gfc_conv_ss_startstride (&loop);
4512 gfc_conv_loop_setup (&loop, &expr->where);
4514 gfc_mark_ss_chain_used (arrayss, 1);
4515 /* Generate the loop body. */
4516 gfc_start_scalarized_body (&loop, &body);
4518 /* If the condition matches then set the return value. */
4519 gfc_start_block (&block);
4520 if (op == EQ_EXPR)
4521 tmp = convert (type, boolean_false_node);
4522 else
4523 tmp = convert (type, boolean_true_node);
4524 gfc_add_modify (&block, resvar, tmp);
4526 /* And break out of the loop. */
4527 tmp = build1_v (GOTO_EXPR, exit_label);
4528 gfc_add_expr_to_block (&block, tmp);
4530 found = gfc_finish_block (&block);
4532 /* Check this element. */
4533 gfc_init_se (&arrayse, NULL);
4534 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4535 arrayse.ss = arrayss;
4536 gfc_conv_expr_val (&arrayse, actual->expr);
4538 gfc_add_block_to_block (&body, &arrayse.pre);
4539 tmp = fold_build2_loc (input_location, op, logical_type_node, arrayse.expr,
4540 build_int_cst (TREE_TYPE (arrayse.expr), 0));
4541 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
4542 gfc_add_expr_to_block (&body, tmp);
4543 gfc_add_block_to_block (&body, &arrayse.post);
4545 gfc_trans_scalarizing_loops (&loop, &body);
4547 /* Add the exit label. */
4548 tmp = build1_v (LABEL_EXPR, exit_label);
4549 gfc_add_expr_to_block (&loop.pre, tmp);
4551 gfc_add_block_to_block (&se->pre, &loop.pre);
4552 gfc_add_block_to_block (&se->pre, &loop.post);
4553 gfc_cleanup_loop (&loop);
4555 se->expr = resvar;
4559 /* Generate the constant 180 / pi, which is used in the conversion
4560 of acosd(), asind(), atand(), atan2d(). */
4562 static tree
4563 rad2deg (int kind)
4565 tree retval;
4566 mpfr_t pi, t0;
4568 gfc_set_model_kind (kind);
4569 mpfr_init (pi);
4570 mpfr_init (t0);
4571 mpfr_set_si (t0, 180, GFC_RND_MODE);
4572 mpfr_const_pi (pi, GFC_RND_MODE);
4573 mpfr_div (t0, t0, pi, GFC_RND_MODE);
4574 retval = gfc_conv_mpfr_to_tree (t0, kind, 0);
4575 mpfr_clear (t0);
4576 mpfr_clear (pi);
4577 return retval;
4581 static gfc_intrinsic_map_t *
4582 gfc_lookup_intrinsic (gfc_isym_id id)
4584 gfc_intrinsic_map_t *m = gfc_intrinsic_map;
4585 for (; m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
4586 if (id == m->id)
4587 break;
4588 gcc_assert (id == m->id);
4589 return m;
4593 /* ACOSD(x) is translated into ACOS(x) * 180 / pi.
4594 ASIND(x) is translated into ASIN(x) * 180 / pi.
4595 ATAND(x) is translated into ATAN(x) * 180 / pi. */
4597 static void
4598 gfc_conv_intrinsic_atrigd (gfc_se * se, gfc_expr * expr, gfc_isym_id id)
4600 tree arg;
4601 tree atrigd;
4602 tree type;
4603 gfc_intrinsic_map_t *m;
4605 type = gfc_typenode_for_spec (&expr->ts);
4607 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4609 switch (id)
4611 case GFC_ISYM_ACOSD:
4612 m = gfc_lookup_intrinsic (GFC_ISYM_ACOS);
4613 break;
4614 case GFC_ISYM_ASIND:
4615 m = gfc_lookup_intrinsic (GFC_ISYM_ASIN);
4616 break;
4617 case GFC_ISYM_ATAND:
4618 m = gfc_lookup_intrinsic (GFC_ISYM_ATAN);
4619 break;
4620 default:
4621 gcc_unreachable ();
4623 atrigd = gfc_get_intrinsic_lib_fndecl (m, expr);
4624 atrigd = build_call_expr_loc (input_location, atrigd, 1, arg);
4626 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atrigd,
4627 fold_convert (type, rad2deg (expr->ts.kind)));
4631 /* COTAN(X) is translated into -TAN(X+PI/2) for REAL argument and
4632 COS(X) / SIN(X) for COMPLEX argument. */
4634 static void
4635 gfc_conv_intrinsic_cotan (gfc_se *se, gfc_expr *expr)
4637 gfc_intrinsic_map_t *m;
4638 tree arg;
4639 tree type;
4641 type = gfc_typenode_for_spec (&expr->ts);
4642 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4644 if (expr->ts.type == BT_REAL)
4646 tree tan;
4647 tree tmp;
4648 mpfr_t pio2;
4650 /* Create pi/2. */
4651 gfc_set_model_kind (expr->ts.kind);
4652 mpfr_init (pio2);
4653 mpfr_const_pi (pio2, GFC_RND_MODE);
4654 mpfr_div_ui (pio2, pio2, 2, GFC_RND_MODE);
4655 tmp = gfc_conv_mpfr_to_tree (pio2, expr->ts.kind, 0);
4656 mpfr_clear (pio2);
4658 /* Find tan builtin function. */
4659 m = gfc_lookup_intrinsic (GFC_ISYM_TAN);
4660 tan = gfc_get_intrinsic_lib_fndecl (m, expr);
4661 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, arg, tmp);
4662 tan = build_call_expr_loc (input_location, tan, 1, tmp);
4663 se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tan);
4665 else
4667 tree sin;
4668 tree cos;
4670 /* Find cos builtin function. */
4671 m = gfc_lookup_intrinsic (GFC_ISYM_COS);
4672 cos = gfc_get_intrinsic_lib_fndecl (m, expr);
4673 cos = build_call_expr_loc (input_location, cos, 1, arg);
4675 /* Find sin builtin function. */
4676 m = gfc_lookup_intrinsic (GFC_ISYM_SIN);
4677 sin = gfc_get_intrinsic_lib_fndecl (m, expr);
4678 sin = build_call_expr_loc (input_location, sin, 1, arg);
4680 /* Divide cos by sin. */
4681 se->expr = fold_build2_loc (input_location, RDIV_EXPR, type, cos, sin);
4686 /* COTAND(X) is translated into -TAND(X+90) for REAL argument. */
4688 static void
4689 gfc_conv_intrinsic_cotand (gfc_se *se, gfc_expr *expr)
4691 tree arg;
4692 tree type;
4693 tree ninety_tree;
4694 mpfr_t ninety;
4696 type = gfc_typenode_for_spec (&expr->ts);
4697 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4699 gfc_set_model_kind (expr->ts.kind);
4701 /* Build the tree for x + 90. */
4702 mpfr_init_set_ui (ninety, 90, GFC_RND_MODE);
4703 ninety_tree = gfc_conv_mpfr_to_tree (ninety, expr->ts.kind, 0);
4704 arg = fold_build2_loc (input_location, PLUS_EXPR, type, arg, ninety_tree);
4705 mpfr_clear (ninety);
4707 /* Find tand. */
4708 gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_TAND);
4709 tree tand = gfc_get_intrinsic_lib_fndecl (m, expr);
4710 tand = build_call_expr_loc (input_location, tand, 1, arg);
4712 se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tand);
4716 /* ATAN2D(Y,X) is translated into ATAN2(Y,X) * 180 / PI. */
4718 static void
4719 gfc_conv_intrinsic_atan2d (gfc_se *se, gfc_expr *expr)
4721 tree args[2];
4722 tree atan2d;
4723 tree type;
4725 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4726 type = TREE_TYPE (args[0]);
4728 gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_ATAN2);
4729 atan2d = gfc_get_intrinsic_lib_fndecl (m, expr);
4730 atan2d = build_call_expr_loc (input_location, atan2d, 2, args[0], args[1]);
4732 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atan2d,
4733 rad2deg (expr->ts.kind));
4737 /* COUNT(A) = Number of true elements in A. */
4738 static void
4739 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
4741 tree resvar;
4742 tree type;
4743 stmtblock_t body;
4744 tree tmp;
4745 gfc_loopinfo loop;
4746 gfc_actual_arglist *actual;
4747 gfc_ss *arrayss;
4748 gfc_se arrayse;
4750 if (se->ss)
4752 gfc_conv_intrinsic_funcall (se, expr);
4753 return;
4756 actual = expr->value.function.actual;
4758 type = gfc_typenode_for_spec (&expr->ts);
4759 /* Initialize the result. */
4760 resvar = gfc_create_var (type, "count");
4761 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4763 /* Walk the arguments. */
4764 arrayss = gfc_walk_expr (actual->expr);
4765 gcc_assert (arrayss != gfc_ss_terminator);
4767 /* Initialize the scalarizer. */
4768 gfc_init_loopinfo (&loop);
4769 gfc_add_ss_to_loop (&loop, arrayss);
4771 /* Initialize the loop. */
4772 gfc_conv_ss_startstride (&loop);
4773 gfc_conv_loop_setup (&loop, &expr->where);
4775 gfc_mark_ss_chain_used (arrayss, 1);
4776 /* Generate the loop body. */
4777 gfc_start_scalarized_body (&loop, &body);
4779 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
4780 resvar, build_int_cst (TREE_TYPE (resvar), 1));
4781 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
4783 gfc_init_se (&arrayse, NULL);
4784 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4785 arrayse.ss = arrayss;
4786 gfc_conv_expr_val (&arrayse, actual->expr);
4787 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
4788 build_empty_stmt (input_location));
4790 gfc_add_block_to_block (&body, &arrayse.pre);
4791 gfc_add_expr_to_block (&body, tmp);
4792 gfc_add_block_to_block (&body, &arrayse.post);
4794 gfc_trans_scalarizing_loops (&loop, &body);
4796 gfc_add_block_to_block (&se->pre, &loop.pre);
4797 gfc_add_block_to_block (&se->pre, &loop.post);
4798 gfc_cleanup_loop (&loop);
4800 se->expr = resvar;
4804 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4805 struct and return the corresponding loopinfo. */
4807 static gfc_loopinfo *
4808 enter_nested_loop (gfc_se *se)
4810 se->ss = se->ss->nested_ss;
4811 gcc_assert (se->ss == se->ss->loop->ss);
4813 return se->ss->loop;
4816 /* Build the condition for a mask, which may be optional. */
4818 static tree
4819 conv_mask_condition (gfc_se *maskse, gfc_expr *maskexpr,
4820 bool optional_mask)
4822 tree present;
4823 tree type;
4825 if (optional_mask)
4827 type = TREE_TYPE (maskse->expr);
4828 present = gfc_conv_expr_present (maskexpr->symtree->n.sym);
4829 present = convert (type, present);
4830 present = fold_build1_loc (input_location, TRUTH_NOT_EXPR, type,
4831 present);
4832 return fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
4833 type, present, maskse->expr);
4835 else
4836 return maskse->expr;
4839 /* Inline implementation of the sum and product intrinsics. */
4840 static void
4841 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
4842 bool norm2)
4844 tree resvar;
4845 tree scale = NULL_TREE;
4846 tree type;
4847 stmtblock_t body;
4848 stmtblock_t block;
4849 tree tmp;
4850 gfc_loopinfo loop, *ploop;
4851 gfc_actual_arglist *arg_array, *arg_mask;
4852 gfc_ss *arrayss = NULL;
4853 gfc_ss *maskss = NULL;
4854 gfc_se arrayse;
4855 gfc_se maskse;
4856 gfc_se *parent_se;
4857 gfc_expr *arrayexpr;
4858 gfc_expr *maskexpr;
4859 bool optional_mask;
4861 if (expr->rank > 0)
4863 gcc_assert (gfc_inline_intrinsic_function_p (expr));
4864 parent_se = se;
4866 else
4867 parent_se = NULL;
4869 type = gfc_typenode_for_spec (&expr->ts);
4870 /* Initialize the result. */
4871 resvar = gfc_create_var (type, "val");
4872 if (norm2)
4874 /* result = 0.0;
4875 scale = 1.0. */
4876 scale = gfc_create_var (type, "scale");
4877 gfc_add_modify (&se->pre, scale,
4878 gfc_build_const (type, integer_one_node));
4879 tmp = gfc_build_const (type, integer_zero_node);
4881 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4882 tmp = gfc_build_const (type, integer_zero_node);
4883 else if (op == NE_EXPR)
4884 /* PARITY. */
4885 tmp = convert (type, boolean_false_node);
4886 else if (op == BIT_AND_EXPR)
4887 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
4888 type, integer_one_node));
4889 else
4890 tmp = gfc_build_const (type, integer_one_node);
4892 gfc_add_modify (&se->pre, resvar, tmp);
4894 arg_array = expr->value.function.actual;
4896 arrayexpr = arg_array->expr;
4898 if (op == NE_EXPR || norm2)
4900 /* PARITY and NORM2. */
4901 maskexpr = NULL;
4902 optional_mask = false;
4904 else
4906 arg_mask = arg_array->next->next;
4907 gcc_assert (arg_mask != NULL);
4908 maskexpr = arg_mask->expr;
4909 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
4910 && maskexpr->symtree->n.sym->attr.dummy
4911 && maskexpr->symtree->n.sym->attr.optional;
4914 if (expr->rank == 0)
4916 /* Walk the arguments. */
4917 arrayss = gfc_walk_expr (arrayexpr);
4918 gcc_assert (arrayss != gfc_ss_terminator);
4920 if (maskexpr && maskexpr->rank > 0)
4922 maskss = gfc_walk_expr (maskexpr);
4923 gcc_assert (maskss != gfc_ss_terminator);
4925 else
4926 maskss = NULL;
4928 /* Initialize the scalarizer. */
4929 gfc_init_loopinfo (&loop);
4931 /* We add the mask first because the number of iterations is
4932 taken from the last ss, and this breaks if an absent
4933 optional argument is used for mask. */
4935 if (maskexpr && maskexpr->rank > 0)
4936 gfc_add_ss_to_loop (&loop, maskss);
4937 gfc_add_ss_to_loop (&loop, arrayss);
4939 /* Initialize the loop. */
4940 gfc_conv_ss_startstride (&loop);
4941 gfc_conv_loop_setup (&loop, &expr->where);
4943 if (maskexpr && maskexpr->rank > 0)
4944 gfc_mark_ss_chain_used (maskss, 1);
4945 gfc_mark_ss_chain_used (arrayss, 1);
4947 ploop = &loop;
4949 else
4950 /* All the work has been done in the parent loops. */
4951 ploop = enter_nested_loop (se);
4953 gcc_assert (ploop);
4955 /* Generate the loop body. */
4956 gfc_start_scalarized_body (ploop, &body);
4958 /* If we have a mask, only add this element if the mask is set. */
4959 if (maskexpr && maskexpr->rank > 0)
4961 gfc_init_se (&maskse, parent_se);
4962 gfc_copy_loopinfo_to_se (&maskse, ploop);
4963 if (expr->rank == 0)
4964 maskse.ss = maskss;
4965 gfc_conv_expr_val (&maskse, maskexpr);
4966 gfc_add_block_to_block (&body, &maskse.pre);
4968 gfc_start_block (&block);
4970 else
4971 gfc_init_block (&block);
4973 /* Do the actual summation/product. */
4974 gfc_init_se (&arrayse, parent_se);
4975 gfc_copy_loopinfo_to_se (&arrayse, ploop);
4976 if (expr->rank == 0)
4977 arrayse.ss = arrayss;
4978 gfc_conv_expr_val (&arrayse, arrayexpr);
4979 gfc_add_block_to_block (&block, &arrayse.pre);
4981 if (norm2)
4983 /* if (x (i) != 0.0)
4985 absX = abs(x(i))
4986 if (absX > scale)
4988 val = scale/absX;
4989 result = 1.0 + result * val * val;
4990 scale = absX;
4992 else
4994 val = absX/scale;
4995 result += val * val;
4997 } */
4998 tree res1, res2, cond, absX, val;
4999 stmtblock_t ifblock1, ifblock2, ifblock3;
5001 gfc_init_block (&ifblock1);
5003 absX = gfc_create_var (type, "absX");
5004 gfc_add_modify (&ifblock1, absX,
5005 fold_build1_loc (input_location, ABS_EXPR, type,
5006 arrayse.expr));
5007 val = gfc_create_var (type, "val");
5008 gfc_add_expr_to_block (&ifblock1, val);
5010 gfc_init_block (&ifblock2);
5011 gfc_add_modify (&ifblock2, val,
5012 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
5013 absX));
5014 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
5015 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
5016 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
5017 gfc_build_const (type, integer_one_node));
5018 gfc_add_modify (&ifblock2, resvar, res1);
5019 gfc_add_modify (&ifblock2, scale, absX);
5020 res1 = gfc_finish_block (&ifblock2);
5022 gfc_init_block (&ifblock3);
5023 gfc_add_modify (&ifblock3, val,
5024 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
5025 scale));
5026 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
5027 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
5028 gfc_add_modify (&ifblock3, resvar, res2);
5029 res2 = gfc_finish_block (&ifblock3);
5031 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
5032 absX, scale);
5033 tmp = build3_v (COND_EXPR, cond, res1, res2);
5034 gfc_add_expr_to_block (&ifblock1, tmp);
5035 tmp = gfc_finish_block (&ifblock1);
5037 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
5038 arrayse.expr,
5039 gfc_build_const (type, integer_zero_node));
5041 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
5042 gfc_add_expr_to_block (&block, tmp);
5044 else
5046 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
5047 gfc_add_modify (&block, resvar, tmp);
5050 gfc_add_block_to_block (&block, &arrayse.post);
5052 if (maskexpr && maskexpr->rank > 0)
5054 /* We enclose the above in if (mask) {...} . If the mask is an
5055 optional argument, generate
5056 IF (.NOT. PRESENT(MASK) .OR. MASK(I)). */
5057 tree ifmask;
5058 tmp = gfc_finish_block (&block);
5059 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5060 tmp = build3_v (COND_EXPR, ifmask, tmp,
5061 build_empty_stmt (input_location));
5063 else
5064 tmp = gfc_finish_block (&block);
5065 gfc_add_expr_to_block (&body, tmp);
5067 gfc_trans_scalarizing_loops (ploop, &body);
5069 /* For a scalar mask, enclose the loop in an if statement. */
5070 if (maskexpr && maskexpr->rank == 0)
5072 gfc_init_block (&block);
5073 gfc_add_block_to_block (&block, &ploop->pre);
5074 gfc_add_block_to_block (&block, &ploop->post);
5075 tmp = gfc_finish_block (&block);
5077 if (expr->rank > 0)
5079 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
5080 build_empty_stmt (input_location));
5081 gfc_advance_se_ss_chain (se);
5083 else
5085 tree ifmask;
5087 gcc_assert (expr->rank == 0);
5088 gfc_init_se (&maskse, NULL);
5089 gfc_conv_expr_val (&maskse, maskexpr);
5090 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5091 tmp = build3_v (COND_EXPR, ifmask, tmp,
5092 build_empty_stmt (input_location));
5095 gfc_add_expr_to_block (&block, tmp);
5096 gfc_add_block_to_block (&se->pre, &block);
5097 gcc_assert (se->post.head == NULL);
5099 else
5101 gfc_add_block_to_block (&se->pre, &ploop->pre);
5102 gfc_add_block_to_block (&se->pre, &ploop->post);
5105 if (expr->rank == 0)
5106 gfc_cleanup_loop (ploop);
5108 if (norm2)
5110 /* result = scale * sqrt(result). */
5111 tree sqrt;
5112 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
5113 resvar = build_call_expr_loc (input_location,
5114 sqrt, 1, resvar);
5115 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
5118 se->expr = resvar;
5122 /* Inline implementation of the dot_product intrinsic. This function
5123 is based on gfc_conv_intrinsic_arith (the previous function). */
5124 static void
5125 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
5127 tree resvar;
5128 tree type;
5129 stmtblock_t body;
5130 stmtblock_t block;
5131 tree tmp;
5132 gfc_loopinfo loop;
5133 gfc_actual_arglist *actual;
5134 gfc_ss *arrayss1, *arrayss2;
5135 gfc_se arrayse1, arrayse2;
5136 gfc_expr *arrayexpr1, *arrayexpr2;
5138 type = gfc_typenode_for_spec (&expr->ts);
5140 /* Initialize the result. */
5141 resvar = gfc_create_var (type, "val");
5142 if (expr->ts.type == BT_LOGICAL)
5143 tmp = build_int_cst (type, 0);
5144 else
5145 tmp = gfc_build_const (type, integer_zero_node);
5147 gfc_add_modify (&se->pre, resvar, tmp);
5149 /* Walk argument #1. */
5150 actual = expr->value.function.actual;
5151 arrayexpr1 = actual->expr;
5152 arrayss1 = gfc_walk_expr (arrayexpr1);
5153 gcc_assert (arrayss1 != gfc_ss_terminator);
5155 /* Walk argument #2. */
5156 actual = actual->next;
5157 arrayexpr2 = actual->expr;
5158 arrayss2 = gfc_walk_expr (arrayexpr2);
5159 gcc_assert (arrayss2 != gfc_ss_terminator);
5161 /* Initialize the scalarizer. */
5162 gfc_init_loopinfo (&loop);
5163 gfc_add_ss_to_loop (&loop, arrayss1);
5164 gfc_add_ss_to_loop (&loop, arrayss2);
5166 /* Initialize the loop. */
5167 gfc_conv_ss_startstride (&loop);
5168 gfc_conv_loop_setup (&loop, &expr->where);
5170 gfc_mark_ss_chain_used (arrayss1, 1);
5171 gfc_mark_ss_chain_used (arrayss2, 1);
5173 /* Generate the loop body. */
5174 gfc_start_scalarized_body (&loop, &body);
5175 gfc_init_block (&block);
5177 /* Make the tree expression for [conjg(]array1[)]. */
5178 gfc_init_se (&arrayse1, NULL);
5179 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
5180 arrayse1.ss = arrayss1;
5181 gfc_conv_expr_val (&arrayse1, arrayexpr1);
5182 if (expr->ts.type == BT_COMPLEX)
5183 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
5184 arrayse1.expr);
5185 gfc_add_block_to_block (&block, &arrayse1.pre);
5187 /* Make the tree expression for array2. */
5188 gfc_init_se (&arrayse2, NULL);
5189 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
5190 arrayse2.ss = arrayss2;
5191 gfc_conv_expr_val (&arrayse2, arrayexpr2);
5192 gfc_add_block_to_block (&block, &arrayse2.pre);
5194 /* Do the actual product and sum. */
5195 if (expr->ts.type == BT_LOGICAL)
5197 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
5198 arrayse1.expr, arrayse2.expr);
5199 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
5201 else
5203 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
5204 arrayse2.expr);
5205 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
5207 gfc_add_modify (&block, resvar, tmp);
5209 /* Finish up the loop block and the loop. */
5210 tmp = gfc_finish_block (&block);
5211 gfc_add_expr_to_block (&body, tmp);
5213 gfc_trans_scalarizing_loops (&loop, &body);
5214 gfc_add_block_to_block (&se->pre, &loop.pre);
5215 gfc_add_block_to_block (&se->pre, &loop.post);
5216 gfc_cleanup_loop (&loop);
5218 se->expr = resvar;
5222 /* Tells whether the expression E is a reference to an optional variable whose
5223 presence is not known at compile time. Those are variable references without
5224 subreference; if there is a subreference, we can assume the variable is
5225 present. We have to special case full arrays, which we represent with a fake
5226 "full" reference, and class descriptors for which a reference to data is not
5227 really a subreference. */
5229 bool
5230 maybe_absent_optional_variable (gfc_expr *e)
5232 if (!(e && e->expr_type == EXPR_VARIABLE))
5233 return false;
5235 gfc_symbol *sym = e->symtree->n.sym;
5236 if (!sym->attr.optional)
5237 return false;
5239 gfc_ref *ref = e->ref;
5240 if (ref == nullptr)
5241 return true;
5243 if (ref->type == REF_ARRAY
5244 && ref->u.ar.type == AR_FULL
5245 && ref->next == nullptr)
5246 return true;
5248 if (!(sym->ts.type == BT_CLASS
5249 && ref->type == REF_COMPONENT
5250 && ref->u.c.component == CLASS_DATA (sym)))
5251 return false;
5253 gfc_ref *next_ref = ref->next;
5254 if (next_ref == nullptr)
5255 return true;
5257 if (next_ref->type == REF_ARRAY
5258 && next_ref->u.ar.type == AR_FULL
5259 && next_ref->next == nullptr)
5260 return true;
5262 return false;
5266 /* Remove unneeded kind= argument from actual argument list when the
5267 result conversion is dealt with in a different place. */
5269 static void
5270 strip_kind_from_actual (gfc_actual_arglist * actual)
5272 for (gfc_actual_arglist *a = actual; a; a = a->next)
5274 if (a && a->name && strcmp (a->name, "kind") == 0)
5276 gfc_free_expr (a->expr);
5277 a->expr = NULL;
5282 /* Emit code for minloc or maxloc intrinsic. There are many different cases
5283 we need to handle. For performance reasons we sometimes create two
5284 loops instead of one, where the second one is much simpler.
5285 Examples for minloc intrinsic:
5286 A: Result is scalar.
5287 1) Array mask is used and NaNs need to be supported:
5288 limit = Infinity;
5289 pos = 0;
5290 S = from;
5291 while (S <= to) {
5292 if (mask[S]) {
5293 if (pos == 0) pos = S + (1 - from);
5294 if (a[S] <= limit) {
5295 limit = a[S];
5296 pos = S + (1 - from);
5297 goto lab1;
5300 S++;
5302 goto lab2;
5303 lab1:;
5304 while (S <= to) {
5305 if (mask[S])
5306 if (a[S] < limit) {
5307 limit = a[S];
5308 pos = S + (1 - from);
5310 S++;
5312 lab2:;
5313 2) NaNs need to be supported, but it is known at compile time or cheaply
5314 at runtime whether array is nonempty or not:
5315 limit = Infinity;
5316 pos = 0;
5317 S = from;
5318 while (S <= to) {
5319 if (a[S] <= limit) {
5320 limit = a[S];
5321 pos = S + (1 - from);
5322 goto lab1;
5324 S++;
5326 if (from <= to) pos = 1;
5327 goto lab2;
5328 lab1:;
5329 while (S <= to) {
5330 if (a[S] < limit) {
5331 limit = a[S];
5332 pos = S + (1 - from);
5334 S++;
5336 lab2:;
5337 3) NaNs aren't supported, array mask is used:
5338 limit = infinities_supported ? Infinity : huge (limit);
5339 pos = 0;
5340 S = from;
5341 while (S <= to) {
5342 if (mask[S]) {
5343 limit = a[S];
5344 pos = S + (1 - from);
5345 goto lab1;
5347 S++;
5349 goto lab2;
5350 lab1:;
5351 while (S <= to) {
5352 if (mask[S])
5353 if (a[S] < limit) {
5354 limit = a[S];
5355 pos = S + (1 - from);
5357 S++;
5359 lab2:;
5360 4) Same without array mask:
5361 limit = infinities_supported ? Infinity : huge (limit);
5362 pos = (from <= to) ? 1 : 0;
5363 S = from;
5364 while (S <= to) {
5365 if (a[S] < limit) {
5366 limit = a[S];
5367 pos = S + (1 - from);
5369 S++;
5371 B: Array result, non-CHARACTER type, DIM absent
5372 Generate similar code as in the scalar case, using a collection of
5373 variables (one per dimension) instead of a single variable as result.
5374 Picking only cases 1) and 4) with ARRAY of rank 2, the generated code
5375 becomes:
5376 1) Array mask is used and NaNs need to be supported:
5377 limit = Infinity;
5378 pos0 = 0;
5379 pos1 = 0;
5380 S1 = from1;
5381 second_loop_entry = false;
5382 while (S1 <= to1) {
5383 S0 = from0;
5384 while (s0 <= to0 {
5385 if (mask[S1][S0]) {
5386 if (pos0 == 0) {
5387 pos0 = S0 + (1 - from0);
5388 pos1 = S1 + (1 - from1);
5390 if (a[S1][S0] <= limit) {
5391 limit = a[S1][S0];
5392 pos0 = S0 + (1 - from0);
5393 pos1 = S1 + (1 - from1);
5394 second_loop_entry = true;
5395 goto lab1;
5398 S0++;
5400 S1++;
5402 goto lab2;
5403 lab1:;
5404 S1 = second_loop_entry ? S1 : from1;
5405 while (S1 <= to1) {
5406 S0 = second_loop_entry ? S0 : from0;
5407 while (S0 <= to0) {
5408 if (mask[S1][S0])
5409 if (a[S1][S0] < limit) {
5410 limit = a[S1][S0];
5411 pos0 = S + (1 - from0);
5412 pos1 = S + (1 - from1);
5414 second_loop_entry = false;
5415 S0++;
5417 S1++;
5419 lab2:;
5420 result = { pos0, pos1 };
5422 4) NANs aren't supported, no array mask.
5423 limit = infinities_supported ? Infinity : huge (limit);
5424 pos0 = (from0 <= to0 && from1 <= to1) ? 1 : 0;
5425 pos1 = (from0 <= to0 && from1 <= to1) ? 1 : 0;
5426 S1 = from1;
5427 while (S1 <= to1) {
5428 S0 = from0;
5429 while (S0 <= to0) {
5430 if (a[S1][S0] < limit) {
5431 limit = a[S1][S0];
5432 pos0 = S + (1 - from0);
5433 pos1 = S + (1 - from1);
5435 S0++;
5437 S1++;
5439 result = { pos0, pos1 };
5440 C: Otherwise, a call is generated.
5441 For 2) and 4), if mask is scalar, this all goes into a conditional,
5442 setting pos = 0; in the else branch.
5444 Since we now also support the BACK argument, instead of using
5445 if (a[S] < limit), we now use
5447 if (back)
5448 cond = a[S] <= limit;
5449 else
5450 cond = a[S] < limit;
5451 if (cond) {
5452 ....
5454 The optimizer is smart enough to move the condition out of the loop.
5455 They are now marked as unlikely too for further speedup. */
5457 static void
5458 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
5460 stmtblock_t body;
5461 stmtblock_t block;
5462 stmtblock_t ifblock;
5463 stmtblock_t elseblock;
5464 tree limit;
5465 tree type;
5466 tree tmp;
5467 tree cond;
5468 tree elsetmp;
5469 tree ifbody;
5470 tree offset[GFC_MAX_DIMENSIONS];
5471 tree nonempty;
5472 tree lab1, lab2;
5473 tree b_if, b_else;
5474 tree back;
5475 gfc_loopinfo loop;
5476 gfc_actual_arglist *actual;
5477 gfc_ss *arrayss;
5478 gfc_ss *maskss;
5479 gfc_se arrayse;
5480 gfc_se maskse;
5481 gfc_expr *arrayexpr;
5482 gfc_expr *maskexpr;
5483 gfc_expr *backexpr;
5484 gfc_se backse;
5485 tree pos[GFC_MAX_DIMENSIONS];
5486 tree idx[GFC_MAX_DIMENSIONS];
5487 tree result_var = NULL_TREE;
5488 int n;
5489 bool optional_mask;
5491 actual = expr->value.function.actual;
5493 /* The last argument, BACK, is passed by value. Ensure that
5494 by setting its name to %VAL. */
5495 for (gfc_actual_arglist *a = actual; a; a = a->next)
5497 if (a->next == NULL)
5498 a->name = "%VAL";
5501 if (se->ss)
5503 if (se->ss->info->useflags)
5505 /* The inline implementation of MINLOC/MAXLOC has been generated
5506 before, out of the scalarization loop; now we can just use the
5507 result. */
5508 gfc_conv_tmp_array_ref (se);
5509 return;
5511 else if (!gfc_inline_intrinsic_function_p (expr))
5513 gfc_conv_intrinsic_funcall (se, expr);
5514 return;
5518 arrayexpr = actual->expr;
5520 /* Special case for character maxloc. Remove unneeded actual
5521 arguments, then call a library function. */
5523 if (arrayexpr->ts.type == BT_CHARACTER)
5525 gfc_actual_arglist *a;
5526 a = actual;
5527 strip_kind_from_actual (a);
5528 while (a)
5530 if (a->name && strcmp (a->name, "dim") == 0)
5532 gfc_free_expr (a->expr);
5533 a->expr = NULL;
5535 a = a->next;
5537 gfc_conv_intrinsic_funcall (se, expr);
5538 return;
5541 type = gfc_typenode_for_spec (&expr->ts);
5543 if (expr->rank > 0)
5545 gfc_array_spec as;
5546 memset (&as, 0, sizeof (as));
5548 as.rank = 1;
5549 as.lower[0] = gfc_get_int_expr (gfc_index_integer_kind,
5550 &arrayexpr->where,
5551 HOST_WIDE_INT_1);
5552 as.upper[0] = gfc_get_int_expr (gfc_index_integer_kind,
5553 &arrayexpr->where,
5554 arrayexpr->rank);
5556 tree array = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
5558 result_var = gfc_create_var (array, "loc_result");
5561 /* Initialize the result. */
5562 for (int i = 0; i < arrayexpr->rank; i++)
5564 pos[i] = gfc_create_var (gfc_array_index_type,
5565 gfc_get_string ("pos%d", i));
5566 offset[i] = gfc_create_var (gfc_array_index_type,
5567 gfc_get_string ("offset%d", i));
5568 idx[i] = gfc_create_var (gfc_array_index_type,
5569 gfc_get_string ("idx%d", i));
5572 /* Walk the arguments. */
5573 arrayss = gfc_walk_expr (arrayexpr);
5574 gcc_assert (arrayss != gfc_ss_terminator);
5576 actual = actual->next->next;
5577 gcc_assert (actual);
5578 maskexpr = actual->expr;
5579 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
5580 && maskexpr->symtree->n.sym->attr.dummy
5581 && maskexpr->symtree->n.sym->attr.optional;
5582 backexpr = actual->next->next->expr;
5584 gfc_init_se (&backse, NULL);
5585 if (backexpr == nullptr)
5586 back = logical_false_node;
5587 else if (maybe_absent_optional_variable (backexpr))
5589 /* This should have been checked already by
5590 maybe_absent_optional_variable. */
5591 gcc_checking_assert (backexpr->expr_type == EXPR_VARIABLE);
5593 gfc_conv_expr (&backse, backexpr);
5594 tree present = gfc_conv_expr_present (backexpr->symtree->n.sym, false);
5595 back = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
5596 logical_type_node, present, backse.expr);
5598 else
5600 gfc_conv_expr (&backse, backexpr);
5601 back = backse.expr;
5603 gfc_add_block_to_block (&se->pre, &backse.pre);
5604 back = gfc_evaluate_now_loc (input_location, back, &se->pre);
5605 gfc_add_block_to_block (&se->pre, &backse.post);
5607 nonempty = NULL;
5608 if (maskexpr && maskexpr->rank != 0)
5610 maskss = gfc_walk_expr (maskexpr);
5611 gcc_assert (maskss != gfc_ss_terminator);
5613 else
5615 mpz_t asize;
5616 if (gfc_array_size (arrayexpr, &asize))
5618 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
5619 mpz_clear (asize);
5620 nonempty = fold_build2_loc (input_location, GT_EXPR,
5621 logical_type_node, nonempty,
5622 gfc_index_zero_node);
5624 maskss = NULL;
5627 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
5628 switch (arrayexpr->ts.type)
5630 case BT_REAL:
5631 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
5632 break;
5634 case BT_INTEGER:
5635 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
5636 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
5637 arrayexpr->ts.kind);
5638 break;
5640 case BT_UNSIGNED:
5641 /* For MAXVAL, the minimum is zero, for MINVAL it is HUGE(). */
5642 if (op == GT_EXPR)
5644 tmp = gfc_get_unsigned_type (arrayexpr->ts.kind);
5645 tmp = build_int_cst (tmp, 0);
5647 else
5649 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
5650 tmp = gfc_conv_mpz_unsigned_to_tree (gfc_unsigned_kinds[n].huge,
5651 expr->ts.kind);
5653 break;
5655 default:
5656 gcc_unreachable ();
5659 /* We start with the most negative possible value for MAXLOC, and the most
5660 positive possible value for MINLOC. The most negative possible value is
5661 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5662 possible value is HUGE in both cases. BT_UNSIGNED has already been dealt
5663 with above. */
5664 if (op == GT_EXPR && expr->ts.type != BT_UNSIGNED)
5665 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
5666 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
5667 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
5668 build_int_cst (TREE_TYPE (tmp), 1));
5670 gfc_add_modify (&se->pre, limit, tmp);
5672 /* If we are in a case where we generate two sets of loops, the second one
5673 should continue where the first stopped instead of restarting from the
5674 beginning. So nested loops in the second set should have a partial range
5675 on the first iteration, but they should start from the beginning and span
5676 their full range on the following iterations. So we use conditionals in
5677 the loops lower bounds, and use the following variable in those
5678 conditionals to decide whether to use the original loop bound or to use
5679 the index at which the loop from the first set stopped. */
5680 tree second_loop_entry = gfc_create_var (logical_type_node,
5681 "second_loop_entry");
5682 gfc_add_modify (&se->pre, second_loop_entry, logical_false_node);
5684 /* Initialize the scalarizer. */
5685 gfc_init_loopinfo (&loop);
5687 /* We add the mask first because the number of iterations is taken
5688 from the last ss, and this breaks if an absent optional argument
5689 is used for mask. */
5691 if (maskss)
5692 gfc_add_ss_to_loop (&loop, maskss);
5694 gfc_add_ss_to_loop (&loop, arrayss);
5696 /* Initialize the loop. */
5697 gfc_conv_ss_startstride (&loop);
5699 /* The code generated can have more than one loop in sequence (see the
5700 comment at the function header). This doesn't work well with the
5701 scalarizer, which changes arrays' offset when the scalarization loops
5702 are generated (see gfc_trans_preloop_setup). Fortunately, we can use
5703 the scalarizer temporary code to handle multiple loops. Thus, we set
5704 temp_dim here, we call gfc_mark_ss_chain_used with flag=3 later, and
5705 we use gfc_trans_scalarized_loop_boundary even later to restore
5706 offset. */
5707 loop.temp_dim = loop.dimen;
5708 gfc_conv_loop_setup (&loop, &expr->where);
5710 if (nonempty == NULL && maskss == NULL)
5712 nonempty = logical_true_node;
5714 for (int i = 0; i < loop.dimen; i++)
5716 if (!(loop.from[i] && loop.to[i]))
5718 nonempty = NULL;
5719 break;
5722 tree tmp = fold_build2_loc (input_location, LE_EXPR,
5723 logical_type_node, loop.from[i],
5724 loop.to[i]);
5726 nonempty = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
5727 logical_type_node, nonempty, tmp);
5731 lab1 = NULL;
5732 lab2 = NULL;
5733 /* Initialize the position to zero, following Fortran 2003. We are free
5734 to do this because Fortran 95 allows the result of an entirely false
5735 mask to be processor dependent. If we know at compile time the array
5736 is non-empty and no MASK is used, we can initialize to 1 to simplify
5737 the inner loop. */
5738 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
5740 tree init = fold_build3_loc (input_location, COND_EXPR,
5741 gfc_array_index_type, nonempty,
5742 gfc_index_one_node,
5743 gfc_index_zero_node);
5744 for (int i = 0; i < loop.dimen; i++)
5745 gfc_add_modify (&loop.pre, pos[i], init);
5747 else
5749 for (int i = 0; i < loop.dimen; i++)
5750 gfc_add_modify (&loop.pre, pos[i], gfc_index_zero_node);
5751 lab1 = gfc_build_label_decl (NULL_TREE);
5752 TREE_USED (lab1) = 1;
5753 lab2 = gfc_build_label_decl (NULL_TREE);
5754 TREE_USED (lab2) = 1;
5757 /* An offset must be added to the loop
5758 counter to obtain the required position. */
5759 for (int i = 0; i < loop.dimen; i++)
5761 gcc_assert (loop.from[i]);
5763 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5764 gfc_index_one_node, loop.from[i]);
5765 gfc_add_modify (&loop.pre, offset[i], tmp);
5768 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
5769 if (maskss)
5770 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
5771 /* Generate the loop body. */
5772 gfc_start_scalarized_body (&loop, &body);
5774 /* If we have a mask, only check this element if the mask is set. */
5775 if (maskss)
5777 gfc_init_se (&maskse, NULL);
5778 gfc_copy_loopinfo_to_se (&maskse, &loop);
5779 maskse.ss = maskss;
5780 gfc_conv_expr_val (&maskse, maskexpr);
5781 gfc_add_block_to_block (&body, &maskse.pre);
5783 gfc_start_block (&block);
5785 else
5786 gfc_init_block (&block);
5788 /* Compare with the current limit. */
5789 gfc_init_se (&arrayse, NULL);
5790 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5791 arrayse.ss = arrayss;
5792 gfc_conv_expr_val (&arrayse, arrayexpr);
5793 gfc_add_block_to_block (&block, &arrayse.pre);
5795 /* We do the following if this is a more extreme value. */
5796 gfc_start_block (&ifblock);
5798 /* Assign the value to the limit... */
5799 gfc_add_modify (&ifblock, limit, arrayse.expr);
5801 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
5803 stmtblock_t ifblock2;
5804 tree ifbody2;
5806 gfc_start_block (&ifblock2);
5807 for (int i = 0; i < loop.dimen; i++)
5809 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos[i]),
5810 loop.loopvar[i], offset[i]);
5811 gfc_add_modify (&ifblock2, pos[i], tmp);
5813 ifbody2 = gfc_finish_block (&ifblock2);
5815 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
5816 pos[0], gfc_index_zero_node);
5817 tmp = build3_v (COND_EXPR, cond, ifbody2,
5818 build_empty_stmt (input_location));
5819 gfc_add_expr_to_block (&block, tmp);
5822 for (int i = 0; i < loop.dimen; i++)
5824 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos[i]),
5825 loop.loopvar[i], offset[i]);
5826 gfc_add_modify (&ifblock, pos[i], tmp);
5827 gfc_add_modify (&ifblock, idx[i], loop.loopvar[i]);
5830 gfc_add_modify (&ifblock, second_loop_entry, logical_true_node);
5832 if (lab1)
5833 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
5835 ifbody = gfc_finish_block (&ifblock);
5837 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
5839 if (lab1)
5840 cond = fold_build2_loc (input_location,
5841 op == GT_EXPR ? GE_EXPR : LE_EXPR,
5842 logical_type_node, arrayse.expr, limit);
5843 else
5845 tree ifbody2, elsebody2;
5847 /* We switch to > or >= depending on the value of the BACK argument. */
5848 cond = gfc_create_var (logical_type_node, "cond");
5850 gfc_start_block (&ifblock);
5851 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5852 logical_type_node, arrayse.expr, limit);
5854 gfc_add_modify (&ifblock, cond, b_if);
5855 ifbody2 = gfc_finish_block (&ifblock);
5857 gfc_start_block (&elseblock);
5858 b_else = fold_build2_loc (input_location, op, logical_type_node,
5859 arrayse.expr, limit);
5861 gfc_add_modify (&elseblock, cond, b_else);
5862 elsebody2 = gfc_finish_block (&elseblock);
5864 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5865 back, ifbody2, elsebody2);
5867 gfc_add_expr_to_block (&block, tmp);
5870 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5871 ifbody = build3_v (COND_EXPR, cond, ifbody,
5872 build_empty_stmt (input_location));
5874 gfc_add_expr_to_block (&block, ifbody);
5876 if (maskss)
5878 /* We enclose the above in if (mask) {...}. If the mask is an
5879 optional argument, generate IF (.NOT. PRESENT(MASK)
5880 .OR. MASK(I)). */
5882 tree ifmask;
5883 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5884 tmp = gfc_finish_block (&block);
5885 tmp = build3_v (COND_EXPR, ifmask, tmp,
5886 build_empty_stmt (input_location));
5888 else
5889 tmp = gfc_finish_block (&block);
5890 gfc_add_expr_to_block (&body, tmp);
5892 if (lab1)
5894 for (int i = 0; i < loop.dimen; i++)
5895 loop.from[i] = fold_build3_loc (input_location, COND_EXPR,
5896 TREE_TYPE (loop.from[i]),
5897 second_loop_entry, idx[i],
5898 loop.from[i]);
5900 gfc_trans_scalarized_loop_boundary (&loop, &body);
5902 stmtblock_t * const outer_block = &loop.code[loop.dimen - 1];
5904 if (HONOR_NANS (DECL_MODE (limit)))
5906 if (nonempty != NULL)
5908 stmtblock_t init_block;
5909 gfc_init_block (&init_block);
5911 for (int i = 0; i < loop.dimen; i++)
5912 gfc_add_modify (&init_block, pos[i], gfc_index_one_node);
5914 tree ifbody = gfc_finish_block (&init_block);
5915 tmp = build3_v (COND_EXPR, nonempty, ifbody,
5916 build_empty_stmt (input_location));
5917 gfc_add_expr_to_block (outer_block, tmp);
5921 gfc_add_expr_to_block (outer_block, build1_v (GOTO_EXPR, lab2));
5922 gfc_add_expr_to_block (outer_block, build1_v (LABEL_EXPR, lab1));
5924 /* If we have a mask, only check this element if the mask is set. */
5925 if (maskss)
5927 gfc_init_se (&maskse, NULL);
5928 gfc_copy_loopinfo_to_se (&maskse, &loop);
5929 maskse.ss = maskss;
5930 gfc_conv_expr_val (&maskse, maskexpr);
5931 gfc_add_block_to_block (&body, &maskse.pre);
5933 gfc_start_block (&block);
5935 else
5936 gfc_init_block (&block);
5938 /* Compare with the current limit. */
5939 gfc_init_se (&arrayse, NULL);
5940 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5941 arrayse.ss = arrayss;
5942 gfc_conv_expr_val (&arrayse, arrayexpr);
5943 gfc_add_block_to_block (&block, &arrayse.pre);
5945 /* We do the following if this is a more extreme value. */
5946 gfc_start_block (&ifblock);
5948 /* Assign the value to the limit... */
5949 gfc_add_modify (&ifblock, limit, arrayse.expr);
5951 for (int i = 0; i < loop.dimen; i++)
5953 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos[i]),
5954 loop.loopvar[i], offset[i]);
5955 gfc_add_modify (&ifblock, pos[i], tmp);
5958 ifbody = gfc_finish_block (&ifblock);
5960 /* We switch to > or >= depending on the value of the BACK argument. */
5962 tree ifbody2, elsebody2;
5964 cond = gfc_create_var (logical_type_node, "cond");
5966 gfc_start_block (&ifblock);
5967 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5968 logical_type_node, arrayse.expr, limit);
5970 gfc_add_modify (&ifblock, cond, b_if);
5971 ifbody2 = gfc_finish_block (&ifblock);
5973 gfc_start_block (&elseblock);
5974 b_else = fold_build2_loc (input_location, op, logical_type_node,
5975 arrayse.expr, limit);
5977 gfc_add_modify (&elseblock, cond, b_else);
5978 elsebody2 = gfc_finish_block (&elseblock);
5980 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5981 back, ifbody2, elsebody2);
5984 gfc_add_expr_to_block (&block, tmp);
5985 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
5986 tmp = build3_v (COND_EXPR, cond, ifbody,
5987 build_empty_stmt (input_location));
5989 gfc_add_expr_to_block (&block, tmp);
5991 if (maskss)
5993 /* We enclose the above in if (mask) {...}. If the mask is
5994 an optional argument, generate IF (.NOT. PRESENT(MASK)
5995 .OR. MASK(I)).*/
5997 tree ifmask;
5998 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5999 tmp = gfc_finish_block (&block);
6000 tmp = build3_v (COND_EXPR, ifmask, tmp,
6001 build_empty_stmt (input_location));
6003 else
6004 tmp = gfc_finish_block (&block);
6006 gfc_add_expr_to_block (&body, tmp);
6007 gfc_add_modify (&body, second_loop_entry, logical_false_node);
6010 gfc_trans_scalarizing_loops (&loop, &body);
6012 if (lab2)
6013 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
6015 /* For a scalar mask, enclose the loop in an if statement. */
6016 if (maskexpr && maskss == NULL)
6018 tree ifmask;
6020 gfc_init_se (&maskse, NULL);
6021 gfc_conv_expr_val (&maskse, maskexpr);
6022 gfc_add_block_to_block (&se->pre, &maskse.pre);
6023 gfc_init_block (&block);
6024 gfc_add_block_to_block (&block, &loop.pre);
6025 gfc_add_block_to_block (&block, &loop.post);
6026 tmp = gfc_finish_block (&block);
6028 /* For the else part of the scalar mask, just initialize
6029 the pos variable the same way as above. */
6031 gfc_init_block (&elseblock);
6032 for (int i = 0; i < loop.dimen; i++)
6033 gfc_add_modify (&elseblock, pos[i], gfc_index_zero_node);
6034 elsetmp = gfc_finish_block (&elseblock);
6035 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6036 tmp = build3_v (COND_EXPR, ifmask, tmp, elsetmp);
6037 gfc_add_expr_to_block (&block, tmp);
6038 gfc_add_block_to_block (&se->pre, &block);
6040 else
6042 gfc_add_block_to_block (&se->pre, &loop.pre);
6043 gfc_add_block_to_block (&se->pre, &loop.post);
6045 gfc_cleanup_loop (&loop);
6047 if (expr->rank > 0)
6049 for (int i = 0; i < arrayexpr->rank; i++)
6051 tree res_idx = build_int_cst (gfc_array_index_type, i);
6052 tree res_arr_ref = gfc_build_array_ref (result_var, res_idx,
6053 NULL_TREE, true);
6055 tree value = convert (type, pos[i]);
6056 gfc_add_modify (&se->pre, res_arr_ref, value);
6059 se->expr = result_var;
6061 else
6062 se->expr = convert (type, pos[0]);
6065 /* Emit code for findloc. */
6067 static void
6068 gfc_conv_intrinsic_findloc (gfc_se *se, gfc_expr *expr)
6070 gfc_actual_arglist *array_arg, *value_arg, *dim_arg, *mask_arg,
6071 *kind_arg, *back_arg;
6072 gfc_expr *value_expr;
6073 int ikind;
6074 tree resvar;
6075 stmtblock_t block;
6076 stmtblock_t body;
6077 stmtblock_t loopblock;
6078 tree type;
6079 tree tmp;
6080 tree found;
6081 tree forward_branch = NULL_TREE;
6082 tree back_branch;
6083 gfc_loopinfo loop;
6084 gfc_ss *arrayss;
6085 gfc_ss *maskss;
6086 gfc_se arrayse;
6087 gfc_se valuese;
6088 gfc_se maskse;
6089 gfc_se backse;
6090 tree exit_label;
6091 gfc_expr *maskexpr;
6092 tree offset;
6093 int i;
6094 bool optional_mask;
6096 array_arg = expr->value.function.actual;
6097 value_arg = array_arg->next;
6098 dim_arg = value_arg->next;
6099 mask_arg = dim_arg->next;
6100 kind_arg = mask_arg->next;
6101 back_arg = kind_arg->next;
6103 /* Remove kind and set ikind. */
6104 if (kind_arg->expr)
6106 ikind = mpz_get_si (kind_arg->expr->value.integer);
6107 gfc_free_expr (kind_arg->expr);
6108 kind_arg->expr = NULL;
6110 else
6111 ikind = gfc_default_integer_kind;
6113 value_expr = value_arg->expr;
6115 /* Unless it's a string, pass VALUE by value. */
6116 if (value_expr->ts.type != BT_CHARACTER)
6117 value_arg->name = "%VAL";
6119 /* Pass BACK argument by value. */
6120 back_arg->name = "%VAL";
6122 /* Call the library if we have a character function or if
6123 rank > 0. */
6124 if (se->ss || array_arg->expr->ts.type == BT_CHARACTER)
6126 se->ignore_optional = 1;
6127 if (expr->rank == 0)
6129 /* Remove dim argument. */
6130 gfc_free_expr (dim_arg->expr);
6131 dim_arg->expr = NULL;
6133 gfc_conv_intrinsic_funcall (se, expr);
6134 return;
6137 type = gfc_get_int_type (ikind);
6139 /* Initialize the result. */
6140 resvar = gfc_create_var (gfc_array_index_type, "pos");
6141 gfc_add_modify (&se->pre, resvar, build_int_cst (gfc_array_index_type, 0));
6142 offset = gfc_create_var (gfc_array_index_type, "offset");
6144 maskexpr = mask_arg->expr;
6145 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
6146 && maskexpr->symtree->n.sym->attr.dummy
6147 && maskexpr->symtree->n.sym->attr.optional;
6149 /* Generate two loops, one for BACK=.true. and one for BACK=.false. */
6151 for (i = 0 ; i < 2; i++)
6153 /* Walk the arguments. */
6154 arrayss = gfc_walk_expr (array_arg->expr);
6155 gcc_assert (arrayss != gfc_ss_terminator);
6157 if (maskexpr && maskexpr->rank != 0)
6159 maskss = gfc_walk_expr (maskexpr);
6160 gcc_assert (maskss != gfc_ss_terminator);
6162 else
6163 maskss = NULL;
6165 /* Initialize the scalarizer. */
6166 gfc_init_loopinfo (&loop);
6167 exit_label = gfc_build_label_decl (NULL_TREE);
6168 TREE_USED (exit_label) = 1;
6170 /* We add the mask first because the number of iterations is
6171 taken from the last ss, and this breaks if an absent
6172 optional argument is used for mask. */
6174 if (maskss)
6175 gfc_add_ss_to_loop (&loop, maskss);
6176 gfc_add_ss_to_loop (&loop, arrayss);
6178 /* Initialize the loop. */
6179 gfc_conv_ss_startstride (&loop);
6180 gfc_conv_loop_setup (&loop, &expr->where);
6182 /* Calculate the offset. */
6183 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6184 gfc_index_one_node, loop.from[0]);
6185 gfc_add_modify (&loop.pre, offset, tmp);
6187 gfc_mark_ss_chain_used (arrayss, 1);
6188 if (maskss)
6189 gfc_mark_ss_chain_used (maskss, 1);
6191 /* The first loop is for BACK=.true. */
6192 if (i == 0)
6193 loop.reverse[0] = GFC_REVERSE_SET;
6195 /* Generate the loop body. */
6196 gfc_start_scalarized_body (&loop, &body);
6198 /* If we have an array mask, only add the element if it is
6199 set. */
6200 if (maskss)
6202 gfc_init_se (&maskse, NULL);
6203 gfc_copy_loopinfo_to_se (&maskse, &loop);
6204 maskse.ss = maskss;
6205 gfc_conv_expr_val (&maskse, maskexpr);
6206 gfc_add_block_to_block (&body, &maskse.pre);
6209 /* If the condition matches then set the return value. */
6210 gfc_start_block (&block);
6212 /* Add the offset. */
6213 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6214 TREE_TYPE (resvar),
6215 loop.loopvar[0], offset);
6216 gfc_add_modify (&block, resvar, tmp);
6217 /* And break out of the loop. */
6218 tmp = build1_v (GOTO_EXPR, exit_label);
6219 gfc_add_expr_to_block (&block, tmp);
6221 found = gfc_finish_block (&block);
6223 /* Check this element. */
6224 gfc_init_se (&arrayse, NULL);
6225 gfc_copy_loopinfo_to_se (&arrayse, &loop);
6226 arrayse.ss = arrayss;
6227 gfc_conv_expr_val (&arrayse, array_arg->expr);
6228 gfc_add_block_to_block (&body, &arrayse.pre);
6230 gfc_init_se (&valuese, NULL);
6231 gfc_conv_expr_val (&valuese, value_arg->expr);
6232 gfc_add_block_to_block (&body, &valuese.pre);
6234 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6235 arrayse.expr, valuese.expr);
6237 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
6238 if (maskss)
6240 /* We enclose the above in if (mask) {...}. If the mask is
6241 an optional argument, generate IF (.NOT. PRESENT(MASK)
6242 .OR. MASK(I)). */
6244 tree ifmask;
6245 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6246 tmp = build3_v (COND_EXPR, ifmask, tmp,
6247 build_empty_stmt (input_location));
6250 gfc_add_expr_to_block (&body, tmp);
6251 gfc_add_block_to_block (&body, &arrayse.post);
6253 gfc_trans_scalarizing_loops (&loop, &body);
6255 /* Add the exit label. */
6256 tmp = build1_v (LABEL_EXPR, exit_label);
6257 gfc_add_expr_to_block (&loop.pre, tmp);
6258 gfc_start_block (&loopblock);
6259 gfc_add_block_to_block (&loopblock, &loop.pre);
6260 gfc_add_block_to_block (&loopblock, &loop.post);
6261 if (i == 0)
6262 forward_branch = gfc_finish_block (&loopblock);
6263 else
6264 back_branch = gfc_finish_block (&loopblock);
6266 gfc_cleanup_loop (&loop);
6269 /* Enclose the two loops in an IF statement. */
6271 gfc_init_se (&backse, NULL);
6272 gfc_conv_expr_val (&backse, back_arg->expr);
6273 gfc_add_block_to_block (&se->pre, &backse.pre);
6274 tmp = build3_v (COND_EXPR, backse.expr, forward_branch, back_branch);
6276 /* For a scalar mask, enclose the loop in an if statement. */
6277 if (maskexpr && maskss == NULL)
6279 tree ifmask;
6280 tree if_stmt;
6282 gfc_init_se (&maskse, NULL);
6283 gfc_conv_expr_val (&maskse, maskexpr);
6284 gfc_init_block (&block);
6285 gfc_add_expr_to_block (&block, maskse.expr);
6286 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6287 if_stmt = build3_v (COND_EXPR, ifmask, tmp,
6288 build_empty_stmt (input_location));
6289 gfc_add_expr_to_block (&block, if_stmt);
6290 tmp = gfc_finish_block (&block);
6293 gfc_add_expr_to_block (&se->pre, tmp);
6294 se->expr = convert (type, resvar);
6298 /* Emit code for minval or maxval intrinsic. There are many different cases
6299 we need to handle. For performance reasons we sometimes create two
6300 loops instead of one, where the second one is much simpler.
6301 Examples for minval intrinsic:
6302 1) Result is an array, a call is generated
6303 2) Array mask is used and NaNs need to be supported, rank 1:
6304 limit = Infinity;
6305 nonempty = false;
6306 S = from;
6307 while (S <= to) {
6308 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
6309 S++;
6311 limit = nonempty ? NaN : huge (limit);
6312 lab:
6313 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
6314 3) NaNs need to be supported, but it is known at compile time or cheaply
6315 at runtime whether array is nonempty or not, rank 1:
6316 limit = Infinity;
6317 S = from;
6318 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
6319 limit = (from <= to) ? NaN : huge (limit);
6320 lab:
6321 while (S <= to) { limit = min (a[S], limit); S++; }
6322 4) Array mask is used and NaNs need to be supported, rank > 1:
6323 limit = Infinity;
6324 nonempty = false;
6325 fast = false;
6326 S1 = from1;
6327 while (S1 <= to1) {
6328 S2 = from2;
6329 while (S2 <= to2) {
6330 if (mask[S1][S2]) {
6331 if (fast) limit = min (a[S1][S2], limit);
6332 else {
6333 nonempty = true;
6334 if (a[S1][S2] <= limit) {
6335 limit = a[S1][S2];
6336 fast = true;
6340 S2++;
6342 S1++;
6344 if (!fast)
6345 limit = nonempty ? NaN : huge (limit);
6346 5) NaNs need to be supported, but it is known at compile time or cheaply
6347 at runtime whether array is nonempty or not, rank > 1:
6348 limit = Infinity;
6349 fast = false;
6350 S1 = from1;
6351 while (S1 <= to1) {
6352 S2 = from2;
6353 while (S2 <= to2) {
6354 if (fast) limit = min (a[S1][S2], limit);
6355 else {
6356 if (a[S1][S2] <= limit) {
6357 limit = a[S1][S2];
6358 fast = true;
6361 S2++;
6363 S1++;
6365 if (!fast)
6366 limit = (nonempty_array) ? NaN : huge (limit);
6367 6) NaNs aren't supported, but infinities are. Array mask is used:
6368 limit = Infinity;
6369 nonempty = false;
6370 S = from;
6371 while (S <= to) {
6372 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
6373 S++;
6375 limit = nonempty ? limit : huge (limit);
6376 7) Same without array mask:
6377 limit = Infinity;
6378 S = from;
6379 while (S <= to) { limit = min (a[S], limit); S++; }
6380 limit = (from <= to) ? limit : huge (limit);
6381 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
6382 limit = huge (limit);
6383 S = from;
6384 while (S <= to) { limit = min (a[S], limit); S++); }
6386 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
6387 with array mask instead).
6388 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
6389 setting limit = huge (limit); in the else branch. */
6391 static void
6392 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
6394 tree limit;
6395 tree type;
6396 tree tmp;
6397 tree ifbody;
6398 tree nonempty;
6399 tree nonempty_var;
6400 tree lab;
6401 tree fast;
6402 tree huge_cst = NULL, nan_cst = NULL;
6403 stmtblock_t body;
6404 stmtblock_t block, block2;
6405 gfc_loopinfo loop;
6406 gfc_actual_arglist *actual;
6407 gfc_ss *arrayss;
6408 gfc_ss *maskss;
6409 gfc_se arrayse;
6410 gfc_se maskse;
6411 gfc_expr *arrayexpr;
6412 gfc_expr *maskexpr;
6413 int n;
6414 bool optional_mask;
6416 if (se->ss)
6418 gfc_conv_intrinsic_funcall (se, expr);
6419 return;
6422 actual = expr->value.function.actual;
6423 arrayexpr = actual->expr;
6425 if (arrayexpr->ts.type == BT_CHARACTER)
6427 gfc_actual_arglist *dim = actual->next;
6428 if (expr->rank == 0 && dim->expr != 0)
6430 gfc_free_expr (dim->expr);
6431 dim->expr = NULL;
6433 gfc_conv_intrinsic_funcall (se, expr);
6434 return;
6437 type = gfc_typenode_for_spec (&expr->ts);
6438 /* Initialize the result. */
6439 limit = gfc_create_var (type, "limit");
6440 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
6441 switch (expr->ts.type)
6443 case BT_REAL:
6444 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
6445 expr->ts.kind, 0);
6446 if (HONOR_INFINITIES (DECL_MODE (limit)))
6448 REAL_VALUE_TYPE real;
6449 real_inf (&real);
6450 tmp = build_real (type, real);
6452 else
6453 tmp = huge_cst;
6454 if (HONOR_NANS (DECL_MODE (limit)))
6455 nan_cst = gfc_build_nan (type, "");
6456 break;
6458 case BT_INTEGER:
6459 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
6460 break;
6462 case BT_UNSIGNED:
6463 /* For MAXVAL, the minimum is zero, for MINVAL it is HUGE(). */
6464 if (op == GT_EXPR)
6465 tmp = build_int_cst (type, 0);
6466 else
6467 tmp = gfc_conv_mpz_unsigned_to_tree (gfc_unsigned_kinds[n].huge,
6468 expr->ts.kind);
6469 break;
6471 default:
6472 gcc_unreachable ();
6475 /* We start with the most negative possible value for MAXVAL, and the most
6476 positive possible value for MINVAL. The most negative possible value is
6477 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
6478 possible value is HUGE in both cases. BT_UNSIGNED has already been dealt
6479 with above. */
6480 if (op == GT_EXPR && expr->ts.type != BT_UNSIGNED)
6482 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
6483 if (huge_cst)
6484 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
6485 TREE_TYPE (huge_cst), huge_cst);
6488 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
6489 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
6490 tmp, build_int_cst (type, 1));
6492 gfc_add_modify (&se->pre, limit, tmp);
6494 /* Walk the arguments. */
6495 arrayss = gfc_walk_expr (arrayexpr);
6496 gcc_assert (arrayss != gfc_ss_terminator);
6498 actual = actual->next->next;
6499 gcc_assert (actual);
6500 maskexpr = actual->expr;
6501 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
6502 && maskexpr->symtree->n.sym->attr.dummy
6503 && maskexpr->symtree->n.sym->attr.optional;
6504 nonempty = NULL;
6505 if (maskexpr && maskexpr->rank != 0)
6507 maskss = gfc_walk_expr (maskexpr);
6508 gcc_assert (maskss != gfc_ss_terminator);
6510 else
6512 mpz_t asize;
6513 if (gfc_array_size (arrayexpr, &asize))
6515 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
6516 mpz_clear (asize);
6517 nonempty = fold_build2_loc (input_location, GT_EXPR,
6518 logical_type_node, nonempty,
6519 gfc_index_zero_node);
6521 maskss = NULL;
6524 /* Initialize the scalarizer. */
6525 gfc_init_loopinfo (&loop);
6527 /* We add the mask first because the number of iterations is taken
6528 from the last ss, and this breaks if an absent optional argument
6529 is used for mask. */
6531 if (maskss)
6532 gfc_add_ss_to_loop (&loop, maskss);
6533 gfc_add_ss_to_loop (&loop, arrayss);
6535 /* Initialize the loop. */
6536 gfc_conv_ss_startstride (&loop);
6538 /* The code generated can have more than one loop in sequence (see the
6539 comment at the function header). This doesn't work well with the
6540 scalarizer, which changes arrays' offset when the scalarization loops
6541 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
6542 are currently inlined in the scalar case only. As there is no dependency
6543 to care about in that case, there is no temporary, so that we can use the
6544 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
6545 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
6546 gfc_trans_scalarized_loop_boundary even later to restore offset.
6547 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
6548 should eventually go away. We could either create two loops properly,
6549 or find another way to save/restore the array offsets between the two
6550 loops (without conflicting with temporary management), or use a single
6551 loop minmaxval implementation. See PR 31067. */
6552 loop.temp_dim = loop.dimen;
6553 gfc_conv_loop_setup (&loop, &expr->where);
6555 if (nonempty == NULL && maskss == NULL
6556 && loop.dimen == 1 && loop.from[0] && loop.to[0])
6557 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
6558 loop.from[0], loop.to[0]);
6559 nonempty_var = NULL;
6560 if (nonempty == NULL
6561 && (HONOR_INFINITIES (DECL_MODE (limit))
6562 || HONOR_NANS (DECL_MODE (limit))))
6564 nonempty_var = gfc_create_var (logical_type_node, "nonempty");
6565 gfc_add_modify (&se->pre, nonempty_var, logical_false_node);
6566 nonempty = nonempty_var;
6568 lab = NULL;
6569 fast = NULL;
6570 if (HONOR_NANS (DECL_MODE (limit)))
6572 if (loop.dimen == 1)
6574 lab = gfc_build_label_decl (NULL_TREE);
6575 TREE_USED (lab) = 1;
6577 else
6579 fast = gfc_create_var (logical_type_node, "fast");
6580 gfc_add_modify (&se->pre, fast, logical_false_node);
6584 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
6585 if (maskss)
6586 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
6587 /* Generate the loop body. */
6588 gfc_start_scalarized_body (&loop, &body);
6590 /* If we have a mask, only add this element if the mask is set. */
6591 if (maskss)
6593 gfc_init_se (&maskse, NULL);
6594 gfc_copy_loopinfo_to_se (&maskse, &loop);
6595 maskse.ss = maskss;
6596 gfc_conv_expr_val (&maskse, maskexpr);
6597 gfc_add_block_to_block (&body, &maskse.pre);
6599 gfc_start_block (&block);
6601 else
6602 gfc_init_block (&block);
6604 /* Compare with the current limit. */
6605 gfc_init_se (&arrayse, NULL);
6606 gfc_copy_loopinfo_to_se (&arrayse, &loop);
6607 arrayse.ss = arrayss;
6608 gfc_conv_expr_val (&arrayse, arrayexpr);
6609 gfc_add_block_to_block (&block, &arrayse.pre);
6611 gfc_init_block (&block2);
6613 if (nonempty_var)
6614 gfc_add_modify (&block2, nonempty_var, logical_true_node);
6616 if (HONOR_NANS (DECL_MODE (limit)))
6618 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
6619 logical_type_node, arrayse.expr, limit);
6620 if (lab)
6621 ifbody = build1_v (GOTO_EXPR, lab);
6622 else
6624 stmtblock_t ifblock;
6626 gfc_init_block (&ifblock);
6627 gfc_add_modify (&ifblock, limit, arrayse.expr);
6628 gfc_add_modify (&ifblock, fast, logical_true_node);
6629 ifbody = gfc_finish_block (&ifblock);
6631 tmp = build3_v (COND_EXPR, tmp, ifbody,
6632 build_empty_stmt (input_location));
6633 gfc_add_expr_to_block (&block2, tmp);
6635 else
6637 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6638 signed zeros. */
6639 tmp = fold_build2_loc (input_location,
6640 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
6641 type, arrayse.expr, limit);
6642 gfc_add_modify (&block2, limit, tmp);
6645 if (fast)
6647 tree elsebody = gfc_finish_block (&block2);
6649 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6650 signed zeros. */
6651 if (HONOR_NANS (DECL_MODE (limit)))
6653 tmp = fold_build2_loc (input_location, op, logical_type_node,
6654 arrayse.expr, limit);
6655 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
6656 ifbody = build3_v (COND_EXPR, tmp, ifbody,
6657 build_empty_stmt (input_location));
6659 else
6661 tmp = fold_build2_loc (input_location,
6662 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
6663 type, arrayse.expr, limit);
6664 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
6666 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
6667 gfc_add_expr_to_block (&block, tmp);
6669 else
6670 gfc_add_block_to_block (&block, &block2);
6672 gfc_add_block_to_block (&block, &arrayse.post);
6674 tmp = gfc_finish_block (&block);
6675 if (maskss)
6677 /* We enclose the above in if (mask) {...}. If the mask is an
6678 optional argument, generate IF (.NOT. PRESENT(MASK)
6679 .OR. MASK(I)). */
6680 tree ifmask;
6681 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6682 tmp = build3_v (COND_EXPR, ifmask, tmp,
6683 build_empty_stmt (input_location));
6685 gfc_add_expr_to_block (&body, tmp);
6687 if (lab)
6689 gfc_trans_scalarized_loop_boundary (&loop, &body);
6691 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
6692 nan_cst, huge_cst);
6693 gfc_add_modify (&loop.code[0], limit, tmp);
6694 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
6696 /* If we have a mask, only add this element if the mask is set. */
6697 if (maskss)
6699 gfc_init_se (&maskse, NULL);
6700 gfc_copy_loopinfo_to_se (&maskse, &loop);
6701 maskse.ss = maskss;
6702 gfc_conv_expr_val (&maskse, maskexpr);
6703 gfc_add_block_to_block (&body, &maskse.pre);
6705 gfc_start_block (&block);
6707 else
6708 gfc_init_block (&block);
6710 /* Compare with the current limit. */
6711 gfc_init_se (&arrayse, NULL);
6712 gfc_copy_loopinfo_to_se (&arrayse, &loop);
6713 arrayse.ss = arrayss;
6714 gfc_conv_expr_val (&arrayse, arrayexpr);
6715 gfc_add_block_to_block (&block, &arrayse.pre);
6717 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6718 signed zeros. */
6719 if (HONOR_NANS (DECL_MODE (limit)))
6721 tmp = fold_build2_loc (input_location, op, logical_type_node,
6722 arrayse.expr, limit);
6723 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
6724 tmp = build3_v (COND_EXPR, tmp, ifbody,
6725 build_empty_stmt (input_location));
6726 gfc_add_expr_to_block (&block, tmp);
6728 else
6730 tmp = fold_build2_loc (input_location,
6731 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
6732 type, arrayse.expr, limit);
6733 gfc_add_modify (&block, limit, tmp);
6736 gfc_add_block_to_block (&block, &arrayse.post);
6738 tmp = gfc_finish_block (&block);
6739 if (maskss)
6740 /* We enclose the above in if (mask) {...}. */
6742 tree ifmask;
6743 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6744 tmp = build3_v (COND_EXPR, ifmask, tmp,
6745 build_empty_stmt (input_location));
6748 gfc_add_expr_to_block (&body, tmp);
6749 /* Avoid initializing loopvar[0] again, it should be left where
6750 it finished by the first loop. */
6751 loop.from[0] = loop.loopvar[0];
6753 gfc_trans_scalarizing_loops (&loop, &body);
6755 if (fast)
6757 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
6758 nan_cst, huge_cst);
6759 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
6760 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
6761 ifbody);
6762 gfc_add_expr_to_block (&loop.pre, tmp);
6764 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
6766 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
6767 huge_cst);
6768 gfc_add_modify (&loop.pre, limit, tmp);
6771 /* For a scalar mask, enclose the loop in an if statement. */
6772 if (maskexpr && maskss == NULL)
6774 tree else_stmt;
6775 tree ifmask;
6777 gfc_init_se (&maskse, NULL);
6778 gfc_conv_expr_val (&maskse, maskexpr);
6779 gfc_init_block (&block);
6780 gfc_add_block_to_block (&block, &loop.pre);
6781 gfc_add_block_to_block (&block, &loop.post);
6782 tmp = gfc_finish_block (&block);
6784 if (HONOR_INFINITIES (DECL_MODE (limit)))
6785 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
6786 else
6787 else_stmt = build_empty_stmt (input_location);
6789 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6790 tmp = build3_v (COND_EXPR, ifmask, tmp, else_stmt);
6791 gfc_add_expr_to_block (&block, tmp);
6792 gfc_add_block_to_block (&se->pre, &block);
6794 else
6796 gfc_add_block_to_block (&se->pre, &loop.pre);
6797 gfc_add_block_to_block (&se->pre, &loop.post);
6800 gfc_cleanup_loop (&loop);
6802 se->expr = limit;
6805 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
6806 static void
6807 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
6809 tree args[2];
6810 tree type;
6811 tree tmp;
6813 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6814 type = TREE_TYPE (args[0]);
6816 /* Optionally generate code for runtime argument check. */
6817 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6819 tree below = fold_build2_loc (input_location, LT_EXPR,
6820 logical_type_node, args[1],
6821 build_int_cst (TREE_TYPE (args[1]), 0));
6822 tree nbits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6823 tree above = fold_build2_loc (input_location, GE_EXPR,
6824 logical_type_node, args[1], nbits);
6825 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6826 logical_type_node, below, above);
6827 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6828 "POS argument (%ld) out of range 0:%ld "
6829 "in intrinsic BTEST",
6830 fold_convert (long_integer_type_node, args[1]),
6831 fold_convert (long_integer_type_node, nbits));
6834 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
6835 build_int_cst (type, 1), args[1]);
6836 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
6837 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
6838 build_int_cst (type, 0));
6839 type = gfc_typenode_for_spec (&expr->ts);
6840 se->expr = convert (type, tmp);
6844 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
6845 static void
6846 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
6848 tree args[2];
6850 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6852 /* Convert both arguments to the unsigned type of the same size. */
6853 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
6854 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
6856 /* If they have unequal type size, convert to the larger one. */
6857 if (TYPE_PRECISION (TREE_TYPE (args[0]))
6858 > TYPE_PRECISION (TREE_TYPE (args[1])))
6859 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
6860 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
6861 > TYPE_PRECISION (TREE_TYPE (args[0])))
6862 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
6864 /* Now, we compare them. */
6865 se->expr = fold_build2_loc (input_location, op, logical_type_node,
6866 args[0], args[1]);
6870 /* Generate code to perform the specified operation. */
6871 static void
6872 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
6874 tree args[2];
6876 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6877 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
6878 args[0], args[1]);
6881 /* Bitwise not. */
6882 static void
6883 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
6885 tree arg;
6887 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6888 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
6889 TREE_TYPE (arg), arg);
6892 /* Set or clear a single bit. */
6893 static void
6894 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
6896 tree args[2];
6897 tree type;
6898 tree tmp;
6899 enum tree_code op;
6901 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6902 type = TREE_TYPE (args[0]);
6904 /* Optionally generate code for runtime argument check. */
6905 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6907 tree below = fold_build2_loc (input_location, LT_EXPR,
6908 logical_type_node, args[1],
6909 build_int_cst (TREE_TYPE (args[1]), 0));
6910 tree nbits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6911 tree above = fold_build2_loc (input_location, GE_EXPR,
6912 logical_type_node, args[1], nbits);
6913 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6914 logical_type_node, below, above);
6915 size_t len_name = strlen (expr->value.function.isym->name);
6916 char *name = XALLOCAVEC (char, len_name + 1);
6917 for (size_t i = 0; i < len_name; i++)
6918 name[i] = TOUPPER (expr->value.function.isym->name[i]);
6919 name[len_name] = '\0';
6920 tree iname = gfc_build_addr_expr (pchar_type_node,
6921 gfc_build_cstring_const (name));
6922 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6923 "POS argument (%ld) out of range 0:%ld "
6924 "in intrinsic %s",
6925 fold_convert (long_integer_type_node, args[1]),
6926 fold_convert (long_integer_type_node, nbits),
6927 iname);
6930 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
6931 build_int_cst (type, 1), args[1]);
6932 if (set)
6933 op = BIT_IOR_EXPR;
6934 else
6936 op = BIT_AND_EXPR;
6937 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
6939 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
6942 /* Extract a sequence of bits.
6943 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
6944 static void
6945 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
6947 tree args[3];
6948 tree type;
6949 tree tmp;
6950 tree mask;
6951 tree num_bits, cond;
6953 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6954 type = TREE_TYPE (args[0]);
6956 /* Optionally generate code for runtime argument check. */
6957 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6959 tree tmp1 = fold_convert (long_integer_type_node, args[1]);
6960 tree tmp2 = fold_convert (long_integer_type_node, args[2]);
6961 tree nbits = build_int_cst (long_integer_type_node,
6962 TYPE_PRECISION (type));
6963 tree below = fold_build2_loc (input_location, LT_EXPR,
6964 logical_type_node, args[1],
6965 build_int_cst (TREE_TYPE (args[1]), 0));
6966 tree above = fold_build2_loc (input_location, GT_EXPR,
6967 logical_type_node, tmp1, nbits);
6968 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6969 logical_type_node, below, above);
6970 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6971 "POS argument (%ld) out of range 0:%ld "
6972 "in intrinsic IBITS", tmp1, nbits);
6973 below = fold_build2_loc (input_location, LT_EXPR,
6974 logical_type_node, args[2],
6975 build_int_cst (TREE_TYPE (args[2]), 0));
6976 above = fold_build2_loc (input_location, GT_EXPR,
6977 logical_type_node, tmp2, nbits);
6978 scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6979 logical_type_node, below, above);
6980 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6981 "LEN argument (%ld) out of range 0:%ld "
6982 "in intrinsic IBITS", tmp2, nbits);
6983 above = fold_build2_loc (input_location, PLUS_EXPR,
6984 long_integer_type_node, tmp1, tmp2);
6985 scond = fold_build2_loc (input_location, GT_EXPR,
6986 logical_type_node, above, nbits);
6987 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6988 "POS(%ld)+LEN(%ld)>BIT_SIZE(%ld) "
6989 "in intrinsic IBITS", tmp1, tmp2, nbits);
6992 /* The Fortran standard allows (shift width) LEN <= BIT_SIZE(I), whereas
6993 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
6994 special case. See also gfc_conv_intrinsic_ishft (). */
6995 num_bits = build_int_cst (TREE_TYPE (args[2]), TYPE_PRECISION (type));
6997 mask = build_int_cst (type, -1);
6998 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
6999 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[2],
7000 num_bits);
7001 mask = fold_build3_loc (input_location, COND_EXPR, type, cond,
7002 build_int_cst (type, 0), mask);
7003 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
7005 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
7007 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
7010 static void
7011 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
7012 bool arithmetic)
7014 tree args[2], type, num_bits, cond;
7015 tree bigshift;
7016 bool do_convert = false;
7018 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7020 args[0] = gfc_evaluate_now (args[0], &se->pre);
7021 args[1] = gfc_evaluate_now (args[1], &se->pre);
7022 type = TREE_TYPE (args[0]);
7024 if (!arithmetic)
7026 args[0] = fold_convert (unsigned_type_for (type), args[0]);
7027 do_convert = true;
7029 else
7030 gcc_assert (right_shift);
7032 if (flag_unsigned && arithmetic && expr->ts.type == BT_UNSIGNED)
7034 do_convert = true;
7035 args[0] = fold_convert (signed_type_for (type), args[0]);
7038 se->expr = fold_build2_loc (input_location,
7039 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
7040 TREE_TYPE (args[0]), args[0], args[1]);
7042 if (do_convert)
7043 se->expr = fold_convert (type, se->expr);
7045 if (!arithmetic)
7046 bigshift = build_int_cst (type, 0);
7047 else
7049 tree nonneg = fold_build2_loc (input_location, GE_EXPR,
7050 logical_type_node, args[0],
7051 build_int_cst (TREE_TYPE (args[0]), 0));
7052 bigshift = fold_build3_loc (input_location, COND_EXPR, type, nonneg,
7053 build_int_cst (type, 0),
7054 build_int_cst (type, -1));
7057 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
7058 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
7059 special case. */
7060 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
7062 /* Optionally generate code for runtime argument check. */
7063 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
7065 tree below = fold_build2_loc (input_location, LT_EXPR,
7066 logical_type_node, args[1],
7067 build_int_cst (TREE_TYPE (args[1]), 0));
7068 tree above = fold_build2_loc (input_location, GT_EXPR,
7069 logical_type_node, args[1], num_bits);
7070 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
7071 logical_type_node, below, above);
7072 size_t len_name = strlen (expr->value.function.isym->name);
7073 char *name = XALLOCAVEC (char, len_name + 1);
7074 for (size_t i = 0; i < len_name; i++)
7075 name[i] = TOUPPER (expr->value.function.isym->name[i]);
7076 name[len_name] = '\0';
7077 tree iname = gfc_build_addr_expr (pchar_type_node,
7078 gfc_build_cstring_const (name));
7079 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
7080 "SHIFT argument (%ld) out of range 0:%ld "
7081 "in intrinsic %s",
7082 fold_convert (long_integer_type_node, args[1]),
7083 fold_convert (long_integer_type_node, num_bits),
7084 iname);
7087 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
7088 args[1], num_bits);
7090 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
7091 bigshift, se->expr);
7094 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
7096 : ((shift >= 0) ? i << shift : i >> -shift)
7097 where all shifts are logical shifts. */
7098 static void
7099 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
7101 tree args[2];
7102 tree type;
7103 tree utype;
7104 tree tmp;
7105 tree width;
7106 tree num_bits;
7107 tree cond;
7108 tree lshift;
7109 tree rshift;
7111 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7113 args[0] = gfc_evaluate_now (args[0], &se->pre);
7114 args[1] = gfc_evaluate_now (args[1], &se->pre);
7116 type = TREE_TYPE (args[0]);
7117 utype = unsigned_type_for (type);
7119 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
7120 args[1]);
7122 /* Left shift if positive. */
7123 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
7125 /* Right shift if negative.
7126 We convert to an unsigned type because we want a logical shift.
7127 The standard doesn't define the case of shifting negative
7128 numbers, and we try to be compatible with other compilers, most
7129 notably g77, here. */
7130 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
7131 utype, convert (utype, args[0]), width));
7133 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[1],
7134 build_int_cst (TREE_TYPE (args[1]), 0));
7135 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
7137 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
7138 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
7139 special case. */
7140 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
7142 /* Optionally generate code for runtime argument check. */
7143 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
7145 tree outside = fold_build2_loc (input_location, GT_EXPR,
7146 logical_type_node, width, num_bits);
7147 gfc_trans_runtime_check (true, false, outside, &se->pre, &expr->where,
7148 "SHIFT argument (%ld) out of range -%ld:%ld "
7149 "in intrinsic ISHFT",
7150 fold_convert (long_integer_type_node, args[1]),
7151 fold_convert (long_integer_type_node, num_bits),
7152 fold_convert (long_integer_type_node, num_bits));
7155 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, width,
7156 num_bits);
7157 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
7158 build_int_cst (type, 0), tmp);
7162 /* Circular shift. AKA rotate or barrel shift. */
7164 static void
7165 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
7167 tree *args;
7168 tree type;
7169 tree tmp;
7170 tree lrot;
7171 tree rrot;
7172 tree zero;
7173 tree nbits;
7174 unsigned int num_args;
7176 num_args = gfc_intrinsic_argument_list_length (expr);
7177 args = XALLOCAVEC (tree, num_args);
7179 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
7181 type = TREE_TYPE (args[0]);
7182 nbits = build_int_cst (long_integer_type_node, TYPE_PRECISION (type));
7184 if (num_args == 3)
7186 gfc_expr *size = expr->value.function.actual->next->next->expr;
7188 /* Use a library function for the 3 parameter version. */
7189 tree int4type = gfc_get_int_type (4);
7191 /* Treat optional SIZE argument when it is passed as an optional
7192 dummy. If SIZE is absent, the default value is BIT_SIZE(I). */
7193 if (size->expr_type == EXPR_VARIABLE
7194 && size->symtree->n.sym->attr.dummy
7195 && size->symtree->n.sym->attr.optional)
7197 tree type_of_size = TREE_TYPE (args[2]);
7198 args[2] = build3_loc (input_location, COND_EXPR, type_of_size,
7199 gfc_conv_expr_present (size->symtree->n.sym),
7200 args[2], fold_convert (type_of_size, nbits));
7203 /* We convert the first argument to at least 4 bytes, and
7204 convert back afterwards. This removes the need for library
7205 functions for all argument sizes, and function will be
7206 aligned to at least 32 bits, so there's no loss. */
7207 if (expr->ts.kind < 4)
7208 args[0] = convert (int4type, args[0]);
7210 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
7211 need loads of library functions. They cannot have values >
7212 BIT_SIZE (I) so the conversion is safe. */
7213 args[1] = convert (int4type, args[1]);
7214 args[2] = convert (int4type, args[2]);
7216 /* Optionally generate code for runtime argument check. */
7217 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
7219 tree size = fold_convert (long_integer_type_node, args[2]);
7220 tree below = fold_build2_loc (input_location, LE_EXPR,
7221 logical_type_node, size,
7222 build_int_cst (TREE_TYPE (args[1]), 0));
7223 tree above = fold_build2_loc (input_location, GT_EXPR,
7224 logical_type_node, size, nbits);
7225 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
7226 logical_type_node, below, above);
7227 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
7228 "SIZE argument (%ld) out of range 1:%ld "
7229 "in intrinsic ISHFTC", size, nbits);
7230 tree width = fold_convert (long_integer_type_node, args[1]);
7231 width = fold_build1_loc (input_location, ABS_EXPR,
7232 long_integer_type_node, width);
7233 scond = fold_build2_loc (input_location, GT_EXPR,
7234 logical_type_node, width, size);
7235 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
7236 "SHIFT argument (%ld) out of range -%ld:%ld "
7237 "in intrinsic ISHFTC",
7238 fold_convert (long_integer_type_node, args[1]),
7239 size, size);
7242 switch (expr->ts.kind)
7244 case 1:
7245 case 2:
7246 case 4:
7247 tmp = gfor_fndecl_math_ishftc4;
7248 break;
7249 case 8:
7250 tmp = gfor_fndecl_math_ishftc8;
7251 break;
7252 case 16:
7253 tmp = gfor_fndecl_math_ishftc16;
7254 break;
7255 default:
7256 gcc_unreachable ();
7258 se->expr = build_call_expr_loc (input_location,
7259 tmp, 3, args[0], args[1], args[2]);
7260 /* Convert the result back to the original type, if we extended
7261 the first argument's width above. */
7262 if (expr->ts.kind < 4)
7263 se->expr = convert (type, se->expr);
7265 return;
7268 /* Evaluate arguments only once. */
7269 args[0] = gfc_evaluate_now (args[0], &se->pre);
7270 args[1] = gfc_evaluate_now (args[1], &se->pre);
7272 /* Optionally generate code for runtime argument check. */
7273 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
7275 tree width = fold_convert (long_integer_type_node, args[1]);
7276 width = fold_build1_loc (input_location, ABS_EXPR,
7277 long_integer_type_node, width);
7278 tree outside = fold_build2_loc (input_location, GT_EXPR,
7279 logical_type_node, width, nbits);
7280 gfc_trans_runtime_check (true, false, outside, &se->pre, &expr->where,
7281 "SHIFT argument (%ld) out of range -%ld:%ld "
7282 "in intrinsic ISHFTC",
7283 fold_convert (long_integer_type_node, args[1]),
7284 nbits, nbits);
7287 /* Rotate left if positive. */
7288 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
7290 /* Rotate right if negative. */
7291 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
7292 args[1]);
7293 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
7295 zero = build_int_cst (TREE_TYPE (args[1]), 0);
7296 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, args[1],
7297 zero);
7298 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
7300 /* Do nothing if shift == 0. */
7301 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, args[1],
7302 zero);
7303 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
7304 rrot);
7308 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
7309 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
7311 The conditional expression is necessary because the result of LEADZ(0)
7312 is defined, but the result of __builtin_clz(0) is undefined for most
7313 targets.
7315 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
7316 difference in bit size between the argument of LEADZ and the C int. */
7318 static void
7319 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
7321 tree arg;
7322 tree arg_type;
7323 tree cond;
7324 tree result_type;
7325 tree leadz;
7326 tree bit_size;
7327 tree tmp;
7328 tree func;
7329 int s, argsize;
7331 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7332 argsize = TYPE_PRECISION (TREE_TYPE (arg));
7334 /* Which variant of __builtin_clz* should we call? */
7335 if (argsize <= INT_TYPE_SIZE)
7337 arg_type = unsigned_type_node;
7338 func = builtin_decl_explicit (BUILT_IN_CLZ);
7340 else if (argsize <= LONG_TYPE_SIZE)
7342 arg_type = long_unsigned_type_node;
7343 func = builtin_decl_explicit (BUILT_IN_CLZL);
7345 else if (argsize <= LONG_LONG_TYPE_SIZE)
7347 arg_type = long_long_unsigned_type_node;
7348 func = builtin_decl_explicit (BUILT_IN_CLZLL);
7350 else
7352 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
7353 arg_type = gfc_build_uint_type (argsize);
7354 func = NULL_TREE;
7357 /* Convert the actual argument twice: first, to the unsigned type of the
7358 same size; then, to the proper argument type for the built-in
7359 function. But the return type is of the default INTEGER kind. */
7360 arg = fold_convert (gfc_build_uint_type (argsize), arg);
7361 arg = fold_convert (arg_type, arg);
7362 arg = gfc_evaluate_now (arg, &se->pre);
7363 result_type = gfc_get_int_type (gfc_default_integer_kind);
7365 /* Compute LEADZ for the case i .ne. 0. */
7366 if (func)
7368 s = TYPE_PRECISION (arg_type) - argsize;
7369 tmp = fold_convert (result_type,
7370 build_call_expr_loc (input_location, func,
7371 1, arg));
7372 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
7373 tmp, build_int_cst (result_type, s));
7375 else
7377 /* We end up here if the argument type is larger than 'long long'.
7378 We generate this code:
7380 if (x & (ULL_MAX << ULL_SIZE) != 0)
7381 return clzll ((unsigned long long) (x >> ULLSIZE));
7382 else
7383 return ULL_SIZE + clzll ((unsigned long long) x);
7384 where ULL_MAX is the largest value that a ULL_MAX can hold
7385 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
7386 is the bit-size of the long long type (64 in this example). */
7387 tree ullsize, ullmax, tmp1, tmp2, btmp;
7389 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
7390 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
7391 long_long_unsigned_type_node,
7392 build_int_cst (long_long_unsigned_type_node,
7393 0));
7395 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
7396 fold_convert (arg_type, ullmax), ullsize);
7397 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
7398 arg, cond);
7399 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7400 cond, build_int_cst (arg_type, 0));
7402 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
7403 arg, ullsize);
7404 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
7405 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
7406 tmp1 = fold_convert (result_type,
7407 build_call_expr_loc (input_location, btmp, 1, tmp1));
7409 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
7410 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
7411 tmp2 = fold_convert (result_type,
7412 build_call_expr_loc (input_location, btmp, 1, tmp2));
7413 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
7414 tmp2, ullsize);
7416 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
7417 cond, tmp1, tmp2);
7420 /* Build BIT_SIZE. */
7421 bit_size = build_int_cst (result_type, argsize);
7423 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7424 arg, build_int_cst (arg_type, 0));
7425 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
7426 bit_size, leadz);
7430 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
7432 The conditional expression is necessary because the result of TRAILZ(0)
7433 is defined, but the result of __builtin_ctz(0) is undefined for most
7434 targets. */
7436 static void
7437 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
7439 tree arg;
7440 tree arg_type;
7441 tree cond;
7442 tree result_type;
7443 tree trailz;
7444 tree bit_size;
7445 tree func;
7446 int argsize;
7448 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7449 argsize = TYPE_PRECISION (TREE_TYPE (arg));
7451 /* Which variant of __builtin_ctz* should we call? */
7452 if (argsize <= INT_TYPE_SIZE)
7454 arg_type = unsigned_type_node;
7455 func = builtin_decl_explicit (BUILT_IN_CTZ);
7457 else if (argsize <= LONG_TYPE_SIZE)
7459 arg_type = long_unsigned_type_node;
7460 func = builtin_decl_explicit (BUILT_IN_CTZL);
7462 else if (argsize <= LONG_LONG_TYPE_SIZE)
7464 arg_type = long_long_unsigned_type_node;
7465 func = builtin_decl_explicit (BUILT_IN_CTZLL);
7467 else
7469 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
7470 arg_type = gfc_build_uint_type (argsize);
7471 func = NULL_TREE;
7474 /* Convert the actual argument twice: first, to the unsigned type of the
7475 same size; then, to the proper argument type for the built-in
7476 function. But the return type is of the default INTEGER kind. */
7477 arg = fold_convert (gfc_build_uint_type (argsize), arg);
7478 arg = fold_convert (arg_type, arg);
7479 arg = gfc_evaluate_now (arg, &se->pre);
7480 result_type = gfc_get_int_type (gfc_default_integer_kind);
7482 /* Compute TRAILZ for the case i .ne. 0. */
7483 if (func)
7484 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
7485 func, 1, arg));
7486 else
7488 /* We end up here if the argument type is larger than 'long long'.
7489 We generate this code:
7491 if ((x & ULL_MAX) == 0)
7492 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
7493 else
7494 return ctzll ((unsigned long long) x);
7496 where ULL_MAX is the largest value that a ULL_MAX can hold
7497 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
7498 is the bit-size of the long long type (64 in this example). */
7499 tree ullsize, ullmax, tmp1, tmp2, btmp;
7501 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
7502 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
7503 long_long_unsigned_type_node,
7504 build_int_cst (long_long_unsigned_type_node, 0));
7506 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
7507 fold_convert (arg_type, ullmax));
7508 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, cond,
7509 build_int_cst (arg_type, 0));
7511 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
7512 arg, ullsize);
7513 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
7514 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
7515 tmp1 = fold_convert (result_type,
7516 build_call_expr_loc (input_location, btmp, 1, tmp1));
7517 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
7518 tmp1, ullsize);
7520 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
7521 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
7522 tmp2 = fold_convert (result_type,
7523 build_call_expr_loc (input_location, btmp, 1, tmp2));
7525 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
7526 cond, tmp1, tmp2);
7529 /* Build BIT_SIZE. */
7530 bit_size = build_int_cst (result_type, argsize);
7532 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7533 arg, build_int_cst (arg_type, 0));
7534 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
7535 bit_size, trailz);
7538 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
7539 for types larger than "long long", we call the long long built-in for
7540 the lower and higher bits and combine the result. */
7542 static void
7543 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
7545 tree arg;
7546 tree arg_type;
7547 tree result_type;
7548 tree func;
7549 int argsize;
7551 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7552 argsize = TYPE_PRECISION (TREE_TYPE (arg));
7553 result_type = gfc_get_int_type (gfc_default_integer_kind);
7555 /* Which variant of the builtin should we call? */
7556 if (argsize <= INT_TYPE_SIZE)
7558 arg_type = unsigned_type_node;
7559 func = builtin_decl_explicit (parity
7560 ? BUILT_IN_PARITY
7561 : BUILT_IN_POPCOUNT);
7563 else if (argsize <= LONG_TYPE_SIZE)
7565 arg_type = long_unsigned_type_node;
7566 func = builtin_decl_explicit (parity
7567 ? BUILT_IN_PARITYL
7568 : BUILT_IN_POPCOUNTL);
7570 else if (argsize <= LONG_LONG_TYPE_SIZE)
7572 arg_type = long_long_unsigned_type_node;
7573 func = builtin_decl_explicit (parity
7574 ? BUILT_IN_PARITYLL
7575 : BUILT_IN_POPCOUNTLL);
7577 else
7579 /* Our argument type is larger than 'long long', which mean none
7580 of the POPCOUNT builtins covers it. We thus call the 'long long'
7581 variant multiple times, and add the results. */
7582 tree utype, arg2, call1, call2;
7584 /* For now, we only cover the case where argsize is twice as large
7585 as 'long long'. */
7586 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
7588 func = builtin_decl_explicit (parity
7589 ? BUILT_IN_PARITYLL
7590 : BUILT_IN_POPCOUNTLL);
7592 /* Convert it to an integer, and store into a variable. */
7593 utype = gfc_build_uint_type (argsize);
7594 arg = fold_convert (utype, arg);
7595 arg = gfc_evaluate_now (arg, &se->pre);
7597 /* Call the builtin twice. */
7598 call1 = build_call_expr_loc (input_location, func, 1,
7599 fold_convert (long_long_unsigned_type_node,
7600 arg));
7602 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
7603 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
7604 call2 = build_call_expr_loc (input_location, func, 1,
7605 fold_convert (long_long_unsigned_type_node,
7606 arg2));
7608 /* Combine the results. */
7609 if (parity)
7610 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR,
7611 integer_type_node, call1, call2);
7612 else
7613 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
7614 integer_type_node, call1, call2);
7616 se->expr = convert (result_type, se->expr);
7617 return;
7620 /* Convert the actual argument twice: first, to the unsigned type of the
7621 same size; then, to the proper argument type for the built-in
7622 function. */
7623 arg = fold_convert (gfc_build_uint_type (argsize), arg);
7624 arg = fold_convert (arg_type, arg);
7626 se->expr = fold_convert (result_type,
7627 build_call_expr_loc (input_location, func, 1, arg));
7631 /* Process an intrinsic with unspecified argument-types that has an optional
7632 argument (which could be of type character), e.g. EOSHIFT. For those, we
7633 need to append the string length of the optional argument if it is not
7634 present and the type is really character.
7635 primary specifies the position (starting at 1) of the non-optional argument
7636 specifying the type and optional gives the position of the optional
7637 argument in the arglist. */
7639 static void
7640 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
7641 unsigned primary, unsigned optional)
7643 gfc_actual_arglist* prim_arg;
7644 gfc_actual_arglist* opt_arg;
7645 unsigned cur_pos;
7646 gfc_actual_arglist* arg;
7647 gfc_symbol* sym;
7648 vec<tree, va_gc> *append_args;
7650 /* Find the two arguments given as position. */
7651 cur_pos = 0;
7652 prim_arg = NULL;
7653 opt_arg = NULL;
7654 for (arg = expr->value.function.actual; arg; arg = arg->next)
7656 ++cur_pos;
7658 if (cur_pos == primary)
7659 prim_arg = arg;
7660 if (cur_pos == optional)
7661 opt_arg = arg;
7663 if (cur_pos >= primary && cur_pos >= optional)
7664 break;
7666 gcc_assert (prim_arg);
7667 gcc_assert (prim_arg->expr);
7668 gcc_assert (opt_arg);
7670 /* If we do have type CHARACTER and the optional argument is really absent,
7671 append a dummy 0 as string length. */
7672 append_args = NULL;
7673 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
7675 tree dummy;
7677 dummy = build_int_cst (gfc_charlen_type_node, 0);
7678 vec_alloc (append_args, 1);
7679 append_args->quick_push (dummy);
7682 /* Build the call itself. */
7683 gcc_assert (!se->ignore_optional);
7684 sym = gfc_get_symbol_for_expr (expr, false);
7685 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
7686 append_args);
7687 gfc_free_symbol (sym);
7690 /* The length of a character string. */
7691 static void
7692 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
7694 tree len;
7695 tree type;
7696 tree decl;
7697 gfc_symbol *sym;
7698 gfc_se argse;
7699 gfc_expr *arg;
7701 gcc_assert (!se->ss);
7703 arg = expr->value.function.actual->expr;
7705 type = gfc_typenode_for_spec (&expr->ts);
7706 switch (arg->expr_type)
7708 case EXPR_CONSTANT:
7709 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
7710 break;
7712 case EXPR_ARRAY:
7713 /* Obtain the string length from the function used by
7714 trans-array.cc(gfc_trans_array_constructor). */
7715 len = NULL_TREE;
7716 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
7717 break;
7719 case EXPR_VARIABLE:
7720 if (arg->ref == NULL
7721 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
7723 /* This doesn't catch all cases.
7724 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
7725 and the surrounding thread. */
7726 sym = arg->symtree->n.sym;
7727 decl = gfc_get_symbol_decl (sym);
7728 if (decl == current_function_decl && sym->attr.function
7729 && (sym->result == sym))
7730 decl = gfc_get_fake_result_decl (sym, 0);
7732 len = sym->ts.u.cl->backend_decl;
7733 gcc_assert (len);
7734 break;
7737 /* Fall through. */
7739 default:
7740 gfc_init_se (&argse, se);
7741 if (arg->rank == 0)
7742 gfc_conv_expr (&argse, arg);
7743 else
7744 gfc_conv_expr_descriptor (&argse, arg);
7745 gfc_add_block_to_block (&se->pre, &argse.pre);
7746 gfc_add_block_to_block (&se->post, &argse.post);
7747 len = argse.string_length;
7748 break;
7750 se->expr = convert (type, len);
7753 /* The length of a character string not including trailing blanks. */
7754 static void
7755 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
7757 int kind = expr->value.function.actual->expr->ts.kind;
7758 tree args[2], type, fndecl;
7760 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7761 type = gfc_typenode_for_spec (&expr->ts);
7763 if (kind == 1)
7764 fndecl = gfor_fndecl_string_len_trim;
7765 else if (kind == 4)
7766 fndecl = gfor_fndecl_string_len_trim_char4;
7767 else
7768 gcc_unreachable ();
7770 se->expr = build_call_expr_loc (input_location,
7771 fndecl, 2, args[0], args[1]);
7772 se->expr = convert (type, se->expr);
7776 /* Returns the starting position of a substring within a string. */
7778 static void
7779 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
7780 tree function)
7782 tree logical4_type_node = gfc_get_logical_type (4);
7783 tree type;
7784 tree fndecl;
7785 tree *args;
7786 unsigned int num_args;
7788 args = XALLOCAVEC (tree, 5);
7790 /* Get number of arguments; characters count double due to the
7791 string length argument. Kind= is not passed to the library
7792 and thus ignored. */
7793 if (expr->value.function.actual->next->next->expr == NULL)
7794 num_args = 4;
7795 else
7796 num_args = 5;
7798 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
7799 type = gfc_typenode_for_spec (&expr->ts);
7801 if (num_args == 4)
7802 args[4] = build_int_cst (logical4_type_node, 0);
7803 else
7804 args[4] = convert (logical4_type_node, args[4]);
7806 fndecl = build_addr (function);
7807 se->expr = build_call_array_loc (input_location,
7808 TREE_TYPE (TREE_TYPE (function)), fndecl,
7809 5, args);
7810 se->expr = convert (type, se->expr);
7814 /* The ascii value for a single character. */
7815 static void
7816 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
7818 tree args[3], type, pchartype;
7819 int nargs;
7821 nargs = gfc_intrinsic_argument_list_length (expr);
7822 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
7823 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
7824 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
7825 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
7826 type = gfc_typenode_for_spec (&expr->ts);
7828 se->expr = build_fold_indirect_ref_loc (input_location,
7829 args[1]);
7830 se->expr = convert (type, se->expr);
7834 /* Intrinsic ISNAN calls __builtin_isnan. */
7836 static void
7837 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
7839 tree arg;
7841 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7842 se->expr = build_call_expr_loc (input_location,
7843 builtin_decl_explicit (BUILT_IN_ISNAN),
7844 1, arg);
7845 STRIP_TYPE_NOPS (se->expr);
7846 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7850 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
7851 their argument against a constant integer value. */
7853 static void
7854 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
7856 tree arg;
7858 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7859 se->expr = fold_build2_loc (input_location, EQ_EXPR,
7860 gfc_typenode_for_spec (&expr->ts),
7861 arg, build_int_cst (TREE_TYPE (arg), value));
7866 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
7868 static void
7869 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
7871 tree tsource;
7872 tree fsource;
7873 tree mask;
7874 tree type;
7875 tree len, len2;
7876 tree *args;
7877 unsigned int num_args;
7879 num_args = gfc_intrinsic_argument_list_length (expr);
7880 args = XALLOCAVEC (tree, num_args);
7882 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
7883 if (expr->ts.type != BT_CHARACTER)
7885 tsource = args[0];
7886 fsource = args[1];
7887 mask = args[2];
7889 else
7891 /* We do the same as in the non-character case, but the argument
7892 list is different because of the string length arguments. We
7893 also have to set the string length for the result. */
7894 len = args[0];
7895 tsource = args[1];
7896 len2 = args[2];
7897 fsource = args[3];
7898 mask = args[4];
7900 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
7901 &se->pre);
7902 se->string_length = len;
7904 tsource = gfc_evaluate_now (tsource, &se->pre);
7905 fsource = gfc_evaluate_now (fsource, &se->pre);
7906 mask = gfc_evaluate_now (mask, &se->pre);
7907 type = TREE_TYPE (tsource);
7908 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
7909 fold_convert (type, fsource));
7913 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
7915 static void
7916 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
7918 tree args[3], mask, type;
7920 gfc_conv_intrinsic_function_args (se, expr, args, 3);
7921 mask = gfc_evaluate_now (args[2], &se->pre);
7923 type = TREE_TYPE (args[0]);
7924 gcc_assert (TREE_TYPE (args[1]) == type);
7925 gcc_assert (TREE_TYPE (mask) == type);
7927 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
7928 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
7929 fold_build1_loc (input_location, BIT_NOT_EXPR,
7930 type, mask));
7931 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
7932 args[0], args[1]);
7936 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
7937 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
7939 static void
7940 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
7942 tree arg, allones, type, utype, res, cond, bitsize;
7943 int i;
7945 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7946 arg = gfc_evaluate_now (arg, &se->pre);
7948 type = gfc_get_int_type (expr->ts.kind);
7949 utype = unsigned_type_for (type);
7951 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
7952 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
7954 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
7955 build_int_cst (utype, 0));
7957 if (left)
7959 /* Left-justified mask. */
7960 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
7961 bitsize, arg);
7962 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
7963 fold_convert (utype, res));
7965 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
7966 smaller than type width. */
7967 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
7968 build_int_cst (TREE_TYPE (arg), 0));
7969 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
7970 build_int_cst (utype, 0), res);
7972 else
7974 /* Right-justified mask. */
7975 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
7976 fold_convert (utype, arg));
7977 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
7979 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
7980 strictly smaller than type width. */
7981 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7982 arg, bitsize);
7983 res = fold_build3_loc (input_location, COND_EXPR, utype,
7984 cond, allones, res);
7987 se->expr = fold_convert (type, res);
7991 /* FRACTION (s) is translated into:
7992 isfinite (s) ? frexp (s, &dummy_int) : NaN */
7993 static void
7994 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
7996 tree arg, type, tmp, res, frexp, cond;
7998 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
8000 type = gfc_typenode_for_spec (&expr->ts);
8001 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8002 arg = gfc_evaluate_now (arg, &se->pre);
8004 cond = build_call_expr_loc (input_location,
8005 builtin_decl_explicit (BUILT_IN_ISFINITE),
8006 1, arg);
8008 tmp = gfc_create_var (integer_type_node, NULL);
8009 res = build_call_expr_loc (input_location, frexp, 2,
8010 fold_convert (type, arg),
8011 gfc_build_addr_expr (NULL_TREE, tmp));
8012 res = fold_convert (type, res);
8014 se->expr = fold_build3_loc (input_location, COND_EXPR, type,
8015 cond, res, gfc_build_nan (type, ""));
8019 /* NEAREST (s, dir) is translated into
8020 tmp = copysign (HUGE_VAL, dir);
8021 return nextafter (s, tmp);
8023 static void
8024 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
8026 tree args[2], type, tmp, nextafter, copysign, huge_val;
8028 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
8029 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
8031 type = gfc_typenode_for_spec (&expr->ts);
8032 gfc_conv_intrinsic_function_args (se, expr, args, 2);
8034 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
8035 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
8036 fold_convert (type, args[1]));
8037 se->expr = build_call_expr_loc (input_location, nextafter, 2,
8038 fold_convert (type, args[0]), tmp);
8039 se->expr = fold_convert (type, se->expr);
8043 /* SPACING (s) is translated into
8044 int e;
8045 if (!isfinite (s))
8046 res = NaN;
8047 else if (s == 0)
8048 res = tiny;
8049 else
8051 frexp (s, &e);
8052 e = e - prec;
8053 e = MAX_EXPR (e, emin);
8054 res = scalbn (1., e);
8056 return res;
8058 where prec is the precision of s, gfc_real_kinds[k].digits,
8059 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
8060 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
8062 static void
8063 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
8065 tree arg, type, prec, emin, tiny, res, e;
8066 tree cond, nan, tmp, frexp, scalbn;
8067 int k;
8068 stmtblock_t block;
8070 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
8071 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
8072 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
8073 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
8075 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
8076 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
8078 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8079 arg = gfc_evaluate_now (arg, &se->pre);
8081 type = gfc_typenode_for_spec (&expr->ts);
8082 e = gfc_create_var (integer_type_node, NULL);
8083 res = gfc_create_var (type, NULL);
8086 /* Build the block for s /= 0. */
8087 gfc_start_block (&block);
8088 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
8089 gfc_build_addr_expr (NULL_TREE, e));
8090 gfc_add_expr_to_block (&block, tmp);
8092 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
8093 prec);
8094 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
8095 integer_type_node, tmp, emin));
8097 tmp = build_call_expr_loc (input_location, scalbn, 2,
8098 build_real_from_int_cst (type, integer_one_node), e);
8099 gfc_add_modify (&block, res, tmp);
8101 /* Finish by building the IF statement for value zero. */
8102 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
8103 build_real_from_int_cst (type, integer_zero_node));
8104 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
8105 gfc_finish_block (&block));
8107 /* And deal with infinities and NaNs. */
8108 cond = build_call_expr_loc (input_location,
8109 builtin_decl_explicit (BUILT_IN_ISFINITE),
8110 1, arg);
8111 nan = gfc_build_nan (type, "");
8112 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
8114 gfc_add_expr_to_block (&se->pre, tmp);
8115 se->expr = res;
8119 /* RRSPACING (s) is translated into
8120 int e;
8121 real x;
8122 x = fabs (s);
8123 if (isfinite (x))
8125 if (x != 0)
8127 frexp (s, &e);
8128 x = scalbn (x, precision - e);
8131 else
8132 x = NaN;
8133 return x;
8135 where precision is gfc_real_kinds[k].digits. */
8137 static void
8138 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
8140 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
8141 int prec, k;
8142 stmtblock_t block;
8144 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
8145 prec = gfc_real_kinds[k].digits;
8147 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
8148 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
8149 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
8151 type = gfc_typenode_for_spec (&expr->ts);
8152 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8153 arg = gfc_evaluate_now (arg, &se->pre);
8155 e = gfc_create_var (integer_type_node, NULL);
8156 x = gfc_create_var (type, NULL);
8157 gfc_add_modify (&se->pre, x,
8158 build_call_expr_loc (input_location, fabs, 1, arg));
8161 gfc_start_block (&block);
8162 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
8163 gfc_build_addr_expr (NULL_TREE, e));
8164 gfc_add_expr_to_block (&block, tmp);
8166 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
8167 build_int_cst (integer_type_node, prec), e);
8168 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
8169 gfc_add_modify (&block, x, tmp);
8170 stmt = gfc_finish_block (&block);
8172 /* if (x != 0) */
8173 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, x,
8174 build_real_from_int_cst (type, integer_zero_node));
8175 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
8177 /* And deal with infinities and NaNs. */
8178 cond = build_call_expr_loc (input_location,
8179 builtin_decl_explicit (BUILT_IN_ISFINITE),
8180 1, x);
8181 nan = gfc_build_nan (type, "");
8182 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
8184 gfc_add_expr_to_block (&se->pre, tmp);
8185 se->expr = fold_convert (type, x);
8189 /* SCALE (s, i) is translated into scalbn (s, i). */
8190 static void
8191 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
8193 tree args[2], type, scalbn;
8195 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
8197 type = gfc_typenode_for_spec (&expr->ts);
8198 gfc_conv_intrinsic_function_args (se, expr, args, 2);
8199 se->expr = build_call_expr_loc (input_location, scalbn, 2,
8200 fold_convert (type, args[0]),
8201 fold_convert (integer_type_node, args[1]));
8202 se->expr = fold_convert (type, se->expr);
8206 /* SET_EXPONENT (s, i) is translated into
8207 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
8208 static void
8209 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
8211 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
8213 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
8214 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
8216 type = gfc_typenode_for_spec (&expr->ts);
8217 gfc_conv_intrinsic_function_args (se, expr, args, 2);
8218 args[0] = gfc_evaluate_now (args[0], &se->pre);
8220 tmp = gfc_create_var (integer_type_node, NULL);
8221 tmp = build_call_expr_loc (input_location, frexp, 2,
8222 fold_convert (type, args[0]),
8223 gfc_build_addr_expr (NULL_TREE, tmp));
8224 res = build_call_expr_loc (input_location, scalbn, 2, tmp,
8225 fold_convert (integer_type_node, args[1]));
8226 res = fold_convert (type, res);
8228 /* Call to isfinite */
8229 cond = build_call_expr_loc (input_location,
8230 builtin_decl_explicit (BUILT_IN_ISFINITE),
8231 1, args[0]);
8232 nan = gfc_build_nan (type, "");
8234 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
8235 res, nan);
8239 static void
8240 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
8242 gfc_actual_arglist *actual;
8243 tree arg1;
8244 tree type;
8245 tree size;
8246 gfc_se argse;
8247 gfc_expr *e;
8248 gfc_symbol *sym = NULL;
8250 gfc_init_se (&argse, NULL);
8251 actual = expr->value.function.actual;
8253 if (actual->expr->ts.type == BT_CLASS)
8254 gfc_add_class_array_ref (actual->expr);
8256 e = actual->expr;
8258 /* These are emerging from the interface mapping, when a class valued
8259 function appears as the rhs in a realloc on assign statement, where
8260 the size of the result is that of one of the actual arguments. */
8261 if (e->expr_type == EXPR_VARIABLE
8262 && e->symtree->n.sym->ns == NULL /* This is distinctive! */
8263 && e->symtree->n.sym->ts.type == BT_CLASS
8264 && e->ref && e->ref->type == REF_COMPONENT
8265 && strcmp (e->ref->u.c.component->name, "_data") == 0)
8266 sym = e->symtree->n.sym;
8268 if ((gfc_option.rtcheck & GFC_RTCHECK_POINTER)
8269 && e
8270 && (e->expr_type == EXPR_VARIABLE || e->expr_type == EXPR_FUNCTION))
8272 symbol_attribute attr;
8273 char *msg;
8274 tree temp;
8275 tree cond;
8277 if (e->symtree->n.sym && IS_CLASS_ARRAY (e->symtree->n.sym))
8279 attr = CLASS_DATA (e->symtree->n.sym)->attr;
8280 attr.pointer = attr.class_pointer;
8282 else
8283 attr = gfc_expr_attr (e);
8285 if (attr.allocatable)
8286 msg = xasprintf ("Allocatable argument '%s' is not allocated",
8287 e->symtree->n.sym->name);
8288 else if (attr.pointer)
8289 msg = xasprintf ("Pointer argument '%s' is not associated",
8290 e->symtree->n.sym->name);
8291 else
8292 goto end_arg_check;
8294 if (sym)
8296 temp = gfc_class_data_get (sym->backend_decl);
8297 temp = gfc_conv_descriptor_data_get (temp);
8299 else
8301 argse.descriptor_only = 1;
8302 gfc_conv_expr_descriptor (&argse, actual->expr);
8303 temp = gfc_conv_descriptor_data_get (argse.expr);
8306 cond = fold_build2_loc (input_location, EQ_EXPR,
8307 logical_type_node, temp,
8308 fold_convert (TREE_TYPE (temp),
8309 null_pointer_node));
8310 gfc_trans_runtime_check (true, false, cond, &argse.pre, &e->where, msg);
8312 free (msg);
8314 end_arg_check:
8316 argse.data_not_needed = 1;
8317 if (gfc_is_class_array_function (e))
8319 /* For functions that return a class array conv_expr_descriptor is not
8320 able to get the descriptor right. Therefore this special case. */
8321 gfc_conv_expr_reference (&argse, e);
8322 argse.expr = gfc_class_data_get (argse.expr);
8324 else if (sym && sym->backend_decl)
8326 gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (sym->backend_decl)));
8327 argse.expr = gfc_class_data_get (sym->backend_decl);
8329 else
8330 gfc_conv_expr_descriptor (&argse, actual->expr);
8331 gfc_add_block_to_block (&se->pre, &argse.pre);
8332 gfc_add_block_to_block (&se->post, &argse.post);
8333 arg1 = argse.expr;
8335 actual = actual->next;
8336 if (actual->expr)
8338 stmtblock_t block;
8339 gfc_init_block (&block);
8340 gfc_init_se (&argse, NULL);
8341 gfc_conv_expr_type (&argse, actual->expr,
8342 gfc_array_index_type);
8343 gfc_add_block_to_block (&block, &argse.pre);
8344 tree tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8345 argse.expr, gfc_index_one_node);
8346 size = gfc_tree_array_size (&block, arg1, e, tmp);
8348 /* Unusually, for an intrinsic, size does not exclude
8349 an optional arg2, so we must test for it. */
8350 if (actual->expr->expr_type == EXPR_VARIABLE
8351 && actual->expr->symtree->n.sym->attr.dummy
8352 && actual->expr->symtree->n.sym->attr.optional)
8354 tree cond;
8355 stmtblock_t block2;
8356 gfc_init_block (&block2);
8357 gfc_init_se (&argse, NULL);
8358 argse.want_pointer = 1;
8359 argse.data_not_needed = 1;
8360 gfc_conv_expr (&argse, actual->expr);
8361 gfc_add_block_to_block (&se->pre, &argse.pre);
8362 /* 'block2' contains the arg2 absent case, 'block' the arg2 present
8363 case; size_var can be used in both blocks. */
8364 tree size_var = gfc_create_var (TREE_TYPE (size), "size");
8365 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8366 TREE_TYPE (size_var), size_var, size);
8367 gfc_add_expr_to_block (&block, tmp);
8368 size = gfc_tree_array_size (&block2, arg1, e, NULL_TREE);
8369 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8370 TREE_TYPE (size_var), size_var, size);
8371 gfc_add_expr_to_block (&block2, tmp);
8372 cond = gfc_conv_expr_present (actual->expr->symtree->n.sym);
8373 tmp = build3_v (COND_EXPR, cond, gfc_finish_block (&block),
8374 gfc_finish_block (&block2));
8375 gfc_add_expr_to_block (&se->pre, tmp);
8376 size = size_var;
8378 else
8379 gfc_add_block_to_block (&se->pre, &block);
8381 else
8382 size = gfc_tree_array_size (&se->pre, arg1, e, NULL_TREE);
8383 type = gfc_typenode_for_spec (&expr->ts);
8384 se->expr = convert (type, size);
8388 /* Helper function to compute the size of a character variable,
8389 excluding the terminating null characters. The result has
8390 gfc_array_index_type type. */
8392 tree
8393 size_of_string_in_bytes (int kind, tree string_length)
8395 tree bytesize;
8396 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
8398 bytesize = build_int_cst (gfc_array_index_type,
8399 gfc_character_kinds[i].bit_size / 8);
8401 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8402 bytesize,
8403 fold_convert (gfc_array_index_type, string_length));
8407 static void
8408 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
8410 gfc_expr *arg;
8411 gfc_se argse;
8412 tree source_bytes;
8413 tree tmp;
8414 tree lower;
8415 tree upper;
8416 tree byte_size;
8417 tree field;
8418 int n;
8420 gfc_init_se (&argse, NULL);
8421 arg = expr->value.function.actual->expr;
8423 if (arg->rank || arg->ts.type == BT_ASSUMED)
8424 gfc_conv_expr_descriptor (&argse, arg);
8425 else
8426 gfc_conv_expr_reference (&argse, arg);
8428 if (arg->ts.type == BT_ASSUMED)
8430 /* This only works if an array descriptor has been passed; thus, extract
8431 the size from the descriptor. */
8432 gcc_assert (TYPE_PRECISION (gfc_array_index_type)
8433 == TYPE_PRECISION (size_type_node));
8434 tmp = arg->symtree->n.sym->backend_decl;
8435 tmp = DECL_LANG_SPECIFIC (tmp)
8436 && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
8437 ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
8438 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
8439 tmp = build_fold_indirect_ref_loc (input_location, tmp);
8441 tmp = gfc_conv_descriptor_dtype (tmp);
8442 field = gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
8443 GFC_DTYPE_ELEM_LEN);
8444 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
8445 tmp, field, NULL_TREE);
8447 byte_size = fold_convert (gfc_array_index_type, tmp);
8449 else if (arg->ts.type == BT_CLASS)
8451 /* Conv_expr_descriptor returns a component_ref to _data component of the
8452 class object. The class object may be a non-pointer object, e.g.
8453 located on the stack, or a memory location pointed to, e.g. a
8454 parameter, i.e., an indirect_ref. */
8455 if (POINTER_TYPE_P (TREE_TYPE (argse.expr))
8456 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (argse.expr))))
8457 byte_size
8458 = gfc_class_vtab_size_get (build_fold_indirect_ref (argse.expr));
8459 else if (GFC_CLASS_TYPE_P (TREE_TYPE (argse.expr)))
8460 byte_size = gfc_class_vtab_size_get (argse.expr);
8461 else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (argse.expr))
8462 && TREE_CODE (argse.expr) == COMPONENT_REF)
8463 byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
8464 else if (arg->rank > 0
8465 || (arg->rank == 0
8466 && arg->ref && arg->ref->type == REF_COMPONENT))
8468 /* The scalarizer added an additional temp. To get the class' vptr
8469 one has to look at the original backend_decl. */
8470 if (argse.class_container)
8471 byte_size = gfc_class_vtab_size_get (argse.class_container);
8472 else if (DECL_LANG_SPECIFIC (arg->symtree->n.sym->backend_decl))
8473 byte_size = gfc_class_vtab_size_get (
8474 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
8475 else
8476 gcc_unreachable ();
8478 else
8479 gcc_unreachable ();
8481 else
8483 if (arg->ts.type == BT_CHARACTER)
8484 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
8485 else
8487 if (arg->rank == 0)
8488 byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
8489 argse.expr));
8490 else
8491 byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
8492 byte_size = fold_convert (gfc_array_index_type,
8493 size_in_bytes (byte_size));
8497 if (arg->rank == 0)
8498 se->expr = byte_size;
8499 else
8501 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
8502 gfc_add_modify (&argse.pre, source_bytes, byte_size);
8504 if (arg->rank == -1)
8506 tree cond, loop_var, exit_label;
8507 stmtblock_t body;
8509 tmp = fold_convert (gfc_array_index_type,
8510 gfc_conv_descriptor_rank (argse.expr));
8511 loop_var = gfc_create_var (gfc_array_index_type, "i");
8512 gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
8513 exit_label = gfc_build_label_decl (NULL_TREE);
8515 /* Create loop:
8516 for (;;)
8518 if (i >= rank)
8519 goto exit;
8520 source_bytes = source_bytes * array.dim[i].extent;
8521 i = i + 1;
8523 exit: */
8524 gfc_start_block (&body);
8525 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
8526 loop_var, tmp);
8527 tmp = build1_v (GOTO_EXPR, exit_label);
8528 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
8529 cond, tmp, build_empty_stmt (input_location));
8530 gfc_add_expr_to_block (&body, tmp);
8532 lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
8533 upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
8534 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
8535 tmp = fold_build2_loc (input_location, MULT_EXPR,
8536 gfc_array_index_type, tmp, source_bytes);
8537 gfc_add_modify (&body, source_bytes, tmp);
8539 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8540 gfc_array_index_type, loop_var,
8541 gfc_index_one_node);
8542 gfc_add_modify_loc (input_location, &body, loop_var, tmp);
8544 tmp = gfc_finish_block (&body);
8546 tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
8547 tmp);
8548 gfc_add_expr_to_block (&argse.pre, tmp);
8550 tmp = build1_v (LABEL_EXPR, exit_label);
8551 gfc_add_expr_to_block (&argse.pre, tmp);
8553 else
8555 /* Obtain the size of the array in bytes. */
8556 for (n = 0; n < arg->rank; n++)
8558 tree idx;
8559 idx = gfc_rank_cst[n];
8560 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
8561 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
8562 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
8563 tmp = fold_build2_loc (input_location, MULT_EXPR,
8564 gfc_array_index_type, tmp, source_bytes);
8565 gfc_add_modify (&argse.pre, source_bytes, tmp);
8568 se->expr = source_bytes;
8571 gfc_add_block_to_block (&se->pre, &argse.pre);
8575 static void
8576 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
8578 gfc_expr *arg;
8579 gfc_se argse;
8580 tree type, result_type, tmp, class_decl = NULL;
8581 gfc_symbol *sym;
8582 bool unlimited = false;
8584 arg = expr->value.function.actual->expr;
8586 gfc_init_se (&argse, NULL);
8587 result_type = gfc_get_int_type (expr->ts.kind);
8589 if (arg->rank == 0)
8591 if (arg->ts.type == BT_CLASS)
8593 unlimited = UNLIMITED_POLY (arg);
8594 gfc_add_vptr_component (arg);
8595 gfc_add_size_component (arg);
8596 gfc_conv_expr (&argse, arg);
8597 tmp = fold_convert (result_type, argse.expr);
8598 class_decl = gfc_get_class_from_expr (argse.expr);
8599 goto done;
8602 gfc_conv_expr_reference (&argse, arg);
8603 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
8604 argse.expr));
8606 else
8608 argse.want_pointer = 0;
8609 gfc_conv_expr_descriptor (&argse, arg);
8610 sym = arg->expr_type == EXPR_VARIABLE ? arg->symtree->n.sym : NULL;
8611 if (arg->ts.type == BT_CLASS)
8613 unlimited = UNLIMITED_POLY (arg);
8614 if (TREE_CODE (argse.expr) == COMPONENT_REF)
8615 tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
8616 else if (arg->rank > 0 && sym
8617 && DECL_LANG_SPECIFIC (sym->backend_decl))
8618 tmp = gfc_class_vtab_size_get (
8619 GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl));
8620 else
8621 gcc_unreachable ();
8622 tmp = fold_convert (result_type, tmp);
8623 class_decl = gfc_get_class_from_expr (argse.expr);
8624 goto done;
8626 type = gfc_get_element_type (TREE_TYPE (argse.expr));
8629 /* Obtain the argument's word length. */
8630 if (arg->ts.type == BT_CHARACTER)
8631 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
8632 else
8633 tmp = size_in_bytes (type);
8634 tmp = fold_convert (result_type, tmp);
8636 done:
8637 if (unlimited && class_decl)
8638 tmp = gfc_resize_class_size_with_len (NULL, class_decl, tmp);
8640 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
8641 build_int_cst (result_type, BITS_PER_UNIT));
8642 gfc_add_block_to_block (&se->pre, &argse.pre);
8646 /* Intrinsic string comparison functions. */
8648 static void
8649 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
8651 tree args[4];
8653 gfc_conv_intrinsic_function_args (se, expr, args, 4);
8655 se->expr
8656 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
8657 expr->value.function.actual->expr->ts.kind,
8658 op);
8659 se->expr = fold_build2_loc (input_location, op,
8660 gfc_typenode_for_spec (&expr->ts), se->expr,
8661 build_int_cst (TREE_TYPE (se->expr), 0));
8664 /* Generate a call to the adjustl/adjustr library function. */
8665 static void
8666 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
8668 tree args[3];
8669 tree len;
8670 tree type;
8671 tree var;
8672 tree tmp;
8674 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
8675 len = args[1];
8677 type = TREE_TYPE (args[2]);
8678 var = gfc_conv_string_tmp (se, type, len);
8679 args[0] = var;
8681 tmp = build_call_expr_loc (input_location,
8682 fndecl, 3, args[0], args[1], args[2]);
8683 gfc_add_expr_to_block (&se->pre, tmp);
8684 se->expr = var;
8685 se->string_length = len;
8689 /* Generate code for the TRANSFER intrinsic:
8690 For scalar results:
8691 DEST = TRANSFER (SOURCE, MOLD)
8692 where:
8693 typeof<DEST> = typeof<MOLD>
8694 and:
8695 MOLD is scalar.
8697 For array results:
8698 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
8699 where:
8700 typeof<DEST> = typeof<MOLD>
8701 and:
8702 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
8703 sizeof (DEST(0) * SIZE). */
8704 static void
8705 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
8707 tree tmp;
8708 tree tmpdecl;
8709 tree ptr;
8710 tree extent;
8711 tree source;
8712 tree source_type;
8713 tree source_bytes;
8714 tree mold_type;
8715 tree dest_word_len;
8716 tree size_words;
8717 tree size_bytes;
8718 tree upper;
8719 tree lower;
8720 tree stmt;
8721 tree class_ref = NULL_TREE;
8722 gfc_actual_arglist *arg;
8723 gfc_se argse;
8724 gfc_array_info *info;
8725 stmtblock_t block;
8726 int n;
8727 bool scalar_mold;
8728 gfc_expr *source_expr, *mold_expr, *class_expr;
8730 info = NULL;
8731 if (se->loop)
8732 info = &se->ss->info->data.array;
8734 /* Convert SOURCE. The output from this stage is:-
8735 source_bytes = length of the source in bytes
8736 source = pointer to the source data. */
8737 arg = expr->value.function.actual;
8738 source_expr = arg->expr;
8740 /* Ensure double transfer through LOGICAL preserves all
8741 the needed bits. */
8742 if (arg->expr->expr_type == EXPR_FUNCTION
8743 && arg->expr->value.function.esym == NULL
8744 && arg->expr->value.function.isym != NULL
8745 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
8746 && arg->expr->ts.type == BT_LOGICAL
8747 && expr->ts.type != arg->expr->ts.type)
8748 arg->expr->value.function.name = "__transfer_in_transfer";
8750 gfc_init_se (&argse, NULL);
8752 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
8754 /* Obtain the pointer to source and the length of source in bytes. */
8755 if (arg->expr->rank == 0)
8757 gfc_conv_expr_reference (&argse, arg->expr);
8758 if (arg->expr->ts.type == BT_CLASS)
8760 tmp = build_fold_indirect_ref_loc (input_location, argse.expr);
8761 if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
8763 source = gfc_class_data_get (tmp);
8764 class_ref = tmp;
8766 else
8768 /* Array elements are evaluated as a reference to the data.
8769 To obtain the vptr for the element size, the argument
8770 expression must be stripped to the class reference and
8771 re-evaluated. The pre and post blocks are not needed. */
8772 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
8773 source = argse.expr;
8774 class_expr = gfc_find_and_cut_at_last_class_ref (arg->expr);
8775 gfc_init_se (&argse, NULL);
8776 gfc_conv_expr (&argse, class_expr);
8777 class_ref = argse.expr;
8780 else
8781 source = argse.expr;
8783 /* Obtain the source word length. */
8784 switch (arg->expr->ts.type)
8786 case BT_CHARACTER:
8787 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
8788 argse.string_length);
8789 break;
8790 case BT_CLASS:
8791 if (class_ref != NULL_TREE)
8793 tmp = gfc_class_vtab_size_get (class_ref);
8794 if (UNLIMITED_POLY (source_expr))
8795 tmp = gfc_resize_class_size_with_len (NULL, class_ref, tmp);
8797 else
8799 tmp = gfc_class_vtab_size_get (argse.expr);
8800 if (UNLIMITED_POLY (source_expr))
8801 tmp = gfc_resize_class_size_with_len (NULL, argse.expr, tmp);
8803 break;
8804 default:
8805 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
8806 source));
8807 tmp = fold_convert (gfc_array_index_type,
8808 size_in_bytes (source_type));
8809 break;
8812 else
8814 argse.want_pointer = 0;
8815 gfc_conv_expr_descriptor (&argse, arg->expr);
8816 source = gfc_conv_descriptor_data_get (argse.expr);
8817 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
8819 /* Repack the source if not simply contiguous. */
8820 if (!gfc_is_simply_contiguous (arg->expr, false, true))
8822 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
8824 if (warn_array_temporaries)
8825 gfc_warning (OPT_Warray_temporaries,
8826 "Creating array temporary at %L", &expr->where);
8828 source = build_call_expr_loc (input_location,
8829 gfor_fndecl_in_pack, 1, tmp);
8830 source = gfc_evaluate_now (source, &argse.pre);
8832 /* Free the temporary. */
8833 gfc_start_block (&block);
8834 tmp = gfc_call_free (source);
8835 gfc_add_expr_to_block (&block, tmp);
8836 stmt = gfc_finish_block (&block);
8838 /* Clean up if it was repacked. */
8839 gfc_init_block (&block);
8840 tmp = gfc_conv_array_data (argse.expr);
8841 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8842 source, tmp);
8843 tmp = build3_v (COND_EXPR, tmp, stmt,
8844 build_empty_stmt (input_location));
8845 gfc_add_expr_to_block (&block, tmp);
8846 gfc_add_block_to_block (&block, &se->post);
8847 gfc_init_block (&se->post);
8848 gfc_add_block_to_block (&se->post, &block);
8851 /* Obtain the source word length. */
8852 if (arg->expr->ts.type == BT_CHARACTER)
8853 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
8854 argse.string_length);
8855 else if (arg->expr->ts.type == BT_CLASS)
8857 class_ref = TREE_OPERAND (argse.expr, 0);
8858 tmp = gfc_class_vtab_size_get (class_ref);
8859 if (UNLIMITED_POLY (arg->expr))
8860 tmp = gfc_resize_class_size_with_len (&argse.pre, class_ref, tmp);
8862 else
8863 tmp = fold_convert (gfc_array_index_type,
8864 size_in_bytes (source_type));
8866 /* Obtain the size of the array in bytes. */
8867 extent = gfc_create_var (gfc_array_index_type, NULL);
8868 for (n = 0; n < arg->expr->rank; n++)
8870 tree idx;
8871 idx = gfc_rank_cst[n];
8872 gfc_add_modify (&argse.pre, source_bytes, tmp);
8873 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
8874 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
8875 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8876 gfc_array_index_type, upper, lower);
8877 gfc_add_modify (&argse.pre, extent, tmp);
8878 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8879 gfc_array_index_type, extent,
8880 gfc_index_one_node);
8881 tmp = fold_build2_loc (input_location, MULT_EXPR,
8882 gfc_array_index_type, tmp, source_bytes);
8886 gfc_add_modify (&argse.pre, source_bytes, tmp);
8887 gfc_add_block_to_block (&se->pre, &argse.pre);
8888 gfc_add_block_to_block (&se->post, &argse.post);
8890 /* Now convert MOLD. The outputs are:
8891 mold_type = the TREE type of MOLD
8892 dest_word_len = destination word length in bytes. */
8893 arg = arg->next;
8894 mold_expr = arg->expr;
8896 gfc_init_se (&argse, NULL);
8898 scalar_mold = arg->expr->rank == 0;
8900 if (arg->expr->rank == 0)
8902 gfc_conv_expr_reference (&argse, mold_expr);
8903 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
8904 argse.expr));
8906 else
8908 argse.want_pointer = 0;
8909 gfc_conv_expr_descriptor (&argse, mold_expr);
8910 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
8913 gfc_add_block_to_block (&se->pre, &argse.pre);
8914 gfc_add_block_to_block (&se->post, &argse.post);
8916 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
8918 /* If this TRANSFER is nested in another TRANSFER, use a type
8919 that preserves all bits. */
8920 if (mold_expr->ts.type == BT_LOGICAL)
8921 mold_type = gfc_get_int_type (mold_expr->ts.kind);
8924 /* Obtain the destination word length. */
8925 switch (mold_expr->ts.type)
8927 case BT_CHARACTER:
8928 tmp = size_of_string_in_bytes (mold_expr->ts.kind, argse.string_length);
8929 mold_type = gfc_get_character_type_len (mold_expr->ts.kind,
8930 argse.string_length);
8931 break;
8932 case BT_CLASS:
8933 if (scalar_mold)
8934 class_ref = argse.expr;
8935 else
8936 class_ref = TREE_OPERAND (argse.expr, 0);
8937 tmp = gfc_class_vtab_size_get (class_ref);
8938 if (UNLIMITED_POLY (arg->expr))
8939 tmp = gfc_resize_class_size_with_len (&argse.pre, class_ref, tmp);
8940 break;
8941 default:
8942 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
8943 break;
8946 /* Do not fix dest_word_len if it is a variable, since the temporary can wind
8947 up being used before the assignment. */
8948 if (mold_expr->ts.type == BT_CHARACTER && mold_expr->ts.deferred)
8949 dest_word_len = tmp;
8950 else
8952 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
8953 gfc_add_modify (&se->pre, dest_word_len, tmp);
8956 /* Finally convert SIZE, if it is present. */
8957 arg = arg->next;
8958 size_words = gfc_create_var (gfc_array_index_type, NULL);
8960 if (arg->expr)
8962 gfc_init_se (&argse, NULL);
8963 gfc_conv_expr_reference (&argse, arg->expr);
8964 tmp = convert (gfc_array_index_type,
8965 build_fold_indirect_ref_loc (input_location,
8966 argse.expr));
8967 gfc_add_block_to_block (&se->pre, &argse.pre);
8968 gfc_add_block_to_block (&se->post, &argse.post);
8970 else
8971 tmp = NULL_TREE;
8973 /* Separate array and scalar results. */
8974 if (scalar_mold && tmp == NULL_TREE)
8975 goto scalar_transfer;
8977 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
8978 if (tmp != NULL_TREE)
8979 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8980 tmp, dest_word_len);
8981 else
8982 tmp = source_bytes;
8984 gfc_add_modify (&se->pre, size_bytes, tmp);
8985 gfc_add_modify (&se->pre, size_words,
8986 fold_build2_loc (input_location, CEIL_DIV_EXPR,
8987 gfc_array_index_type,
8988 size_bytes, dest_word_len));
8990 /* Evaluate the bounds of the result. If the loop range exists, we have
8991 to check if it is too large. If so, we modify loop->to be consistent
8992 with min(size, size(source)). Otherwise, size is made consistent with
8993 the loop range, so that the right number of bytes is transferred.*/
8994 n = se->loop->order[0];
8995 if (se->loop->to[n] != NULL_TREE)
8997 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8998 se->loop->to[n], se->loop->from[n]);
8999 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
9000 tmp, gfc_index_one_node);
9001 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
9002 tmp, size_words);
9003 gfc_add_modify (&se->pre, size_words, tmp);
9004 gfc_add_modify (&se->pre, size_bytes,
9005 fold_build2_loc (input_location, MULT_EXPR,
9006 gfc_array_index_type,
9007 size_words, dest_word_len));
9008 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
9009 size_words, se->loop->from[n]);
9010 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
9011 upper, gfc_index_one_node);
9013 else
9015 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
9016 size_words, gfc_index_one_node);
9017 se->loop->from[n] = gfc_index_zero_node;
9020 se->loop->to[n] = upper;
9022 /* Build a destination descriptor, using the pointer, source, as the
9023 data field. */
9024 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
9025 NULL_TREE, false, true, false, &expr->where);
9027 /* Cast the pointer to the result. */
9028 tmp = gfc_conv_descriptor_data_get (info->descriptor);
9029 tmp = fold_convert (pvoid_type_node, tmp);
9031 /* Use memcpy to do the transfer. */
9033 = build_call_expr_loc (input_location,
9034 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
9035 fold_convert (pvoid_type_node, source),
9036 fold_convert (size_type_node,
9037 fold_build2_loc (input_location,
9038 MIN_EXPR,
9039 gfc_array_index_type,
9040 size_bytes,
9041 source_bytes)));
9042 gfc_add_expr_to_block (&se->pre, tmp);
9044 se->expr = info->descriptor;
9045 if (expr->ts.type == BT_CHARACTER)
9047 tmp = fold_convert (gfc_charlen_type_node,
9048 TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind)));
9049 se->string_length = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
9050 gfc_charlen_type_node,
9051 dest_word_len, tmp);
9054 return;
9056 /* Deal with scalar results. */
9057 scalar_transfer:
9058 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
9059 dest_word_len, source_bytes);
9060 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
9061 extent, gfc_index_zero_node);
9063 if (expr->ts.type == BT_CHARACTER)
9065 tree direct, indirect, free;
9067 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
9068 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
9069 "transfer");
9071 /* If source is longer than the destination, use a pointer to
9072 the source directly. */
9073 gfc_init_block (&block);
9074 gfc_add_modify (&block, tmpdecl, ptr);
9075 direct = gfc_finish_block (&block);
9077 /* Otherwise, allocate a string with the length of the destination
9078 and copy the source into it. */
9079 gfc_init_block (&block);
9080 tmp = gfc_get_pchar_type (expr->ts.kind);
9081 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
9082 gfc_add_modify (&block, tmpdecl,
9083 fold_convert (TREE_TYPE (ptr), tmp));
9084 tmp = build_call_expr_loc (input_location,
9085 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
9086 fold_convert (pvoid_type_node, tmpdecl),
9087 fold_convert (pvoid_type_node, ptr),
9088 fold_convert (size_type_node, extent));
9089 gfc_add_expr_to_block (&block, tmp);
9090 indirect = gfc_finish_block (&block);
9092 /* Wrap it up with the condition. */
9093 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
9094 dest_word_len, source_bytes);
9095 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
9096 gfc_add_expr_to_block (&se->pre, tmp);
9098 /* Free the temporary string, if necessary. */
9099 free = gfc_call_free (tmpdecl);
9100 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
9101 dest_word_len, source_bytes);
9102 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
9103 gfc_add_expr_to_block (&se->post, tmp);
9105 se->expr = tmpdecl;
9106 tmp = fold_convert (gfc_charlen_type_node,
9107 TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind)));
9108 se->string_length = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
9109 gfc_charlen_type_node,
9110 dest_word_len, tmp);
9112 else
9114 tmpdecl = gfc_create_var (mold_type, "transfer");
9116 ptr = convert (build_pointer_type (mold_type), source);
9118 /* For CLASS results, allocate the needed memory first. */
9119 if (mold_expr->ts.type == BT_CLASS)
9121 tree cdata;
9122 cdata = gfc_class_data_get (tmpdecl);
9123 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
9124 gfc_add_modify (&se->pre, cdata, tmp);
9127 /* Use memcpy to do the transfer. */
9128 if (mold_expr->ts.type == BT_CLASS)
9129 tmp = gfc_class_data_get (tmpdecl);
9130 else
9131 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
9133 tmp = build_call_expr_loc (input_location,
9134 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
9135 fold_convert (pvoid_type_node, tmp),
9136 fold_convert (pvoid_type_node, ptr),
9137 fold_convert (size_type_node, extent));
9138 gfc_add_expr_to_block (&se->pre, tmp);
9140 /* For CLASS results, set the _vptr. */
9141 if (mold_expr->ts.type == BT_CLASS)
9142 gfc_reset_vptr (&se->pre, nullptr, tmpdecl, source_expr->ts.u.derived);
9144 se->expr = tmpdecl;
9149 /* Generate a call to caf_is_present. */
9151 static tree
9152 trans_caf_is_present (gfc_se *se, gfc_expr *expr)
9154 tree caf_reference, caf_decl, token, image_index;
9156 /* Compile the reference chain. */
9157 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
9158 gcc_assert (caf_reference != NULL_TREE);
9160 caf_decl = gfc_get_tree_for_caf_expr (expr);
9161 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
9162 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
9163 image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
9164 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
9165 expr);
9167 return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
9168 3, token, image_index, caf_reference);
9172 /* Test whether this ref-chain refs this image only. */
9174 static bool
9175 caf_this_image_ref (gfc_ref *ref)
9177 for ( ; ref; ref = ref->next)
9178 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
9179 return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
9181 return false;
9185 /* Generate code for the ALLOCATED intrinsic.
9186 Generate inline code that directly check the address of the argument. */
9188 static void
9189 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
9191 gfc_se arg1se;
9192 tree tmp;
9193 bool coindexed_caf_comp = false;
9194 gfc_expr *e = expr->value.function.actual->expr;
9196 gfc_init_se (&arg1se, NULL);
9197 if (e->ts.type == BT_CLASS)
9199 /* Make sure that class array expressions have both a _data
9200 component reference and an array reference.... */
9201 if (CLASS_DATA (e)->attr.dimension)
9202 gfc_add_class_array_ref (e);
9203 /* .... whilst scalars only need the _data component. */
9204 else
9205 gfc_add_data_component (e);
9208 /* When 'e' references an allocatable component in a coarray, then call
9209 the caf-library function caf_is_present (). */
9210 if (flag_coarray == GFC_FCOARRAY_LIB && e->expr_type == EXPR_FUNCTION
9211 && e->value.function.isym
9212 && e->value.function.isym->id == GFC_ISYM_CAF_GET)
9214 e = e->value.function.actual->expr;
9215 if (gfc_expr_attr (e).codimension)
9217 /* Last partref is the coindexed coarray. As coarrays are collectively
9218 (de)allocated, the allocation status must be the same as the one of
9219 the local allocation. Convert to local access. */
9220 for (gfc_ref *ref = e->ref; ref; ref = ref->next)
9221 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
9223 for (int i = ref->u.ar.dimen;
9224 i < ref->u.ar.dimen + ref->u.ar.codimen; ++i)
9225 ref->u.ar.dimen_type[i] = DIMEN_THIS_IMAGE;
9226 break;
9229 else if (!caf_this_image_ref (e->ref))
9230 coindexed_caf_comp = true;
9232 if (coindexed_caf_comp)
9233 tmp = trans_caf_is_present (se, e);
9234 else
9236 if (e->rank == 0)
9238 /* Allocatable scalar. */
9239 arg1se.want_pointer = 1;
9240 gfc_conv_expr (&arg1se, e);
9241 tmp = arg1se.expr;
9243 else
9245 /* Allocatable array. */
9246 arg1se.descriptor_only = 1;
9247 gfc_conv_expr_descriptor (&arg1se, e);
9248 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
9251 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
9252 fold_convert (TREE_TYPE (tmp), null_pointer_node));
9255 /* Components of pointer array references sometimes come back with a pre block. */
9256 if (arg1se.pre.head)
9257 gfc_add_block_to_block (&se->pre, &arg1se.pre);
9259 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
9263 /* Generate code for the ASSOCIATED intrinsic.
9264 If both POINTER and TARGET are arrays, generate a call to library function
9265 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
9266 In other cases, generate inline code that directly compare the address of
9267 POINTER with the address of TARGET. */
9269 static void
9270 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
9272 gfc_actual_arglist *arg1;
9273 gfc_actual_arglist *arg2;
9274 gfc_se arg1se;
9275 gfc_se arg2se;
9276 tree tmp2;
9277 tree tmp;
9278 tree nonzero_arraylen = NULL_TREE;
9279 gfc_ss *ss;
9280 bool scalar;
9282 gfc_init_se (&arg1se, NULL);
9283 gfc_init_se (&arg2se, NULL);
9284 arg1 = expr->value.function.actual;
9285 arg2 = arg1->next;
9287 /* Check whether the expression is a scalar or not; we cannot use
9288 arg1->expr->rank as it can be nonzero for proc pointers. */
9289 ss = gfc_walk_expr (arg1->expr);
9290 scalar = ss == gfc_ss_terminator;
9291 if (!scalar)
9292 gfc_free_ss_chain (ss);
9294 if (!arg2->expr)
9296 /* No optional target. */
9297 if (scalar)
9299 /* A pointer to a scalar. */
9300 arg1se.want_pointer = 1;
9301 gfc_conv_expr (&arg1se, arg1->expr);
9302 if (arg1->expr->symtree->n.sym->attr.proc_pointer
9303 && arg1->expr->symtree->n.sym->attr.dummy)
9304 arg1se.expr = build_fold_indirect_ref_loc (input_location,
9305 arg1se.expr);
9306 if (arg1->expr->ts.type == BT_CLASS)
9308 tmp2 = gfc_class_data_get (arg1se.expr);
9309 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
9310 tmp2 = gfc_conv_descriptor_data_get (tmp2);
9312 else
9313 tmp2 = arg1se.expr;
9315 else
9317 /* A pointer to an array. */
9318 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
9319 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
9321 gfc_add_block_to_block (&se->pre, &arg1se.pre);
9322 gfc_add_block_to_block (&se->post, &arg1se.post);
9323 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp2,
9324 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
9325 se->expr = tmp;
9327 else
9329 /* An optional target. */
9330 if (arg2->expr->ts.type == BT_CLASS
9331 && arg2->expr->expr_type != EXPR_FUNCTION)
9332 gfc_add_data_component (arg2->expr);
9334 if (scalar)
9336 /* A pointer to a scalar. */
9337 arg1se.want_pointer = 1;
9338 gfc_conv_expr (&arg1se, arg1->expr);
9339 if (arg1->expr->symtree->n.sym->attr.proc_pointer
9340 && arg1->expr->symtree->n.sym->attr.dummy)
9341 arg1se.expr = build_fold_indirect_ref_loc (input_location,
9342 arg1se.expr);
9343 if (arg1->expr->ts.type == BT_CLASS)
9344 arg1se.expr = gfc_class_data_get (arg1se.expr);
9346 arg2se.want_pointer = 1;
9347 gfc_conv_expr (&arg2se, arg2->expr);
9348 if (arg2->expr->symtree->n.sym->attr.proc_pointer
9349 && arg2->expr->symtree->n.sym->attr.dummy)
9350 arg2se.expr = build_fold_indirect_ref_loc (input_location,
9351 arg2se.expr);
9352 if (arg2->expr->ts.type == BT_CLASS)
9354 arg2se.expr = gfc_evaluate_now (arg2se.expr, &arg2se.pre);
9355 arg2se.expr = gfc_class_data_get (arg2se.expr);
9357 gfc_add_block_to_block (&se->pre, &arg1se.pre);
9358 gfc_add_block_to_block (&se->post, &arg1se.post);
9359 gfc_add_block_to_block (&se->pre, &arg2se.pre);
9360 gfc_add_block_to_block (&se->post, &arg2se.post);
9361 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
9362 arg1se.expr, arg2se.expr);
9363 tmp2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9364 arg1se.expr, null_pointer_node);
9365 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9366 logical_type_node, tmp, tmp2);
9368 else
9370 /* An array pointer of zero length is not associated if target is
9371 present. */
9372 arg1se.descriptor_only = 1;
9373 gfc_conv_expr_lhs (&arg1se, arg1->expr);
9374 if (arg1->expr->rank == -1)
9376 tmp = gfc_conv_descriptor_rank (arg1se.expr);
9377 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9378 TREE_TYPE (tmp), tmp,
9379 build_int_cst (TREE_TYPE (tmp), 1));
9381 else
9382 tmp = gfc_rank_cst[arg1->expr->rank - 1];
9383 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
9384 if (arg2->expr->rank != 0)
9385 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
9386 logical_type_node, tmp,
9387 build_int_cst (TREE_TYPE (tmp), 0));
9389 /* A pointer to an array, call library function _gfor_associated. */
9390 arg1se.want_pointer = 1;
9391 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
9392 gfc_add_block_to_block (&se->pre, &arg1se.pre);
9393 gfc_add_block_to_block (&se->post, &arg1se.post);
9395 arg2se.want_pointer = 1;
9396 arg2se.force_no_tmp = 1;
9397 if (arg2->expr->rank != 0)
9398 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
9399 else
9401 gfc_conv_expr (&arg2se, arg2->expr);
9402 arg2se.expr
9403 = gfc_conv_scalar_to_descriptor (&arg2se, arg2se.expr,
9404 gfc_expr_attr (arg2->expr));
9405 arg2se.expr = gfc_build_addr_expr (NULL_TREE, arg2se.expr);
9407 gfc_add_block_to_block (&se->pre, &arg2se.pre);
9408 gfc_add_block_to_block (&se->post, &arg2se.post);
9409 se->expr = build_call_expr_loc (input_location,
9410 gfor_fndecl_associated, 2,
9411 arg1se.expr, arg2se.expr);
9412 se->expr = convert (logical_type_node, se->expr);
9413 if (arg2->expr->rank != 0)
9414 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9415 logical_type_node, se->expr,
9416 nonzero_arraylen);
9419 /* If target is present zero character length pointers cannot
9420 be associated. */
9421 if (arg1->expr->ts.type == BT_CHARACTER)
9423 tmp = arg1se.string_length;
9424 tmp = fold_build2_loc (input_location, NE_EXPR,
9425 logical_type_node, tmp,
9426 build_zero_cst (TREE_TYPE (tmp)));
9427 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9428 logical_type_node, se->expr, tmp);
9432 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9436 /* Generate code for the SAME_TYPE_AS intrinsic.
9437 Generate inline code that directly checks the vindices. */
9439 static void
9440 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
9442 gfc_expr *a, *b;
9443 gfc_se se1, se2;
9444 tree tmp;
9445 tree conda = NULL_TREE, condb = NULL_TREE;
9447 gfc_init_se (&se1, NULL);
9448 gfc_init_se (&se2, NULL);
9450 a = expr->value.function.actual->expr;
9451 b = expr->value.function.actual->next->expr;
9453 bool unlimited_poly_a = UNLIMITED_POLY (a);
9454 bool unlimited_poly_b = UNLIMITED_POLY (b);
9455 if (unlimited_poly_a)
9457 se1.want_pointer = 1;
9458 gfc_add_vptr_component (a);
9460 else if (a->ts.type == BT_CLASS)
9462 gfc_add_vptr_component (a);
9463 gfc_add_hash_component (a);
9465 else if (a->ts.type == BT_DERIVED)
9466 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
9467 a->ts.u.derived->hash_value);
9469 if (unlimited_poly_b)
9471 se2.want_pointer = 1;
9472 gfc_add_vptr_component (b);
9474 else if (b->ts.type == BT_CLASS)
9476 gfc_add_vptr_component (b);
9477 gfc_add_hash_component (b);
9479 else if (b->ts.type == BT_DERIVED)
9480 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
9481 b->ts.u.derived->hash_value);
9483 gfc_conv_expr (&se1, a);
9484 gfc_conv_expr (&se2, b);
9486 if (unlimited_poly_a)
9488 conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9489 se1.expr,
9490 build_int_cst (TREE_TYPE (se1.expr), 0));
9491 se1.expr = gfc_vptr_hash_get (se1.expr);
9494 if (unlimited_poly_b)
9496 condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9497 se2.expr,
9498 build_int_cst (TREE_TYPE (se2.expr), 0));
9499 se2.expr = gfc_vptr_hash_get (se2.expr);
9502 tmp = fold_build2_loc (input_location, EQ_EXPR,
9503 logical_type_node, se1.expr,
9504 fold_convert (TREE_TYPE (se1.expr), se2.expr));
9506 if (conda)
9507 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
9508 logical_type_node, conda, tmp);
9510 if (condb)
9511 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
9512 logical_type_node, condb, tmp);
9514 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
9518 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
9520 static void
9521 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
9523 tree args[2];
9525 gfc_conv_intrinsic_function_args (se, expr, args, 2);
9526 se->expr = build_call_expr_loc (input_location,
9527 gfor_fndecl_sc_kind, 2, args[0], args[1]);
9528 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9532 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
9534 static void
9535 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
9537 tree arg, type;
9539 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
9541 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
9542 type = gfc_get_int_type (4);
9543 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
9545 /* Convert it to the required type. */
9546 type = gfc_typenode_for_spec (&expr->ts);
9547 se->expr = build_call_expr_loc (input_location,
9548 gfor_fndecl_si_kind, 1, arg);
9549 se->expr = fold_convert (type, se->expr);
9553 /* Generate code for SELECTED_LOGICAL_KIND (BITS) intrinsic function. */
9555 static void
9556 gfc_conv_intrinsic_sl_kind (gfc_se *se, gfc_expr *expr)
9558 tree arg, type;
9560 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
9562 /* The argument to SELECTED_LOGICAL_KIND is INTEGER(4). */
9563 type = gfc_get_int_type (4);
9564 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
9566 /* Convert it to the required type. */
9567 type = gfc_typenode_for_spec (&expr->ts);
9568 se->expr = build_call_expr_loc (input_location,
9569 gfor_fndecl_sl_kind, 1, arg);
9570 se->expr = fold_convert (type, se->expr);
9574 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
9576 static void
9577 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
9579 gfc_actual_arglist *actual;
9580 tree type;
9581 gfc_se argse;
9582 vec<tree, va_gc> *args = NULL;
9584 for (actual = expr->value.function.actual; actual; actual = actual->next)
9586 gfc_init_se (&argse, se);
9588 /* Pass a NULL pointer for an absent arg. */
9589 if (actual->expr == NULL)
9590 argse.expr = null_pointer_node;
9591 else
9593 gfc_typespec ts;
9594 gfc_clear_ts (&ts);
9596 if (actual->expr->ts.kind != gfc_c_int_kind)
9598 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
9599 ts.type = BT_INTEGER;
9600 ts.kind = gfc_c_int_kind;
9601 gfc_convert_type (actual->expr, &ts, 2);
9603 gfc_conv_expr_reference (&argse, actual->expr);
9606 gfc_add_block_to_block (&se->pre, &argse.pre);
9607 gfc_add_block_to_block (&se->post, &argse.post);
9608 vec_safe_push (args, argse.expr);
9611 /* Convert it to the required type. */
9612 type = gfc_typenode_for_spec (&expr->ts);
9613 se->expr = build_call_expr_loc_vec (input_location,
9614 gfor_fndecl_sr_kind, args);
9615 se->expr = fold_convert (type, se->expr);
9619 /* Generate code for TRIM (A) intrinsic function. */
9621 static void
9622 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
9624 tree var;
9625 tree len;
9626 tree addr;
9627 tree tmp;
9628 tree cond;
9629 tree fndecl;
9630 tree function;
9631 tree *args;
9632 unsigned int num_args;
9634 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
9635 args = XALLOCAVEC (tree, num_args);
9637 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
9638 addr = gfc_build_addr_expr (ppvoid_type_node, var);
9639 len = gfc_create_var (gfc_charlen_type_node, "len");
9641 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
9642 args[0] = gfc_build_addr_expr (NULL_TREE, len);
9643 args[1] = addr;
9645 if (expr->ts.kind == 1)
9646 function = gfor_fndecl_string_trim;
9647 else if (expr->ts.kind == 4)
9648 function = gfor_fndecl_string_trim_char4;
9649 else
9650 gcc_unreachable ();
9652 fndecl = build_addr (function);
9653 tmp = build_call_array_loc (input_location,
9654 TREE_TYPE (TREE_TYPE (function)), fndecl,
9655 num_args, args);
9656 gfc_add_expr_to_block (&se->pre, tmp);
9658 /* Free the temporary afterwards, if necessary. */
9659 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
9660 len, build_int_cst (TREE_TYPE (len), 0));
9661 tmp = gfc_call_free (var);
9662 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
9663 gfc_add_expr_to_block (&se->post, tmp);
9665 se->expr = var;
9666 se->string_length = len;
9670 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
9672 static void
9673 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
9675 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
9676 tree type, cond, tmp, count, exit_label, n, max, largest;
9677 tree size;
9678 stmtblock_t block, body;
9679 int i;
9681 /* We store in charsize the size of a character. */
9682 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
9683 size = build_int_cst (sizetype, gfc_character_kinds[i].bit_size / 8);
9685 /* Get the arguments. */
9686 gfc_conv_intrinsic_function_args (se, expr, args, 3);
9687 slen = fold_convert (sizetype, gfc_evaluate_now (args[0], &se->pre));
9688 src = args[1];
9689 ncopies = gfc_evaluate_now (args[2], &se->pre);
9690 ncopies_type = TREE_TYPE (ncopies);
9692 /* Check that NCOPIES is not negative. */
9693 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, ncopies,
9694 build_int_cst (ncopies_type, 0));
9695 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
9696 "Argument NCOPIES of REPEAT intrinsic is negative "
9697 "(its value is %ld)",
9698 fold_convert (long_integer_type_node, ncopies));
9700 /* If the source length is zero, any non negative value of NCOPIES
9701 is valid, and nothing happens. */
9702 n = gfc_create_var (ncopies_type, "ncopies");
9703 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
9704 size_zero_node);
9705 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
9706 build_int_cst (ncopies_type, 0), ncopies);
9707 gfc_add_modify (&se->pre, n, tmp);
9708 ncopies = n;
9710 /* Check that ncopies is not too large: ncopies should be less than
9711 (or equal to) MAX / slen, where MAX is the maximal integer of
9712 the gfc_charlen_type_node type. If slen == 0, we need a special
9713 case to avoid the division by zero. */
9714 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, sizetype,
9715 fold_convert (sizetype,
9716 TYPE_MAX_VALUE (gfc_charlen_type_node)),
9717 slen);
9718 largest = TYPE_PRECISION (sizetype) > TYPE_PRECISION (ncopies_type)
9719 ? sizetype : ncopies_type;
9720 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
9721 fold_convert (largest, ncopies),
9722 fold_convert (largest, max));
9723 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
9724 size_zero_node);
9725 cond = fold_build3_loc (input_location, COND_EXPR, logical_type_node, tmp,
9726 logical_false_node, cond);
9727 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
9728 "Argument NCOPIES of REPEAT intrinsic is too large");
9730 /* Compute the destination length. */
9731 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
9732 fold_convert (gfc_charlen_type_node, slen),
9733 fold_convert (gfc_charlen_type_node, ncopies));
9734 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
9735 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
9737 /* Generate the code to do the repeat operation:
9738 for (i = 0; i < ncopies; i++)
9739 memmove (dest + (i * slen * size), src, slen*size); */
9740 gfc_start_block (&block);
9741 count = gfc_create_var (sizetype, "count");
9742 gfc_add_modify (&block, count, size_zero_node);
9743 exit_label = gfc_build_label_decl (NULL_TREE);
9745 /* Start the loop body. */
9746 gfc_start_block (&body);
9748 /* Exit the loop if count >= ncopies. */
9749 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, count,
9750 fold_convert (sizetype, ncopies));
9751 tmp = build1_v (GOTO_EXPR, exit_label);
9752 TREE_USED (exit_label) = 1;
9753 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
9754 build_empty_stmt (input_location));
9755 gfc_add_expr_to_block (&body, tmp);
9757 /* Call memmove (dest + (i*slen*size), src, slen*size). */
9758 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, slen,
9759 count);
9760 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, tmp,
9761 size);
9762 tmp = fold_build_pointer_plus_loc (input_location,
9763 fold_convert (pvoid_type_node, dest), tmp);
9764 tmp = build_call_expr_loc (input_location,
9765 builtin_decl_explicit (BUILT_IN_MEMMOVE),
9766 3, tmp, src,
9767 fold_build2_loc (input_location, MULT_EXPR,
9768 size_type_node, slen, size));
9769 gfc_add_expr_to_block (&body, tmp);
9771 /* Increment count. */
9772 tmp = fold_build2_loc (input_location, PLUS_EXPR, sizetype,
9773 count, size_one_node);
9774 gfc_add_modify (&body, count, tmp);
9776 /* Build the loop. */
9777 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
9778 gfc_add_expr_to_block (&block, tmp);
9780 /* Add the exit label. */
9781 tmp = build1_v (LABEL_EXPR, exit_label);
9782 gfc_add_expr_to_block (&block, tmp);
9784 /* Finish the block. */
9785 tmp = gfc_finish_block (&block);
9786 gfc_add_expr_to_block (&se->pre, tmp);
9788 /* Set the result value. */
9789 se->expr = dest;
9790 se->string_length = dlen;
9794 /* Generate code for the IARGC intrinsic. */
9796 static void
9797 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
9799 tree tmp;
9800 tree fndecl;
9801 tree type;
9803 /* Call the library function. This always returns an INTEGER(4). */
9804 fndecl = gfor_fndecl_iargc;
9805 tmp = build_call_expr_loc (input_location,
9806 fndecl, 0);
9808 /* Convert it to the required type. */
9809 type = gfc_typenode_for_spec (&expr->ts);
9810 tmp = fold_convert (type, tmp);
9812 se->expr = tmp;
9816 /* Generate code for the KILL intrinsic. */
9818 static void
9819 conv_intrinsic_kill (gfc_se *se, gfc_expr *expr)
9821 tree *args;
9822 tree int4_type_node = gfc_get_int_type (4);
9823 tree pid;
9824 tree sig;
9825 tree tmp;
9826 unsigned int num_args;
9828 num_args = gfc_intrinsic_argument_list_length (expr);
9829 args = XALLOCAVEC (tree, num_args);
9830 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
9832 /* Convert PID to a INTEGER(4) entity. */
9833 pid = convert (int4_type_node, args[0]);
9835 /* Convert SIG to a INTEGER(4) entity. */
9836 sig = convert (int4_type_node, args[1]);
9838 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill, 2, pid, sig);
9840 se->expr = fold_convert (TREE_TYPE (args[0]), tmp);
9844 static tree
9845 conv_intrinsic_kill_sub (gfc_code *code)
9847 stmtblock_t block;
9848 gfc_se se, se_stat;
9849 tree int4_type_node = gfc_get_int_type (4);
9850 tree pid;
9851 tree sig;
9852 tree statp;
9853 tree tmp;
9855 /* Make the function call. */
9856 gfc_init_block (&block);
9857 gfc_init_se (&se, NULL);
9859 /* Convert PID to a INTEGER(4) entity. */
9860 gfc_conv_expr (&se, code->ext.actual->expr);
9861 gfc_add_block_to_block (&block, &se.pre);
9862 pid = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
9863 gfc_add_block_to_block (&block, &se.post);
9865 /* Convert SIG to a INTEGER(4) entity. */
9866 gfc_conv_expr (&se, code->ext.actual->next->expr);
9867 gfc_add_block_to_block (&block, &se.pre);
9868 sig = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
9869 gfc_add_block_to_block (&block, &se.post);
9871 /* Deal with an optional STATUS. */
9872 if (code->ext.actual->next->next->expr)
9874 gfc_init_se (&se_stat, NULL);
9875 gfc_conv_expr (&se_stat, code->ext.actual->next->next->expr);
9876 statp = gfc_create_var (gfc_get_int_type (4), "_statp");
9878 else
9879 statp = NULL_TREE;
9881 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill_sub, 3, pid, sig,
9882 statp ? gfc_build_addr_expr (NULL_TREE, statp) : null_pointer_node);
9884 gfc_add_expr_to_block (&block, tmp);
9886 if (statp && statp != se_stat.expr)
9887 gfc_add_modify (&block, se_stat.expr,
9888 fold_convert (TREE_TYPE (se_stat.expr), statp));
9890 return gfc_finish_block (&block);
9895 /* The loc intrinsic returns the address of its argument as
9896 gfc_index_integer_kind integer. */
9898 static void
9899 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
9901 tree temp_var;
9902 gfc_expr *arg_expr;
9904 gcc_assert (!se->ss);
9906 arg_expr = expr->value.function.actual->expr;
9907 if (arg_expr->rank == 0)
9909 if (arg_expr->ts.type == BT_CLASS)
9910 gfc_add_data_component (arg_expr);
9911 gfc_conv_expr_reference (se, arg_expr);
9913 else
9914 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
9915 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
9917 /* Create a temporary variable for loc return value. Without this,
9918 we get an error an ICE in gcc/expr.cc(expand_expr_addr_expr_1). */
9919 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
9920 gfc_add_modify (&se->pre, temp_var, se->expr);
9921 se->expr = temp_var;
9925 /* The following routine generates code for the intrinsic
9926 functions from the ISO_C_BINDING module:
9927 * C_LOC
9928 * C_FUNLOC
9929 * C_ASSOCIATED */
9931 static void
9932 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
9934 gfc_actual_arglist *arg = expr->value.function.actual;
9936 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
9938 if (arg->expr->rank == 0)
9939 gfc_conv_expr_reference (se, arg->expr);
9940 else if (gfc_is_simply_contiguous (arg->expr, false, false))
9941 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
9942 else
9944 gfc_conv_expr_descriptor (se, arg->expr);
9945 se->expr = gfc_conv_descriptor_data_get (se->expr);
9948 /* TODO -- the following two lines shouldn't be necessary, but if
9949 they're removed, a bug is exposed later in the code path.
9950 This workaround was thus introduced, but will have to be
9951 removed; please see PR 35150 for details about the issue. */
9952 se->expr = convert (pvoid_type_node, se->expr);
9953 se->expr = gfc_evaluate_now (se->expr, &se->pre);
9955 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
9956 gfc_conv_expr_reference (se, arg->expr);
9957 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
9959 gfc_se arg1se;
9960 gfc_se arg2se;
9962 /* Build the addr_expr for the first argument. The argument is
9963 already an *address* so we don't need to set want_pointer in
9964 the gfc_se. */
9965 gfc_init_se (&arg1se, NULL);
9966 gfc_conv_expr (&arg1se, arg->expr);
9967 gfc_add_block_to_block (&se->pre, &arg1se.pre);
9968 gfc_add_block_to_block (&se->post, &arg1se.post);
9970 /* See if we were given two arguments. */
9971 if (arg->next->expr == NULL)
9972 /* Only given one arg so generate a null and do a
9973 not-equal comparison against the first arg. */
9974 se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9975 arg1se.expr,
9976 fold_convert (TREE_TYPE (arg1se.expr),
9977 null_pointer_node));
9978 else
9980 tree eq_expr;
9981 tree not_null_expr;
9983 /* Given two arguments so build the arg2se from second arg. */
9984 gfc_init_se (&arg2se, NULL);
9985 gfc_conv_expr (&arg2se, arg->next->expr);
9986 gfc_add_block_to_block (&se->pre, &arg2se.pre);
9987 gfc_add_block_to_block (&se->post, &arg2se.post);
9989 /* Generate test to compare that the two args are equal. */
9990 eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
9991 arg1se.expr, arg2se.expr);
9992 /* Generate test to ensure that the first arg is not null. */
9993 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
9994 logical_type_node,
9995 arg1se.expr, null_pointer_node);
9997 /* Finally, the generated test must check that both arg1 is not
9998 NULL and that it is equal to the second arg. */
9999 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10000 logical_type_node,
10001 not_null_expr, eq_expr);
10004 else
10005 gcc_unreachable ();
10009 /* The following routine generates code for the intrinsic
10010 subroutines from the ISO_C_BINDING module:
10011 * C_F_POINTER
10012 * C_F_PROCPOINTER. */
10014 static tree
10015 conv_isocbinding_subroutine (gfc_code *code)
10017 gfc_se se;
10018 gfc_se cptrse;
10019 gfc_se fptrse;
10020 gfc_se shapese;
10021 gfc_ss *shape_ss;
10022 tree desc, dim, tmp, stride, offset;
10023 stmtblock_t body, block;
10024 gfc_loopinfo loop;
10025 gfc_actual_arglist *arg = code->ext.actual;
10027 gfc_init_se (&se, NULL);
10028 gfc_init_se (&cptrse, NULL);
10029 gfc_conv_expr (&cptrse, arg->expr);
10030 gfc_add_block_to_block (&se.pre, &cptrse.pre);
10031 gfc_add_block_to_block (&se.post, &cptrse.post);
10033 gfc_init_se (&fptrse, NULL);
10034 if (arg->next->expr->rank == 0)
10036 fptrse.want_pointer = 1;
10037 gfc_conv_expr (&fptrse, arg->next->expr);
10038 gfc_add_block_to_block (&se.pre, &fptrse.pre);
10039 gfc_add_block_to_block (&se.post, &fptrse.post);
10040 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
10041 && arg->next->expr->symtree->n.sym->attr.dummy)
10042 fptrse.expr = build_fold_indirect_ref_loc (input_location,
10043 fptrse.expr);
10044 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
10045 TREE_TYPE (fptrse.expr),
10046 fptrse.expr,
10047 fold_convert (TREE_TYPE (fptrse.expr),
10048 cptrse.expr));
10049 gfc_add_expr_to_block (&se.pre, se.expr);
10050 gfc_add_block_to_block (&se.pre, &se.post);
10051 return gfc_finish_block (&se.pre);
10054 gfc_start_block (&block);
10056 /* Get the descriptor of the Fortran pointer. */
10057 fptrse.descriptor_only = 1;
10058 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
10059 gfc_add_block_to_block (&block, &fptrse.pre);
10060 desc = fptrse.expr;
10062 /* Set the span field. */
10063 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
10064 tmp = fold_convert (gfc_array_index_type, tmp);
10065 gfc_conv_descriptor_span_set (&block, desc, tmp);
10067 /* Set data value, dtype, and offset. */
10068 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
10069 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
10070 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
10071 gfc_get_dtype (TREE_TYPE (desc)));
10073 /* Start scalarization of the bounds, using the shape argument. */
10075 shape_ss = gfc_walk_expr (arg->next->next->expr);
10076 gcc_assert (shape_ss != gfc_ss_terminator);
10077 gfc_init_se (&shapese, NULL);
10079 gfc_init_loopinfo (&loop);
10080 gfc_add_ss_to_loop (&loop, shape_ss);
10081 gfc_conv_ss_startstride (&loop);
10082 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
10083 gfc_mark_ss_chain_used (shape_ss, 1);
10085 gfc_copy_loopinfo_to_se (&shapese, &loop);
10086 shapese.ss = shape_ss;
10088 stride = gfc_create_var (gfc_array_index_type, "stride");
10089 offset = gfc_create_var (gfc_array_index_type, "offset");
10090 gfc_add_modify (&block, stride, gfc_index_one_node);
10091 gfc_add_modify (&block, offset, gfc_index_zero_node);
10093 /* Loop body. */
10094 gfc_start_scalarized_body (&loop, &body);
10096 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
10097 loop.loopvar[0], loop.from[0]);
10099 /* Set bounds and stride. */
10100 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
10101 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
10103 gfc_conv_expr (&shapese, arg->next->next->expr);
10104 gfc_add_block_to_block (&body, &shapese.pre);
10105 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
10106 gfc_add_block_to_block (&body, &shapese.post);
10108 /* Calculate offset. */
10109 gfc_add_modify (&body, offset,
10110 fold_build2_loc (input_location, PLUS_EXPR,
10111 gfc_array_index_type, offset, stride));
10112 /* Update stride. */
10113 gfc_add_modify (&body, stride,
10114 fold_build2_loc (input_location, MULT_EXPR,
10115 gfc_array_index_type, stride,
10116 fold_convert (gfc_array_index_type,
10117 shapese.expr)));
10118 /* Finish scalarization loop. */
10119 gfc_trans_scalarizing_loops (&loop, &body);
10120 gfc_add_block_to_block (&block, &loop.pre);
10121 gfc_add_block_to_block (&block, &loop.post);
10122 gfc_add_block_to_block (&block, &fptrse.post);
10123 gfc_cleanup_loop (&loop);
10125 gfc_add_modify (&block, offset,
10126 fold_build1_loc (input_location, NEGATE_EXPR,
10127 gfc_array_index_type, offset));
10128 gfc_conv_descriptor_offset_set (&block, desc, offset);
10130 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
10131 gfc_add_block_to_block (&se.pre, &se.post);
10132 return gfc_finish_block (&se.pre);
10136 /* Save and restore floating-point state. */
10138 tree
10139 gfc_save_fp_state (stmtblock_t *block)
10141 tree type, fpstate, tmp;
10143 type = build_array_type (char_type_node,
10144 build_range_type (size_type_node, size_zero_node,
10145 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
10146 fpstate = gfc_create_var (type, "fpstate");
10147 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
10149 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
10150 1, fpstate);
10151 gfc_add_expr_to_block (block, tmp);
10153 return fpstate;
10157 void
10158 gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
10160 tree tmp;
10162 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
10163 1, fpstate);
10164 gfc_add_expr_to_block (block, tmp);
10168 /* Generate code for arguments of IEEE functions. */
10170 static void
10171 conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
10172 int nargs)
10174 gfc_actual_arglist *actual;
10175 gfc_expr *e;
10176 gfc_se argse;
10177 int arg;
10179 actual = expr->value.function.actual;
10180 for (arg = 0; arg < nargs; arg++, actual = actual->next)
10182 gcc_assert (actual);
10183 e = actual->expr;
10185 gfc_init_se (&argse, se);
10186 gfc_conv_expr_val (&argse, e);
10188 gfc_add_block_to_block (&se->pre, &argse.pre);
10189 gfc_add_block_to_block (&se->post, &argse.post);
10190 argarray[arg] = argse.expr;
10195 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE
10196 and IEEE_UNORDERED, which translate directly to GCC type-generic
10197 built-ins. */
10199 static void
10200 conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
10201 enum built_in_function code, int nargs)
10203 tree args[2];
10204 gcc_assert ((unsigned) nargs <= ARRAY_SIZE (args));
10206 conv_ieee_function_args (se, expr, args, nargs);
10207 se->expr = build_call_expr_loc_array (input_location,
10208 builtin_decl_explicit (code),
10209 nargs, args);
10210 STRIP_TYPE_NOPS (se->expr);
10211 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
10215 /* Generate code for intrinsics IEEE_SIGNBIT. */
10217 static void
10218 conv_intrinsic_ieee_signbit (gfc_se * se, gfc_expr * expr)
10220 tree arg, signbit;
10222 conv_ieee_function_args (se, expr, &arg, 1);
10223 signbit = build_call_expr_loc (input_location,
10224 builtin_decl_explicit (BUILT_IN_SIGNBIT),
10225 1, arg);
10226 signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10227 signbit, integer_zero_node);
10228 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), signbit);
10232 /* Generate code for IEEE_IS_NORMAL intrinsic:
10233 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
10235 static void
10236 conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
10238 tree arg, isnormal, iszero;
10240 /* Convert arg, evaluate it only once. */
10241 conv_ieee_function_args (se, expr, &arg, 1);
10242 arg = gfc_evaluate_now (arg, &se->pre);
10244 isnormal = build_call_expr_loc (input_location,
10245 builtin_decl_explicit (BUILT_IN_ISNORMAL),
10246 1, arg);
10247 iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
10248 build_real_from_int_cst (TREE_TYPE (arg),
10249 integer_zero_node));
10250 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
10251 logical_type_node, isnormal, iszero);
10252 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
10256 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
10257 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
10259 static void
10260 conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
10262 tree arg, signbit, isnan;
10264 /* Convert arg, evaluate it only once. */
10265 conv_ieee_function_args (se, expr, &arg, 1);
10266 arg = gfc_evaluate_now (arg, &se->pre);
10268 isnan = build_call_expr_loc (input_location,
10269 builtin_decl_explicit (BUILT_IN_ISNAN),
10270 1, arg);
10271 STRIP_TYPE_NOPS (isnan);
10273 signbit = build_call_expr_loc (input_location,
10274 builtin_decl_explicit (BUILT_IN_SIGNBIT),
10275 1, arg);
10276 signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10277 signbit, integer_zero_node);
10279 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10280 logical_type_node, signbit,
10281 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
10282 TREE_TYPE(isnan), isnan));
10284 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
10288 /* Generate code for IEEE_LOGB and IEEE_RINT. */
10290 static void
10291 conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
10292 enum built_in_function code)
10294 tree arg, decl, call, fpstate;
10295 int argprec;
10297 conv_ieee_function_args (se, expr, &arg, 1);
10298 argprec = TYPE_PRECISION (TREE_TYPE (arg));
10299 decl = builtin_decl_for_precision (code, argprec);
10301 /* Save floating-point state. */
10302 fpstate = gfc_save_fp_state (&se->pre);
10304 /* Make the function call. */
10305 call = build_call_expr_loc (input_location, decl, 1, arg);
10306 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
10308 /* Restore floating-point state. */
10309 gfc_restore_fp_state (&se->post, fpstate);
10313 /* Generate code for IEEE_REM. */
10315 static void
10316 conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
10318 tree args[2], decl, call, fpstate;
10319 int argprec;
10321 conv_ieee_function_args (se, expr, args, 2);
10323 /* If arguments have unequal size, convert them to the larger. */
10324 if (TYPE_PRECISION (TREE_TYPE (args[0]))
10325 > TYPE_PRECISION (TREE_TYPE (args[1])))
10326 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
10327 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
10328 > TYPE_PRECISION (TREE_TYPE (args[0])))
10329 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
10331 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
10332 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
10334 /* Save floating-point state. */
10335 fpstate = gfc_save_fp_state (&se->pre);
10337 /* Make the function call. */
10338 call = build_call_expr_loc_array (input_location, decl, 2, args);
10339 se->expr = fold_convert (TREE_TYPE (args[0]), call);
10341 /* Restore floating-point state. */
10342 gfc_restore_fp_state (&se->post, fpstate);
10346 /* Generate code for IEEE_NEXT_AFTER. */
10348 static void
10349 conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
10351 tree args[2], decl, call, fpstate;
10352 int argprec;
10354 conv_ieee_function_args (se, expr, args, 2);
10356 /* Result has the characteristics of first argument. */
10357 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
10358 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
10359 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
10361 /* Save floating-point state. */
10362 fpstate = gfc_save_fp_state (&se->pre);
10364 /* Make the function call. */
10365 call = build_call_expr_loc_array (input_location, decl, 2, args);
10366 se->expr = fold_convert (TREE_TYPE (args[0]), call);
10368 /* Restore floating-point state. */
10369 gfc_restore_fp_state (&se->post, fpstate);
10373 /* Generate code for IEEE_SCALB. */
10375 static void
10376 conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
10378 tree args[2], decl, call, huge, type;
10379 int argprec, n;
10381 conv_ieee_function_args (se, expr, args, 2);
10383 /* Result has the characteristics of first argument. */
10384 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
10385 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
10387 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
10389 /* We need to fold the integer into the range of a C int. */
10390 args[1] = gfc_evaluate_now (args[1], &se->pre);
10391 type = TREE_TYPE (args[1]);
10393 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
10394 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
10395 gfc_c_int_kind);
10396 huge = fold_convert (type, huge);
10397 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
10398 huge);
10399 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
10400 fold_build1_loc (input_location, NEGATE_EXPR,
10401 type, huge));
10404 args[1] = fold_convert (integer_type_node, args[1]);
10406 /* Make the function call. */
10407 call = build_call_expr_loc_array (input_location, decl, 2, args);
10408 se->expr = fold_convert (TREE_TYPE (args[0]), call);
10412 /* Generate code for IEEE_COPY_SIGN. */
10414 static void
10415 conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
10417 tree args[2], decl, sign;
10418 int argprec;
10420 conv_ieee_function_args (se, expr, args, 2);
10422 /* Get the sign of the second argument. */
10423 sign = build_call_expr_loc (input_location,
10424 builtin_decl_explicit (BUILT_IN_SIGNBIT),
10425 1, args[1]);
10426 sign = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10427 sign, integer_zero_node);
10429 /* Create a value of one, with the right sign. */
10430 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
10431 sign,
10432 fold_build1_loc (input_location, NEGATE_EXPR,
10433 integer_type_node,
10434 integer_one_node),
10435 integer_one_node);
10436 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
10438 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
10439 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
10441 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
10445 /* Generate code for IEEE_CLASS. */
10447 static void
10448 conv_intrinsic_ieee_class (gfc_se *se, gfc_expr *expr)
10450 tree arg, c, t1, t2, t3, t4;
10452 /* Convert arg, evaluate it only once. */
10453 conv_ieee_function_args (se, expr, &arg, 1);
10454 arg = gfc_evaluate_now (arg, &se->pre);
10456 c = build_call_expr_loc (input_location,
10457 builtin_decl_explicit (BUILT_IN_FPCLASSIFY), 6,
10458 build_int_cst (integer_type_node, IEEE_QUIET_NAN),
10459 build_int_cst (integer_type_node,
10460 IEEE_POSITIVE_INF),
10461 build_int_cst (integer_type_node,
10462 IEEE_POSITIVE_NORMAL),
10463 build_int_cst (integer_type_node,
10464 IEEE_POSITIVE_DENORMAL),
10465 build_int_cst (integer_type_node,
10466 IEEE_POSITIVE_ZERO),
10467 arg);
10468 c = gfc_evaluate_now (c, &se->pre);
10469 t1 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
10470 c, build_int_cst (integer_type_node,
10471 IEEE_QUIET_NAN));
10472 t2 = build_call_expr_loc (input_location,
10473 builtin_decl_explicit (BUILT_IN_ISSIGNALING), 1,
10474 arg);
10475 t2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10476 t2, build_zero_cst (TREE_TYPE (t2)));
10477 t1 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10478 logical_type_node, t1, t2);
10479 t3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
10480 c, build_int_cst (integer_type_node,
10481 IEEE_POSITIVE_ZERO));
10482 t4 = build_call_expr_loc (input_location,
10483 builtin_decl_explicit (BUILT_IN_SIGNBIT), 1,
10484 arg);
10485 t4 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10486 t4, build_zero_cst (TREE_TYPE (t4)));
10487 t3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10488 logical_type_node, t3, t4);
10489 int s = IEEE_NEGATIVE_ZERO + IEEE_POSITIVE_ZERO;
10490 gcc_assert (IEEE_NEGATIVE_INF == s - IEEE_POSITIVE_INF);
10491 gcc_assert (IEEE_NEGATIVE_NORMAL == s - IEEE_POSITIVE_NORMAL);
10492 gcc_assert (IEEE_NEGATIVE_DENORMAL == s - IEEE_POSITIVE_DENORMAL);
10493 gcc_assert (IEEE_NEGATIVE_SUBNORMAL == s - IEEE_POSITIVE_SUBNORMAL);
10494 gcc_assert (IEEE_NEGATIVE_ZERO == s - IEEE_POSITIVE_ZERO);
10495 t4 = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (c),
10496 build_int_cst (TREE_TYPE (c), s), c);
10497 t3 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c),
10498 t3, t4, c);
10499 t1 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c), t1,
10500 build_int_cst (TREE_TYPE (c), IEEE_SIGNALING_NAN),
10501 t3);
10502 tree type = gfc_typenode_for_spec (&expr->ts);
10503 /* Perform a quick sanity check that the return type is
10504 IEEE_CLASS_TYPE derived type defined in
10505 libgfortran/ieee/ieee_arithmetic.F90
10506 Primarily check that it is a derived type with a single
10507 member in it. */
10508 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
10509 tree field = NULL_TREE;
10510 for (tree f = TYPE_FIELDS (type); f != NULL_TREE; f = DECL_CHAIN (f))
10511 if (TREE_CODE (f) == FIELD_DECL)
10513 gcc_assert (field == NULL_TREE);
10514 field = f;
10516 gcc_assert (field);
10517 t1 = fold_convert (TREE_TYPE (field), t1);
10518 se->expr = build_constructor_single (type, field, t1);
10522 /* Generate code for IEEE_VALUE. */
10524 static void
10525 conv_intrinsic_ieee_value (gfc_se *se, gfc_expr *expr)
10527 tree args[2], arg, ret, tmp;
10528 stmtblock_t body;
10530 /* Convert args, evaluate the second one only once. */
10531 conv_ieee_function_args (se, expr, args, 2);
10532 arg = gfc_evaluate_now (args[1], &se->pre);
10534 tree type = TREE_TYPE (arg);
10535 /* Perform a quick sanity check that the second argument's type is
10536 IEEE_CLASS_TYPE derived type defined in
10537 libgfortran/ieee/ieee_arithmetic.F90
10538 Primarily check that it is a derived type with a single
10539 member in it. */
10540 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
10541 tree field = NULL_TREE;
10542 for (tree f = TYPE_FIELDS (type); f != NULL_TREE; f = DECL_CHAIN (f))
10543 if (TREE_CODE (f) == FIELD_DECL)
10545 gcc_assert (field == NULL_TREE);
10546 field = f;
10548 gcc_assert (field);
10549 arg = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
10550 arg, field, NULL_TREE);
10551 arg = gfc_evaluate_now (arg, &se->pre);
10553 type = gfc_typenode_for_spec (&expr->ts);
10554 gcc_assert (SCALAR_FLOAT_TYPE_P (type));
10555 ret = gfc_create_var (type, NULL);
10557 gfc_init_block (&body);
10559 tree end_label = gfc_build_label_decl (NULL_TREE);
10560 for (int c = IEEE_SIGNALING_NAN; c <= IEEE_POSITIVE_INF; ++c)
10562 tree label = gfc_build_label_decl (NULL_TREE);
10563 tree low = build_int_cst (TREE_TYPE (arg), c);
10564 tmp = build_case_label (low, low, label);
10565 gfc_add_expr_to_block (&body, tmp);
10567 REAL_VALUE_TYPE real;
10568 int k;
10569 switch (c)
10571 case IEEE_SIGNALING_NAN:
10572 real_nan (&real, "", 0, TYPE_MODE (type));
10573 break;
10574 case IEEE_QUIET_NAN:
10575 real_nan (&real, "", 1, TYPE_MODE (type));
10576 break;
10577 case IEEE_NEGATIVE_INF:
10578 real_inf (&real);
10579 real = real_value_negate (&real);
10580 break;
10581 case IEEE_NEGATIVE_NORMAL:
10582 real_from_integer (&real, TYPE_MODE (type), -42, SIGNED);
10583 break;
10584 case IEEE_NEGATIVE_DENORMAL:
10585 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
10586 real_from_mpfr (&real, gfc_real_kinds[k].tiny,
10587 type, GFC_RND_MODE);
10588 real_arithmetic (&real, RDIV_EXPR, &real, &dconst2);
10589 real = real_value_negate (&real);
10590 break;
10591 case IEEE_NEGATIVE_ZERO:
10592 real_from_integer (&real, TYPE_MODE (type), 0, SIGNED);
10593 real = real_value_negate (&real);
10594 break;
10595 case IEEE_POSITIVE_ZERO:
10596 /* Make this also the default: label. The other possibility
10597 would be to add a separate default: label followed by
10598 __builtin_unreachable (). */
10599 label = gfc_build_label_decl (NULL_TREE);
10600 tmp = build_case_label (NULL_TREE, NULL_TREE, label);
10601 gfc_add_expr_to_block (&body, tmp);
10602 real_from_integer (&real, TYPE_MODE (type), 0, SIGNED);
10603 break;
10604 case IEEE_POSITIVE_DENORMAL:
10605 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
10606 real_from_mpfr (&real, gfc_real_kinds[k].tiny,
10607 type, GFC_RND_MODE);
10608 real_arithmetic (&real, RDIV_EXPR, &real, &dconst2);
10609 break;
10610 case IEEE_POSITIVE_NORMAL:
10611 real_from_integer (&real, TYPE_MODE (type), 42, SIGNED);
10612 break;
10613 case IEEE_POSITIVE_INF:
10614 real_inf (&real);
10615 break;
10616 default:
10617 gcc_unreachable ();
10620 tree val = build_real (type, real);
10621 gfc_add_modify (&body, ret, val);
10623 tmp = build1_v (GOTO_EXPR, end_label);
10624 gfc_add_expr_to_block (&body, tmp);
10627 tmp = gfc_finish_block (&body);
10628 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, arg, tmp);
10629 gfc_add_expr_to_block (&se->pre, tmp);
10631 tmp = build1_v (LABEL_EXPR, end_label);
10632 gfc_add_expr_to_block (&se->pre, tmp);
10634 se->expr = ret;
10638 /* Generate code for IEEE_FMA. */
10640 static void
10641 conv_intrinsic_ieee_fma (gfc_se * se, gfc_expr * expr)
10643 tree args[3], decl, call;
10644 int argprec;
10646 conv_ieee_function_args (se, expr, args, 3);
10648 /* All three arguments should have the same type. */
10649 gcc_assert (TYPE_PRECISION (TREE_TYPE (args[0])) == TYPE_PRECISION (TREE_TYPE (args[1])));
10650 gcc_assert (TYPE_PRECISION (TREE_TYPE (args[0])) == TYPE_PRECISION (TREE_TYPE (args[2])));
10652 /* Call the type-generic FMA built-in. */
10653 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
10654 decl = builtin_decl_for_precision (BUILT_IN_FMA, argprec);
10655 call = build_call_expr_loc_array (input_location, decl, 3, args);
10657 /* Convert to the final type. */
10658 se->expr = fold_convert (TREE_TYPE (args[0]), call);
10662 /* Generate code for IEEE_{MIN,MAX}_NUM{,_MAG}. */
10664 static void
10665 conv_intrinsic_ieee_minmax (gfc_se * se, gfc_expr * expr, int max,
10666 const char *name)
10668 tree args[2], func;
10669 built_in_function fn;
10671 conv_ieee_function_args (se, expr, args, 2);
10672 gcc_assert (TYPE_PRECISION (TREE_TYPE (args[0])) == TYPE_PRECISION (TREE_TYPE (args[1])));
10673 args[0] = gfc_evaluate_now (args[0], &se->pre);
10674 args[1] = gfc_evaluate_now (args[1], &se->pre);
10676 if (startswith (name, "mag"))
10678 /* IEEE_MIN_NUM_MAG and IEEE_MAX_NUM_MAG translate to C functions
10679 fminmag() and fmaxmag(), which do not exist as built-ins.
10681 Following glibc, we emit this:
10683 fminmag (x, y) {
10684 ax = ABS (x);
10685 ay = ABS (y);
10686 if (isless (ax, ay))
10687 return x;
10688 else if (isgreater (ax, ay))
10689 return y;
10690 else if (ax == ay)
10691 return x < y ? x : y;
10692 else if (issignaling (x) || issignaling (y))
10693 return x + y;
10694 else
10695 return isnan (y) ? x : y;
10698 fmaxmag (x, y) {
10699 ax = ABS (x);
10700 ay = ABS (y);
10701 if (isgreater (ax, ay))
10702 return x;
10703 else if (isless (ax, ay))
10704 return y;
10705 else if (ax == ay)
10706 return x > y ? x : y;
10707 else if (issignaling (x) || issignaling (y))
10708 return x + y;
10709 else
10710 return isnan (y) ? x : y;
10715 tree abs0, abs1, sig0, sig1;
10716 tree cond1, cond2, cond3, cond4, cond5;
10717 tree res;
10718 tree type = TREE_TYPE (args[0]);
10720 func = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
10721 abs0 = build_call_expr_loc (input_location, func, 1, args[0]);
10722 abs1 = build_call_expr_loc (input_location, func, 1, args[1]);
10723 abs0 = gfc_evaluate_now (abs0, &se->pre);
10724 abs1 = gfc_evaluate_now (abs1, &se->pre);
10726 cond5 = build_call_expr_loc (input_location,
10727 builtin_decl_explicit (BUILT_IN_ISNAN),
10728 1, args[1]);
10729 res = fold_build3_loc (input_location, COND_EXPR, type, cond5,
10730 args[0], args[1]);
10732 sig0 = build_call_expr_loc (input_location,
10733 builtin_decl_explicit (BUILT_IN_ISSIGNALING),
10734 1, args[0]);
10735 sig1 = build_call_expr_loc (input_location,
10736 builtin_decl_explicit (BUILT_IN_ISSIGNALING),
10737 1, args[1]);
10738 cond4 = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
10739 logical_type_node, sig0, sig1);
10740 res = fold_build3_loc (input_location, COND_EXPR, type, cond4,
10741 fold_build2_loc (input_location, PLUS_EXPR,
10742 type, args[0], args[1]),
10743 res);
10745 cond3 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
10746 abs0, abs1);
10747 res = fold_build3_loc (input_location, COND_EXPR, type, cond3,
10748 fold_build2_loc (input_location,
10749 max ? MAX_EXPR : MIN_EXPR,
10750 type, args[0], args[1]),
10751 res);
10753 func = builtin_decl_explicit (max ? BUILT_IN_ISLESS : BUILT_IN_ISGREATER);
10754 cond2 = build_call_expr_loc (input_location, func, 2, abs0, abs1);
10755 res = fold_build3_loc (input_location, COND_EXPR, type, cond2,
10756 args[1], res);
10758 func = builtin_decl_explicit (max ? BUILT_IN_ISGREATER : BUILT_IN_ISLESS);
10759 cond1 = build_call_expr_loc (input_location, func, 2, abs0, abs1);
10760 res = fold_build3_loc (input_location, COND_EXPR, type, cond1,
10761 args[0], res);
10763 se->expr = res;
10765 else
10767 /* IEEE_MIN_NUM and IEEE_MAX_NUM translate to fmin() and fmax(). */
10768 fn = max ? BUILT_IN_FMAX : BUILT_IN_FMIN;
10769 func = gfc_builtin_decl_for_float_kind (fn, expr->ts.kind);
10770 se->expr = build_call_expr_loc_array (input_location, func, 2, args);
10775 /* Generate code for comparison functions IEEE_QUIET_* and
10776 IEEE_SIGNALING_*. */
10778 static void
10779 conv_intrinsic_ieee_comparison (gfc_se * se, gfc_expr * expr, int signaling,
10780 const char *name)
10782 tree args[2];
10783 tree arg1, arg2, res;
10785 /* Evaluate arguments only once. */
10786 conv_ieee_function_args (se, expr, args, 2);
10787 arg1 = gfc_evaluate_now (args[0], &se->pre);
10788 arg2 = gfc_evaluate_now (args[1], &se->pre);
10790 if (startswith (name, "eq"))
10792 if (signaling)
10793 res = build_call_expr_loc (input_location,
10794 builtin_decl_explicit (BUILT_IN_ISEQSIG),
10795 2, arg1, arg2);
10796 else
10797 res = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
10798 arg1, arg2);
10800 else if (startswith (name, "ne"))
10802 if (signaling)
10804 res = build_call_expr_loc (input_location,
10805 builtin_decl_explicit (BUILT_IN_ISEQSIG),
10806 2, arg1, arg2);
10807 res = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
10808 logical_type_node, res);
10810 else
10811 res = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10812 arg1, arg2);
10814 else if (startswith (name, "ge"))
10816 if (signaling)
10817 res = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
10818 arg1, arg2);
10819 else
10820 res = build_call_expr_loc (input_location,
10821 builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL),
10822 2, arg1, arg2);
10824 else if (startswith (name, "gt"))
10826 if (signaling)
10827 res = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
10828 arg1, arg2);
10829 else
10830 res = build_call_expr_loc (input_location,
10831 builtin_decl_explicit (BUILT_IN_ISGREATER),
10832 2, arg1, arg2);
10834 else if (startswith (name, "le"))
10836 if (signaling)
10837 res = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
10838 arg1, arg2);
10839 else
10840 res = build_call_expr_loc (input_location,
10841 builtin_decl_explicit (BUILT_IN_ISLESSEQUAL),
10842 2, arg1, arg2);
10844 else if (startswith (name, "lt"))
10846 if (signaling)
10847 res = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
10848 arg1, arg2);
10849 else
10850 res = build_call_expr_loc (input_location,
10851 builtin_decl_explicit (BUILT_IN_ISLESS),
10852 2, arg1, arg2);
10854 else
10855 gcc_unreachable ();
10857 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), res);
10861 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
10862 module. */
10864 bool
10865 gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
10867 const char *name = expr->value.function.name;
10869 if (startswith (name, "_gfortran_ieee_is_nan"))
10870 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
10871 else if (startswith (name, "_gfortran_ieee_is_finite"))
10872 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
10873 else if (startswith (name, "_gfortran_ieee_unordered"))
10874 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
10875 else if (startswith (name, "_gfortran_ieee_signbit"))
10876 conv_intrinsic_ieee_signbit (se, expr);
10877 else if (startswith (name, "_gfortran_ieee_is_normal"))
10878 conv_intrinsic_ieee_is_normal (se, expr);
10879 else if (startswith (name, "_gfortran_ieee_is_negative"))
10880 conv_intrinsic_ieee_is_negative (se, expr);
10881 else if (startswith (name, "_gfortran_ieee_copy_sign"))
10882 conv_intrinsic_ieee_copy_sign (se, expr);
10883 else if (startswith (name, "_gfortran_ieee_scalb"))
10884 conv_intrinsic_ieee_scalb (se, expr);
10885 else if (startswith (name, "_gfortran_ieee_next_after"))
10886 conv_intrinsic_ieee_next_after (se, expr);
10887 else if (startswith (name, "_gfortran_ieee_rem"))
10888 conv_intrinsic_ieee_rem (se, expr);
10889 else if (startswith (name, "_gfortran_ieee_logb"))
10890 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
10891 else if (startswith (name, "_gfortran_ieee_rint"))
10892 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
10893 else if (startswith (name, "ieee_class_") && ISDIGIT (name[11]))
10894 conv_intrinsic_ieee_class (se, expr);
10895 else if (startswith (name, "ieee_value_") && ISDIGIT (name[11]))
10896 conv_intrinsic_ieee_value (se, expr);
10897 else if (startswith (name, "_gfortran_ieee_fma"))
10898 conv_intrinsic_ieee_fma (se, expr);
10899 else if (startswith (name, "_gfortran_ieee_min_num_"))
10900 conv_intrinsic_ieee_minmax (se, expr, 0, name + 23);
10901 else if (startswith (name, "_gfortran_ieee_max_num_"))
10902 conv_intrinsic_ieee_minmax (se, expr, 1, name + 23);
10903 else if (startswith (name, "_gfortran_ieee_quiet_"))
10904 conv_intrinsic_ieee_comparison (se, expr, 0, name + 21);
10905 else if (startswith (name, "_gfortran_ieee_signaling_"))
10906 conv_intrinsic_ieee_comparison (se, expr, 1, name + 25);
10907 else
10908 /* It is not among the functions we translate directly. We return
10909 false, so a library function call is emitted. */
10910 return false;
10912 return true;
10916 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
10918 static void
10919 gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
10921 tree arg, res, restype;
10923 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
10924 arg = fold_convert (size_type_node, arg);
10925 res = build_call_expr_loc (input_location,
10926 builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
10927 restype = gfc_typenode_for_spec (&expr->ts);
10928 se->expr = fold_convert (restype, res);
10932 /* Generate code for an intrinsic function. Some map directly to library
10933 calls, others get special handling. In some cases the name of the function
10934 used depends on the type specifiers. */
10936 void
10937 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
10939 const char *name;
10940 int lib, kind;
10941 tree fndecl;
10943 name = &expr->value.function.name[2];
10945 if (expr->rank > 0)
10947 lib = gfc_is_intrinsic_libcall (expr);
10948 if (lib != 0)
10950 if (lib == 1)
10951 se->ignore_optional = 1;
10953 switch (expr->value.function.isym->id)
10955 case GFC_ISYM_EOSHIFT:
10956 case GFC_ISYM_PACK:
10957 case GFC_ISYM_RESHAPE:
10958 /* For all of those the first argument specifies the type and the
10959 third is optional. */
10960 conv_generic_with_optional_char_arg (se, expr, 1, 3);
10961 break;
10963 case GFC_ISYM_FINDLOC:
10964 gfc_conv_intrinsic_findloc (se, expr);
10965 break;
10967 case GFC_ISYM_MINLOC:
10968 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
10969 break;
10971 case GFC_ISYM_MAXLOC:
10972 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
10973 break;
10975 default:
10976 gfc_conv_intrinsic_funcall (se, expr);
10977 break;
10980 return;
10984 switch (expr->value.function.isym->id)
10986 case GFC_ISYM_NONE:
10987 gcc_unreachable ();
10989 case GFC_ISYM_REPEAT:
10990 gfc_conv_intrinsic_repeat (se, expr);
10991 break;
10993 case GFC_ISYM_TRIM:
10994 gfc_conv_intrinsic_trim (se, expr);
10995 break;
10997 case GFC_ISYM_SC_KIND:
10998 gfc_conv_intrinsic_sc_kind (se, expr);
10999 break;
11001 case GFC_ISYM_SI_KIND:
11002 gfc_conv_intrinsic_si_kind (se, expr);
11003 break;
11005 case GFC_ISYM_SL_KIND:
11006 gfc_conv_intrinsic_sl_kind (se, expr);
11007 break;
11009 case GFC_ISYM_SR_KIND:
11010 gfc_conv_intrinsic_sr_kind (se, expr);
11011 break;
11013 case GFC_ISYM_EXPONENT:
11014 gfc_conv_intrinsic_exponent (se, expr);
11015 break;
11017 case GFC_ISYM_SCAN:
11018 kind = expr->value.function.actual->expr->ts.kind;
11019 if (kind == 1)
11020 fndecl = gfor_fndecl_string_scan;
11021 else if (kind == 4)
11022 fndecl = gfor_fndecl_string_scan_char4;
11023 else
11024 gcc_unreachable ();
11026 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
11027 break;
11029 case GFC_ISYM_VERIFY:
11030 kind = expr->value.function.actual->expr->ts.kind;
11031 if (kind == 1)
11032 fndecl = gfor_fndecl_string_verify;
11033 else if (kind == 4)
11034 fndecl = gfor_fndecl_string_verify_char4;
11035 else
11036 gcc_unreachable ();
11038 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
11039 break;
11041 case GFC_ISYM_ALLOCATED:
11042 gfc_conv_allocated (se, expr);
11043 break;
11045 case GFC_ISYM_ASSOCIATED:
11046 gfc_conv_associated(se, expr);
11047 break;
11049 case GFC_ISYM_SAME_TYPE_AS:
11050 gfc_conv_same_type_as (se, expr);
11051 break;
11053 case GFC_ISYM_ABS:
11054 gfc_conv_intrinsic_abs (se, expr);
11055 break;
11057 case GFC_ISYM_ADJUSTL:
11058 if (expr->ts.kind == 1)
11059 fndecl = gfor_fndecl_adjustl;
11060 else if (expr->ts.kind == 4)
11061 fndecl = gfor_fndecl_adjustl_char4;
11062 else
11063 gcc_unreachable ();
11065 gfc_conv_intrinsic_adjust (se, expr, fndecl);
11066 break;
11068 case GFC_ISYM_ADJUSTR:
11069 if (expr->ts.kind == 1)
11070 fndecl = gfor_fndecl_adjustr;
11071 else if (expr->ts.kind == 4)
11072 fndecl = gfor_fndecl_adjustr_char4;
11073 else
11074 gcc_unreachable ();
11076 gfc_conv_intrinsic_adjust (se, expr, fndecl);
11077 break;
11079 case GFC_ISYM_AIMAG:
11080 gfc_conv_intrinsic_imagpart (se, expr);
11081 break;
11083 case GFC_ISYM_AINT:
11084 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
11085 break;
11087 case GFC_ISYM_ALL:
11088 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
11089 break;
11091 case GFC_ISYM_ANINT:
11092 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
11093 break;
11095 case GFC_ISYM_AND:
11096 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
11097 break;
11099 case GFC_ISYM_ANY:
11100 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
11101 break;
11103 case GFC_ISYM_ACOSD:
11104 case GFC_ISYM_ASIND:
11105 case GFC_ISYM_ATAND:
11106 gfc_conv_intrinsic_atrigd (se, expr, expr->value.function.isym->id);
11107 break;
11109 case GFC_ISYM_COTAN:
11110 gfc_conv_intrinsic_cotan (se, expr);
11111 break;
11113 case GFC_ISYM_COTAND:
11114 gfc_conv_intrinsic_cotand (se, expr);
11115 break;
11117 case GFC_ISYM_ATAN2D:
11118 gfc_conv_intrinsic_atan2d (se, expr);
11119 break;
11121 case GFC_ISYM_BTEST:
11122 gfc_conv_intrinsic_btest (se, expr);
11123 break;
11125 case GFC_ISYM_BGE:
11126 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
11127 break;
11129 case GFC_ISYM_BGT:
11130 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
11131 break;
11133 case GFC_ISYM_BLE:
11134 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
11135 break;
11137 case GFC_ISYM_BLT:
11138 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
11139 break;
11141 case GFC_ISYM_C_ASSOCIATED:
11142 case GFC_ISYM_C_FUNLOC:
11143 case GFC_ISYM_C_LOC:
11144 conv_isocbinding_function (se, expr);
11145 break;
11147 case GFC_ISYM_ACHAR:
11148 case GFC_ISYM_CHAR:
11149 gfc_conv_intrinsic_char (se, expr);
11150 break;
11152 case GFC_ISYM_CONVERSION:
11153 case GFC_ISYM_DBLE:
11154 case GFC_ISYM_DFLOAT:
11155 case GFC_ISYM_FLOAT:
11156 case GFC_ISYM_LOGICAL:
11157 case GFC_ISYM_REAL:
11158 case GFC_ISYM_REALPART:
11159 case GFC_ISYM_SNGL:
11160 gfc_conv_intrinsic_conversion (se, expr);
11161 break;
11163 /* Integer conversions are handled separately to make sure we get the
11164 correct rounding mode. */
11165 case GFC_ISYM_INT:
11166 case GFC_ISYM_INT2:
11167 case GFC_ISYM_INT8:
11168 case GFC_ISYM_LONG:
11169 case GFC_ISYM_UINT:
11170 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
11171 break;
11173 case GFC_ISYM_NINT:
11174 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
11175 break;
11177 case GFC_ISYM_CEILING:
11178 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
11179 break;
11181 case GFC_ISYM_FLOOR:
11182 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
11183 break;
11185 case GFC_ISYM_MOD:
11186 gfc_conv_intrinsic_mod (se, expr, 0);
11187 break;
11189 case GFC_ISYM_MODULO:
11190 gfc_conv_intrinsic_mod (se, expr, 1);
11191 break;
11193 case GFC_ISYM_CAF_GET:
11194 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
11195 false, NULL);
11196 break;
11198 case GFC_ISYM_CMPLX:
11199 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
11200 break;
11202 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
11203 gfc_conv_intrinsic_iargc (se, expr);
11204 break;
11206 case GFC_ISYM_COMPLEX:
11207 gfc_conv_intrinsic_cmplx (se, expr, 1);
11208 break;
11210 case GFC_ISYM_CONJG:
11211 gfc_conv_intrinsic_conjg (se, expr);
11212 break;
11214 case GFC_ISYM_COUNT:
11215 gfc_conv_intrinsic_count (se, expr);
11216 break;
11218 case GFC_ISYM_CTIME:
11219 gfc_conv_intrinsic_ctime (se, expr);
11220 break;
11222 case GFC_ISYM_DIM:
11223 gfc_conv_intrinsic_dim (se, expr);
11224 break;
11226 case GFC_ISYM_DOT_PRODUCT:
11227 gfc_conv_intrinsic_dot_product (se, expr);
11228 break;
11230 case GFC_ISYM_DPROD:
11231 gfc_conv_intrinsic_dprod (se, expr);
11232 break;
11234 case GFC_ISYM_DSHIFTL:
11235 gfc_conv_intrinsic_dshift (se, expr, true);
11236 break;
11238 case GFC_ISYM_DSHIFTR:
11239 gfc_conv_intrinsic_dshift (se, expr, false);
11240 break;
11242 case GFC_ISYM_FDATE:
11243 gfc_conv_intrinsic_fdate (se, expr);
11244 break;
11246 case GFC_ISYM_FRACTION:
11247 gfc_conv_intrinsic_fraction (se, expr);
11248 break;
11250 case GFC_ISYM_IALL:
11251 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
11252 break;
11254 case GFC_ISYM_IAND:
11255 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
11256 break;
11258 case GFC_ISYM_IANY:
11259 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
11260 break;
11262 case GFC_ISYM_IBCLR:
11263 gfc_conv_intrinsic_singlebitop (se, expr, 0);
11264 break;
11266 case GFC_ISYM_IBITS:
11267 gfc_conv_intrinsic_ibits (se, expr);
11268 break;
11270 case GFC_ISYM_IBSET:
11271 gfc_conv_intrinsic_singlebitop (se, expr, 1);
11272 break;
11274 case GFC_ISYM_IACHAR:
11275 case GFC_ISYM_ICHAR:
11276 /* We assume ASCII character sequence. */
11277 gfc_conv_intrinsic_ichar (se, expr);
11278 break;
11280 case GFC_ISYM_IARGC:
11281 gfc_conv_intrinsic_iargc (se, expr);
11282 break;
11284 case GFC_ISYM_IEOR:
11285 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
11286 break;
11288 case GFC_ISYM_INDEX:
11289 kind = expr->value.function.actual->expr->ts.kind;
11290 if (kind == 1)
11291 fndecl = gfor_fndecl_string_index;
11292 else if (kind == 4)
11293 fndecl = gfor_fndecl_string_index_char4;
11294 else
11295 gcc_unreachable ();
11297 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
11298 break;
11300 case GFC_ISYM_IOR:
11301 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
11302 break;
11304 case GFC_ISYM_IPARITY:
11305 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
11306 break;
11308 case GFC_ISYM_IS_IOSTAT_END:
11309 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
11310 break;
11312 case GFC_ISYM_IS_IOSTAT_EOR:
11313 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
11314 break;
11316 case GFC_ISYM_IS_CONTIGUOUS:
11317 gfc_conv_intrinsic_is_contiguous (se, expr);
11318 break;
11320 case GFC_ISYM_ISNAN:
11321 gfc_conv_intrinsic_isnan (se, expr);
11322 break;
11324 case GFC_ISYM_KILL:
11325 conv_intrinsic_kill (se, expr);
11326 break;
11328 case GFC_ISYM_LSHIFT:
11329 gfc_conv_intrinsic_shift (se, expr, false, false);
11330 break;
11332 case GFC_ISYM_RSHIFT:
11333 gfc_conv_intrinsic_shift (se, expr, true, true);
11334 break;
11336 case GFC_ISYM_SHIFTA:
11337 gfc_conv_intrinsic_shift (se, expr, true, true);
11338 break;
11340 case GFC_ISYM_SHIFTL:
11341 gfc_conv_intrinsic_shift (se, expr, false, false);
11342 break;
11344 case GFC_ISYM_SHIFTR:
11345 gfc_conv_intrinsic_shift (se, expr, true, false);
11346 break;
11348 case GFC_ISYM_ISHFT:
11349 gfc_conv_intrinsic_ishft (se, expr);
11350 break;
11352 case GFC_ISYM_ISHFTC:
11353 gfc_conv_intrinsic_ishftc (se, expr);
11354 break;
11356 case GFC_ISYM_LEADZ:
11357 gfc_conv_intrinsic_leadz (se, expr);
11358 break;
11360 case GFC_ISYM_TRAILZ:
11361 gfc_conv_intrinsic_trailz (se, expr);
11362 break;
11364 case GFC_ISYM_POPCNT:
11365 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
11366 break;
11368 case GFC_ISYM_POPPAR:
11369 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
11370 break;
11372 case GFC_ISYM_LBOUND:
11373 gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_LBOUND);
11374 break;
11376 case GFC_ISYM_LCOBOUND:
11377 conv_intrinsic_cobound (se, expr);
11378 break;
11380 case GFC_ISYM_TRANSPOSE:
11381 /* The scalarizer has already been set up for reversed dimension access
11382 order ; now we just get the argument value normally. */
11383 gfc_conv_expr (se, expr->value.function.actual->expr);
11384 break;
11386 case GFC_ISYM_LEN:
11387 gfc_conv_intrinsic_len (se, expr);
11388 break;
11390 case GFC_ISYM_LEN_TRIM:
11391 gfc_conv_intrinsic_len_trim (se, expr);
11392 break;
11394 case GFC_ISYM_LGE:
11395 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
11396 break;
11398 case GFC_ISYM_LGT:
11399 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
11400 break;
11402 case GFC_ISYM_LLE:
11403 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
11404 break;
11406 case GFC_ISYM_LLT:
11407 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
11408 break;
11410 case GFC_ISYM_MALLOC:
11411 gfc_conv_intrinsic_malloc (se, expr);
11412 break;
11414 case GFC_ISYM_MASKL:
11415 gfc_conv_intrinsic_mask (se, expr, 1);
11416 break;
11418 case GFC_ISYM_MASKR:
11419 gfc_conv_intrinsic_mask (se, expr, 0);
11420 break;
11422 case GFC_ISYM_MAX:
11423 if (expr->ts.type == BT_CHARACTER)
11424 gfc_conv_intrinsic_minmax_char (se, expr, 1);
11425 else
11426 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
11427 break;
11429 case GFC_ISYM_MAXLOC:
11430 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
11431 break;
11433 case GFC_ISYM_FINDLOC:
11434 gfc_conv_intrinsic_findloc (se, expr);
11435 break;
11437 case GFC_ISYM_MAXVAL:
11438 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
11439 break;
11441 case GFC_ISYM_MERGE:
11442 gfc_conv_intrinsic_merge (se, expr);
11443 break;
11445 case GFC_ISYM_MERGE_BITS:
11446 gfc_conv_intrinsic_merge_bits (se, expr);
11447 break;
11449 case GFC_ISYM_MIN:
11450 if (expr->ts.type == BT_CHARACTER)
11451 gfc_conv_intrinsic_minmax_char (se, expr, -1);
11452 else
11453 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
11454 break;
11456 case GFC_ISYM_MINLOC:
11457 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
11458 break;
11460 case GFC_ISYM_MINVAL:
11461 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
11462 break;
11464 case GFC_ISYM_NEAREST:
11465 gfc_conv_intrinsic_nearest (se, expr);
11466 break;
11468 case GFC_ISYM_NORM2:
11469 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
11470 break;
11472 case GFC_ISYM_NOT:
11473 gfc_conv_intrinsic_not (se, expr);
11474 break;
11476 case GFC_ISYM_OR:
11477 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
11478 break;
11480 case GFC_ISYM_PARITY:
11481 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
11482 break;
11484 case GFC_ISYM_PRESENT:
11485 gfc_conv_intrinsic_present (se, expr);
11486 break;
11488 case GFC_ISYM_PRODUCT:
11489 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
11490 break;
11492 case GFC_ISYM_RANK:
11493 gfc_conv_intrinsic_rank (se, expr);
11494 break;
11496 case GFC_ISYM_RRSPACING:
11497 gfc_conv_intrinsic_rrspacing (se, expr);
11498 break;
11500 case GFC_ISYM_SET_EXPONENT:
11501 gfc_conv_intrinsic_set_exponent (se, expr);
11502 break;
11504 case GFC_ISYM_SCALE:
11505 gfc_conv_intrinsic_scale (se, expr);
11506 break;
11508 case GFC_ISYM_SHAPE:
11509 gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_SHAPE);
11510 break;
11512 case GFC_ISYM_SIGN:
11513 gfc_conv_intrinsic_sign (se, expr);
11514 break;
11516 case GFC_ISYM_SIZE:
11517 gfc_conv_intrinsic_size (se, expr);
11518 break;
11520 case GFC_ISYM_SIZEOF:
11521 case GFC_ISYM_C_SIZEOF:
11522 gfc_conv_intrinsic_sizeof (se, expr);
11523 break;
11525 case GFC_ISYM_STORAGE_SIZE:
11526 gfc_conv_intrinsic_storage_size (se, expr);
11527 break;
11529 case GFC_ISYM_SPACING:
11530 gfc_conv_intrinsic_spacing (se, expr);
11531 break;
11533 case GFC_ISYM_STRIDE:
11534 conv_intrinsic_stride (se, expr);
11535 break;
11537 case GFC_ISYM_SUM:
11538 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
11539 break;
11541 case GFC_ISYM_TEAM_NUMBER:
11542 conv_intrinsic_team_number (se, expr);
11543 break;
11545 case GFC_ISYM_TRANSFER:
11546 if (se->ss && se->ss->info->useflags)
11547 /* Access the previously obtained result. */
11548 gfc_conv_tmp_array_ref (se);
11549 else
11550 gfc_conv_intrinsic_transfer (se, expr);
11551 break;
11553 case GFC_ISYM_TTYNAM:
11554 gfc_conv_intrinsic_ttynam (se, expr);
11555 break;
11557 case GFC_ISYM_UBOUND:
11558 gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_UBOUND);
11559 break;
11561 case GFC_ISYM_UCOBOUND:
11562 conv_intrinsic_cobound (se, expr);
11563 break;
11565 case GFC_ISYM_XOR:
11566 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
11567 break;
11569 case GFC_ISYM_LOC:
11570 gfc_conv_intrinsic_loc (se, expr);
11571 break;
11573 case GFC_ISYM_THIS_IMAGE:
11574 /* For num_images() == 1, handle as LCOBOUND. */
11575 if (expr->value.function.actual->expr
11576 && flag_coarray == GFC_FCOARRAY_SINGLE)
11577 conv_intrinsic_cobound (se, expr);
11578 else
11579 trans_this_image (se, expr);
11580 break;
11582 case GFC_ISYM_IMAGE_INDEX:
11583 trans_image_index (se, expr);
11584 break;
11586 case GFC_ISYM_IMAGE_STATUS:
11587 conv_intrinsic_image_status (se, expr);
11588 break;
11590 case GFC_ISYM_NUM_IMAGES:
11591 trans_num_images (se, expr);
11592 break;
11594 case GFC_ISYM_ACCESS:
11595 case GFC_ISYM_CHDIR:
11596 case GFC_ISYM_CHMOD:
11597 case GFC_ISYM_DTIME:
11598 case GFC_ISYM_ETIME:
11599 case GFC_ISYM_EXTENDS_TYPE_OF:
11600 case GFC_ISYM_FGET:
11601 case GFC_ISYM_FGETC:
11602 case GFC_ISYM_FNUM:
11603 case GFC_ISYM_FPUT:
11604 case GFC_ISYM_FPUTC:
11605 case GFC_ISYM_FSTAT:
11606 case GFC_ISYM_FTELL:
11607 case GFC_ISYM_GETCWD:
11608 case GFC_ISYM_GETGID:
11609 case GFC_ISYM_GETPID:
11610 case GFC_ISYM_GETUID:
11611 case GFC_ISYM_HOSTNM:
11612 case GFC_ISYM_IERRNO:
11613 case GFC_ISYM_IRAND:
11614 case GFC_ISYM_ISATTY:
11615 case GFC_ISYM_JN2:
11616 case GFC_ISYM_LINK:
11617 case GFC_ISYM_LSTAT:
11618 case GFC_ISYM_MATMUL:
11619 case GFC_ISYM_MCLOCK:
11620 case GFC_ISYM_MCLOCK8:
11621 case GFC_ISYM_RAND:
11622 case GFC_ISYM_RENAME:
11623 case GFC_ISYM_SECOND:
11624 case GFC_ISYM_SECNDS:
11625 case GFC_ISYM_SIGNAL:
11626 case GFC_ISYM_STAT:
11627 case GFC_ISYM_SYMLNK:
11628 case GFC_ISYM_SYSTEM:
11629 case GFC_ISYM_TIME:
11630 case GFC_ISYM_TIME8:
11631 case GFC_ISYM_UMASK:
11632 case GFC_ISYM_UNLINK:
11633 case GFC_ISYM_YN2:
11634 gfc_conv_intrinsic_funcall (se, expr);
11635 break;
11637 case GFC_ISYM_EOSHIFT:
11638 case GFC_ISYM_PACK:
11639 case GFC_ISYM_RESHAPE:
11640 /* For those, expr->rank should always be >0 and thus the if above the
11641 switch should have matched. */
11642 gcc_unreachable ();
11643 break;
11645 default:
11646 gfc_conv_intrinsic_lib_function (se, expr);
11647 break;
11652 static gfc_ss *
11653 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
11655 gfc_ss *arg_ss, *tmp_ss;
11656 gfc_actual_arglist *arg;
11658 arg = expr->value.function.actual;
11660 gcc_assert (arg->expr);
11662 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
11663 gcc_assert (arg_ss != gfc_ss_terminator);
11665 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
11667 if (tmp_ss->info->type != GFC_SS_SCALAR
11668 && tmp_ss->info->type != GFC_SS_REFERENCE)
11670 gcc_assert (tmp_ss->dimen == 2);
11672 /* We just invert dimensions. */
11673 std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
11676 /* Stop when tmp_ss points to the last valid element of the chain... */
11677 if (tmp_ss->next == gfc_ss_terminator)
11678 break;
11681 /* ... so that we can attach the rest of the chain to it. */
11682 tmp_ss->next = ss;
11684 return arg_ss;
11688 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
11689 This has the side effect of reversing the nested list, so there is no
11690 need to call gfc_reverse_ss on it (the given list is assumed not to be
11691 reversed yet). */
11693 static gfc_ss *
11694 nest_loop_dimension (gfc_ss *ss, int dim)
11696 int ss_dim, i;
11697 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
11698 gfc_loopinfo *new_loop;
11700 gcc_assert (ss != gfc_ss_terminator);
11702 for (; ss != gfc_ss_terminator; ss = ss->next)
11704 new_ss = gfc_get_ss ();
11705 new_ss->next = prev_ss;
11706 new_ss->parent = ss;
11707 new_ss->info = ss->info;
11708 new_ss->info->refcount++;
11709 if (ss->dimen != 0)
11711 gcc_assert (ss->info->type != GFC_SS_SCALAR
11712 && ss->info->type != GFC_SS_REFERENCE);
11714 new_ss->dimen = 1;
11715 new_ss->dim[0] = ss->dim[dim];
11717 gcc_assert (dim < ss->dimen);
11719 ss_dim = --ss->dimen;
11720 for (i = dim; i < ss_dim; i++)
11721 ss->dim[i] = ss->dim[i + 1];
11723 ss->dim[ss_dim] = 0;
11725 prev_ss = new_ss;
11727 if (ss->nested_ss)
11729 ss->nested_ss->parent = new_ss;
11730 new_ss->nested_ss = ss->nested_ss;
11732 ss->nested_ss = new_ss;
11735 new_loop = gfc_get_loopinfo ();
11736 gfc_init_loopinfo (new_loop);
11738 gcc_assert (prev_ss != NULL);
11739 gcc_assert (prev_ss != gfc_ss_terminator);
11740 gfc_add_ss_to_loop (new_loop, prev_ss);
11741 return new_ss->parent;
11745 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
11746 is to be inlined. */
11748 static gfc_ss *
11749 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
11751 gfc_ss *tmp_ss, *tail, *array_ss;
11752 gfc_actual_arglist *arg1, *arg2, *arg3;
11753 int sum_dim;
11754 bool scalar_mask = false;
11756 /* The rank of the result will be determined later. */
11757 arg1 = expr->value.function.actual;
11758 arg2 = arg1->next;
11759 arg3 = arg2->next;
11760 gcc_assert (arg3 != NULL);
11762 if (expr->rank == 0)
11763 return ss;
11765 tmp_ss = gfc_ss_terminator;
11767 if (arg3->expr)
11769 gfc_ss *mask_ss;
11771 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
11772 if (mask_ss == tmp_ss)
11773 scalar_mask = 1;
11775 tmp_ss = mask_ss;
11778 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
11779 gcc_assert (array_ss != tmp_ss);
11781 /* Odd thing: If the mask is scalar, it is used by the frontend after
11782 the array (to make an if around the nested loop). Thus it shall
11783 be after array_ss once the gfc_ss list is reversed. */
11784 if (scalar_mask)
11785 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
11786 else
11787 tmp_ss = array_ss;
11789 /* "Hide" the dimension on which we will sum in the first arg's scalarization
11790 chain. */
11791 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
11792 tail = nest_loop_dimension (tmp_ss, sum_dim);
11793 tail->next = ss;
11795 return tmp_ss;
11799 /* Create the gfc_ss list for the arguments to MINLOC or MAXLOC when the
11800 function is to be inlined. */
11802 static gfc_ss *
11803 walk_inline_intrinsic_minmaxloc (gfc_ss *ss, gfc_expr *expr ATTRIBUTE_UNUSED)
11805 if (expr->rank == 0)
11806 return ss;
11808 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
11812 static gfc_ss *
11813 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
11816 switch (expr->value.function.isym->id)
11818 case GFC_ISYM_PRODUCT:
11819 case GFC_ISYM_SUM:
11820 return walk_inline_intrinsic_arith (ss, expr);
11822 case GFC_ISYM_TRANSPOSE:
11823 return walk_inline_intrinsic_transpose (ss, expr);
11825 case GFC_ISYM_MAXLOC:
11826 case GFC_ISYM_MINLOC:
11827 return walk_inline_intrinsic_minmaxloc (ss, expr);
11829 default:
11830 gcc_unreachable ();
11832 gcc_unreachable ();
11836 /* This generates code to execute before entering the scalarization loop.
11837 Currently does nothing. */
11839 void
11840 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
11842 switch (ss->info->expr->value.function.isym->id)
11844 case GFC_ISYM_UBOUND:
11845 case GFC_ISYM_LBOUND:
11846 case GFC_ISYM_UCOBOUND:
11847 case GFC_ISYM_LCOBOUND:
11848 case GFC_ISYM_MAXLOC:
11849 case GFC_ISYM_MINLOC:
11850 case GFC_ISYM_THIS_IMAGE:
11851 case GFC_ISYM_SHAPE:
11852 break;
11854 default:
11855 gcc_unreachable ();
11860 /* The LBOUND, LCOBOUND, UBOUND, UCOBOUND, and SHAPE intrinsics with
11861 one parameter are expanded into code inside the scalarization loop. */
11863 static gfc_ss *
11864 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
11866 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
11867 gfc_add_class_array_ref (expr->value.function.actual->expr);
11869 /* The two argument version returns a scalar. */
11870 if (expr->value.function.isym->id != GFC_ISYM_SHAPE
11871 && expr->value.function.actual->next->expr)
11872 return ss;
11874 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
11878 /* Walk an intrinsic array libcall. */
11880 static gfc_ss *
11881 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
11883 gcc_assert (expr->rank > 0);
11884 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
11888 /* Return whether the function call expression EXPR will be expanded
11889 inline by gfc_conv_intrinsic_function. */
11891 bool
11892 gfc_inline_intrinsic_function_p (gfc_expr *expr)
11894 gfc_actual_arglist *args, *dim_arg, *mask_arg;
11895 gfc_expr *maskexpr;
11897 gfc_intrinsic_sym *isym = expr->value.function.isym;
11898 if (!isym)
11899 return false;
11901 switch (isym->id)
11903 case GFC_ISYM_PRODUCT:
11904 case GFC_ISYM_SUM:
11905 /* Disable inline expansion if code size matters. */
11906 if (optimize_size)
11907 return false;
11909 args = expr->value.function.actual;
11910 dim_arg = args->next;
11912 /* We need to be able to subset the SUM argument at compile-time. */
11913 if (dim_arg->expr && dim_arg->expr->expr_type != EXPR_CONSTANT)
11914 return false;
11916 /* FIXME: If MASK is optional for a more than two-dimensional
11917 argument, the scalarizer gets confused if the mask is
11918 absent. See PR 82995. For now, fall back to the library
11919 function. */
11921 mask_arg = dim_arg->next;
11922 maskexpr = mask_arg->expr;
11924 if (expr->rank > 0 && maskexpr && maskexpr->expr_type == EXPR_VARIABLE
11925 && maskexpr->symtree->n.sym->attr.dummy
11926 && maskexpr->symtree->n.sym->attr.optional)
11927 return false;
11929 return true;
11931 case GFC_ISYM_TRANSPOSE:
11932 return true;
11934 case GFC_ISYM_MINLOC:
11935 case GFC_ISYM_MAXLOC:
11937 if ((isym->id == GFC_ISYM_MINLOC
11938 && (flag_inline_intrinsics
11939 & GFC_FLAG_INLINE_INTRINSIC_MINLOC) == 0)
11940 || (isym->id == GFC_ISYM_MAXLOC
11941 && (flag_inline_intrinsics
11942 & GFC_FLAG_INLINE_INTRINSIC_MAXLOC) == 0))
11943 return false;
11945 gfc_actual_arglist *array_arg = expr->value.function.actual;
11946 gfc_actual_arglist *dim_arg = array_arg->next;
11948 gfc_expr *array = array_arg->expr;
11949 gfc_expr *dim = dim_arg->expr;
11951 if (!(array->ts.type == BT_INTEGER
11952 || array->ts.type == BT_REAL))
11953 return false;
11955 if (array->rank == 1)
11956 return true;
11958 if (dim == nullptr)
11959 return true;
11961 return false;
11964 default:
11965 return false;
11970 /* Returns nonzero if the specified intrinsic function call maps directly to
11971 an external library call. Should only be used for functions that return
11972 arrays. */
11975 gfc_is_intrinsic_libcall (gfc_expr * expr)
11977 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
11978 gcc_assert (expr->rank > 0);
11980 if (gfc_inline_intrinsic_function_p (expr))
11981 return 0;
11983 switch (expr->value.function.isym->id)
11985 case GFC_ISYM_ALL:
11986 case GFC_ISYM_ANY:
11987 case GFC_ISYM_COUNT:
11988 case GFC_ISYM_FINDLOC:
11989 case GFC_ISYM_JN2:
11990 case GFC_ISYM_IANY:
11991 case GFC_ISYM_IALL:
11992 case GFC_ISYM_IPARITY:
11993 case GFC_ISYM_MATMUL:
11994 case GFC_ISYM_MAXLOC:
11995 case GFC_ISYM_MAXVAL:
11996 case GFC_ISYM_MINLOC:
11997 case GFC_ISYM_MINVAL:
11998 case GFC_ISYM_NORM2:
11999 case GFC_ISYM_PARITY:
12000 case GFC_ISYM_PRODUCT:
12001 case GFC_ISYM_SUM:
12002 case GFC_ISYM_SPREAD:
12003 case GFC_ISYM_YN2:
12004 /* Ignore absent optional parameters. */
12005 return 1;
12007 case GFC_ISYM_CSHIFT:
12008 case GFC_ISYM_EOSHIFT:
12009 case GFC_ISYM_GET_TEAM:
12010 case GFC_ISYM_FAILED_IMAGES:
12011 case GFC_ISYM_STOPPED_IMAGES:
12012 case GFC_ISYM_PACK:
12013 case GFC_ISYM_RESHAPE:
12014 case GFC_ISYM_UNPACK:
12015 /* Pass absent optional parameters. */
12016 return 2;
12018 default:
12019 return 0;
12023 /* Walk an intrinsic function. */
12024 gfc_ss *
12025 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
12026 gfc_intrinsic_sym * isym)
12028 gcc_assert (isym);
12030 if (isym->elemental)
12031 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
12032 expr->value.function.isym,
12033 GFC_SS_SCALAR);
12035 if (expr->rank == 0 && expr->corank == 0)
12036 return ss;
12038 if (gfc_inline_intrinsic_function_p (expr))
12039 return walk_inline_intrinsic_function (ss, expr);
12041 if (expr->rank != 0 && gfc_is_intrinsic_libcall (expr))
12042 return gfc_walk_intrinsic_libfunc (ss, expr);
12044 /* Special cases. */
12045 switch (isym->id)
12047 case GFC_ISYM_LBOUND:
12048 case GFC_ISYM_LCOBOUND:
12049 case GFC_ISYM_UBOUND:
12050 case GFC_ISYM_UCOBOUND:
12051 case GFC_ISYM_THIS_IMAGE:
12052 case GFC_ISYM_SHAPE:
12053 return gfc_walk_intrinsic_bound (ss, expr);
12055 case GFC_ISYM_TRANSFER:
12056 case GFC_ISYM_CAF_GET:
12057 return gfc_walk_intrinsic_libfunc (ss, expr);
12059 default:
12060 /* This probably meant someone forgot to add an intrinsic to the above
12061 list(s) when they implemented it, or something's gone horribly
12062 wrong. */
12063 gcc_unreachable ();
12067 static tree
12068 conv_co_collective (gfc_code *code)
12070 gfc_se argse;
12071 stmtblock_t block, post_block;
12072 tree fndecl, array = NULL_TREE, strlen, image_index, stat, errmsg, errmsg_len;
12073 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
12075 gfc_start_block (&block);
12076 gfc_init_block (&post_block);
12078 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
12080 opr_expr = code->ext.actual->next->expr;
12081 image_idx_expr = code->ext.actual->next->next->expr;
12082 stat_expr = code->ext.actual->next->next->next->expr;
12083 errmsg_expr = code->ext.actual->next->next->next->next->expr;
12085 else
12087 opr_expr = NULL;
12088 image_idx_expr = code->ext.actual->next->expr;
12089 stat_expr = code->ext.actual->next->next->expr;
12090 errmsg_expr = code->ext.actual->next->next->next->expr;
12093 /* stat. */
12094 if (stat_expr)
12096 gfc_init_se (&argse, NULL);
12097 gfc_conv_expr (&argse, stat_expr);
12098 gfc_add_block_to_block (&block, &argse.pre);
12099 gfc_add_block_to_block (&post_block, &argse.post);
12100 stat = argse.expr;
12101 if (flag_coarray != GFC_FCOARRAY_SINGLE)
12102 stat = gfc_build_addr_expr (NULL_TREE, stat);
12104 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
12105 stat = NULL_TREE;
12106 else
12107 stat = null_pointer_node;
12109 /* Early exit for GFC_FCOARRAY_SINGLE. */
12110 if (flag_coarray == GFC_FCOARRAY_SINGLE)
12112 if (stat != NULL_TREE)
12114 /* For optional stats, check the pointer is valid before zero'ing. */
12115 if (gfc_expr_attr (stat_expr).optional)
12117 tree tmp;
12118 stmtblock_t ass_block;
12119 gfc_start_block (&ass_block);
12120 gfc_add_modify (&ass_block, stat,
12121 fold_convert (TREE_TYPE (stat),
12122 integer_zero_node));
12123 tmp = fold_build2 (NE_EXPR, logical_type_node,
12124 gfc_build_addr_expr (NULL_TREE, stat),
12125 null_pointer_node);
12126 tmp = fold_build3 (COND_EXPR, void_type_node, tmp,
12127 gfc_finish_block (&ass_block),
12128 build_empty_stmt (input_location));
12129 gfc_add_expr_to_block (&block, tmp);
12131 else
12132 gfc_add_modify (&block, stat,
12133 fold_convert (TREE_TYPE (stat), integer_zero_node));
12135 return gfc_finish_block (&block);
12138 gfc_symbol *derived = code->ext.actual->expr->ts.type == BT_DERIVED
12139 ? code->ext.actual->expr->ts.u.derived : NULL;
12141 /* Handle the array. */
12142 gfc_init_se (&argse, NULL);
12143 if (!derived || !derived->attr.alloc_comp
12144 || code->resolved_isym->id != GFC_ISYM_CO_BROADCAST)
12146 if (code->ext.actual->expr->rank == 0)
12148 symbol_attribute attr;
12149 gfc_clear_attr (&attr);
12150 gfc_init_se (&argse, NULL);
12151 gfc_conv_expr (&argse, code->ext.actual->expr);
12152 gfc_add_block_to_block (&block, &argse.pre);
12153 gfc_add_block_to_block (&post_block, &argse.post);
12154 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
12155 array = gfc_build_addr_expr (NULL_TREE, array);
12157 else
12159 argse.want_pointer = 1;
12160 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
12161 array = argse.expr;
12165 gfc_add_block_to_block (&block, &argse.pre);
12166 gfc_add_block_to_block (&post_block, &argse.post);
12168 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
12169 strlen = argse.string_length;
12170 else
12171 strlen = integer_zero_node;
12173 /* image_index. */
12174 if (image_idx_expr)
12176 gfc_init_se (&argse, NULL);
12177 gfc_conv_expr (&argse, image_idx_expr);
12178 gfc_add_block_to_block (&block, &argse.pre);
12179 gfc_add_block_to_block (&post_block, &argse.post);
12180 image_index = fold_convert (integer_type_node, argse.expr);
12182 else
12183 image_index = integer_zero_node;
12185 /* errmsg. */
12186 if (errmsg_expr)
12188 gfc_init_se (&argse, NULL);
12189 gfc_conv_expr (&argse, errmsg_expr);
12190 gfc_add_block_to_block (&block, &argse.pre);
12191 gfc_add_block_to_block (&post_block, &argse.post);
12192 errmsg = argse.expr;
12193 errmsg_len = fold_convert (size_type_node, argse.string_length);
12195 else
12197 errmsg = null_pointer_node;
12198 errmsg_len = build_zero_cst (size_type_node);
12201 /* Generate the function call. */
12202 switch (code->resolved_isym->id)
12204 case GFC_ISYM_CO_BROADCAST:
12205 fndecl = gfor_fndecl_co_broadcast;
12206 break;
12207 case GFC_ISYM_CO_MAX:
12208 fndecl = gfor_fndecl_co_max;
12209 break;
12210 case GFC_ISYM_CO_MIN:
12211 fndecl = gfor_fndecl_co_min;
12212 break;
12213 case GFC_ISYM_CO_REDUCE:
12214 fndecl = gfor_fndecl_co_reduce;
12215 break;
12216 case GFC_ISYM_CO_SUM:
12217 fndecl = gfor_fndecl_co_sum;
12218 break;
12219 default:
12220 gcc_unreachable ();
12223 if (derived && derived->attr.alloc_comp
12224 && code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
12225 /* The derived type has the attribute 'alloc_comp'. */
12227 tree tmp = gfc_bcast_alloc_comp (derived, code->ext.actual->expr,
12228 code->ext.actual->expr->rank,
12229 image_index, stat, errmsg, errmsg_len);
12230 gfc_add_expr_to_block (&block, tmp);
12232 else
12234 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
12235 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
12236 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
12237 image_index, stat, errmsg, errmsg_len);
12238 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
12239 fndecl = build_call_expr_loc (input_location, fndecl, 6, array,
12240 image_index, stat, errmsg,
12241 strlen, errmsg_len);
12242 else
12244 tree opr, opr_flags;
12246 // FIXME: Handle TS29113's bind(C) strings with descriptor.
12247 int opr_flag_int;
12248 if (gfc_is_proc_ptr_comp (opr_expr))
12250 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
12251 opr_flag_int = sym->attr.dimension
12252 || (sym->ts.type == BT_CHARACTER
12253 && !sym->attr.is_bind_c)
12254 ? GFC_CAF_BYREF : 0;
12255 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
12256 && !sym->attr.is_bind_c
12257 ? GFC_CAF_HIDDENLEN : 0;
12258 opr_flag_int |= sym->formal->sym->attr.value
12259 ? GFC_CAF_ARG_VALUE : 0;
12261 else
12263 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
12264 ? GFC_CAF_BYREF : 0;
12265 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
12266 && !opr_expr->symtree->n.sym->attr.is_bind_c
12267 ? GFC_CAF_HIDDENLEN : 0;
12268 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
12269 ? GFC_CAF_ARG_VALUE : 0;
12271 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
12272 gfc_conv_expr (&argse, opr_expr);
12273 opr = argse.expr;
12274 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr,
12275 opr_flags, image_index, stat, errmsg,
12276 strlen, errmsg_len);
12280 gfc_add_expr_to_block (&block, fndecl);
12281 gfc_add_block_to_block (&block, &post_block);
12283 return gfc_finish_block (&block);
12287 static tree
12288 conv_intrinsic_atomic_op (gfc_code *code)
12290 gfc_se argse;
12291 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
12292 stmtblock_t block, post_block;
12293 gfc_expr *atom_expr = code->ext.actual->expr;
12294 gfc_expr *stat_expr;
12295 built_in_function fn;
12297 if (atom_expr->expr_type == EXPR_FUNCTION
12298 && atom_expr->value.function.isym
12299 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
12300 atom_expr = atom_expr->value.function.actual->expr;
12302 gfc_start_block (&block);
12303 gfc_init_block (&post_block);
12305 gfc_init_se (&argse, NULL);
12306 argse.want_pointer = 1;
12307 gfc_conv_expr (&argse, atom_expr);
12308 gfc_add_block_to_block (&block, &argse.pre);
12309 gfc_add_block_to_block (&post_block, &argse.post);
12310 atom = argse.expr;
12312 gfc_init_se (&argse, NULL);
12313 if (flag_coarray == GFC_FCOARRAY_LIB
12314 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
12315 argse.want_pointer = 1;
12316 gfc_conv_expr (&argse, code->ext.actual->next->expr);
12317 gfc_add_block_to_block (&block, &argse.pre);
12318 gfc_add_block_to_block (&post_block, &argse.post);
12319 value = argse.expr;
12321 switch (code->resolved_isym->id)
12323 case GFC_ISYM_ATOMIC_ADD:
12324 case GFC_ISYM_ATOMIC_AND:
12325 case GFC_ISYM_ATOMIC_DEF:
12326 case GFC_ISYM_ATOMIC_OR:
12327 case GFC_ISYM_ATOMIC_XOR:
12328 stat_expr = code->ext.actual->next->next->expr;
12329 if (flag_coarray == GFC_FCOARRAY_LIB)
12330 old = null_pointer_node;
12331 break;
12332 default:
12333 gfc_init_se (&argse, NULL);
12334 if (flag_coarray == GFC_FCOARRAY_LIB)
12335 argse.want_pointer = 1;
12336 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
12337 gfc_add_block_to_block (&block, &argse.pre);
12338 gfc_add_block_to_block (&post_block, &argse.post);
12339 old = argse.expr;
12340 stat_expr = code->ext.actual->next->next->next->expr;
12343 /* STAT= */
12344 if (stat_expr != NULL)
12346 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
12347 gfc_init_se (&argse, NULL);
12348 if (flag_coarray == GFC_FCOARRAY_LIB)
12349 argse.want_pointer = 1;
12350 gfc_conv_expr_val (&argse, stat_expr);
12351 gfc_add_block_to_block (&block, &argse.pre);
12352 gfc_add_block_to_block (&post_block, &argse.post);
12353 stat = argse.expr;
12355 else if (flag_coarray == GFC_FCOARRAY_LIB)
12356 stat = null_pointer_node;
12358 if (flag_coarray == GFC_FCOARRAY_LIB)
12360 tree image_index, caf_decl, offset, token;
12361 int op;
12363 switch (code->resolved_isym->id)
12365 case GFC_ISYM_ATOMIC_ADD:
12366 case GFC_ISYM_ATOMIC_FETCH_ADD:
12367 op = (int) GFC_CAF_ATOMIC_ADD;
12368 break;
12369 case GFC_ISYM_ATOMIC_AND:
12370 case GFC_ISYM_ATOMIC_FETCH_AND:
12371 op = (int) GFC_CAF_ATOMIC_AND;
12372 break;
12373 case GFC_ISYM_ATOMIC_OR:
12374 case GFC_ISYM_ATOMIC_FETCH_OR:
12375 op = (int) GFC_CAF_ATOMIC_OR;
12376 break;
12377 case GFC_ISYM_ATOMIC_XOR:
12378 case GFC_ISYM_ATOMIC_FETCH_XOR:
12379 op = (int) GFC_CAF_ATOMIC_XOR;
12380 break;
12381 case GFC_ISYM_ATOMIC_DEF:
12382 op = 0; /* Unused. */
12383 break;
12384 default:
12385 gcc_unreachable ();
12388 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
12389 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
12390 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
12392 if (gfc_is_coindexed (atom_expr))
12393 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
12394 else
12395 image_index = integer_zero_node;
12397 if (!POINTER_TYPE_P (TREE_TYPE (value)))
12399 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
12400 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
12401 value = gfc_build_addr_expr (NULL_TREE, tmp);
12404 gfc_init_se (&argse, NULL);
12405 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
12406 atom_expr);
12408 gfc_add_block_to_block (&block, &argse.pre);
12409 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
12410 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
12411 token, offset, image_index, value, stat,
12412 build_int_cst (integer_type_node,
12413 (int) atom_expr->ts.type),
12414 build_int_cst (integer_type_node,
12415 (int) atom_expr->ts.kind));
12416 else
12417 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
12418 build_int_cst (integer_type_node, op),
12419 token, offset, image_index, value, old, stat,
12420 build_int_cst (integer_type_node,
12421 (int) atom_expr->ts.type),
12422 build_int_cst (integer_type_node,
12423 (int) atom_expr->ts.kind));
12425 gfc_add_expr_to_block (&block, tmp);
12426 gfc_add_block_to_block (&block, &argse.post);
12427 gfc_add_block_to_block (&block, &post_block);
12428 return gfc_finish_block (&block);
12432 switch (code->resolved_isym->id)
12434 case GFC_ISYM_ATOMIC_ADD:
12435 case GFC_ISYM_ATOMIC_FETCH_ADD:
12436 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
12437 break;
12438 case GFC_ISYM_ATOMIC_AND:
12439 case GFC_ISYM_ATOMIC_FETCH_AND:
12440 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
12441 break;
12442 case GFC_ISYM_ATOMIC_DEF:
12443 fn = BUILT_IN_ATOMIC_STORE_N;
12444 break;
12445 case GFC_ISYM_ATOMIC_OR:
12446 case GFC_ISYM_ATOMIC_FETCH_OR:
12447 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
12448 break;
12449 case GFC_ISYM_ATOMIC_XOR:
12450 case GFC_ISYM_ATOMIC_FETCH_XOR:
12451 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
12452 break;
12453 default:
12454 gcc_unreachable ();
12457 tmp = TREE_TYPE (TREE_TYPE (atom));
12458 fn = (built_in_function) ((int) fn
12459 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
12460 + 1);
12461 tree itype = TREE_TYPE (TREE_TYPE (atom));
12462 tmp = builtin_decl_explicit (fn);
12464 switch (code->resolved_isym->id)
12466 case GFC_ISYM_ATOMIC_ADD:
12467 case GFC_ISYM_ATOMIC_AND:
12468 case GFC_ISYM_ATOMIC_DEF:
12469 case GFC_ISYM_ATOMIC_OR:
12470 case GFC_ISYM_ATOMIC_XOR:
12471 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
12472 fold_convert (itype, value),
12473 build_int_cst (NULL, MEMMODEL_RELAXED));
12474 gfc_add_expr_to_block (&block, tmp);
12475 break;
12476 default:
12477 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
12478 fold_convert (itype, value),
12479 build_int_cst (NULL, MEMMODEL_RELAXED));
12480 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
12481 break;
12484 if (stat != NULL_TREE)
12485 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
12486 gfc_add_block_to_block (&block, &post_block);
12487 return gfc_finish_block (&block);
12491 static tree
12492 conv_intrinsic_atomic_ref (gfc_code *code)
12494 gfc_se argse;
12495 tree tmp, atom, value, stat = NULL_TREE;
12496 stmtblock_t block, post_block;
12497 built_in_function fn;
12498 gfc_expr *atom_expr = code->ext.actual->next->expr;
12500 if (atom_expr->expr_type == EXPR_FUNCTION
12501 && atom_expr->value.function.isym
12502 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
12503 atom_expr = atom_expr->value.function.actual->expr;
12505 gfc_start_block (&block);
12506 gfc_init_block (&post_block);
12507 gfc_init_se (&argse, NULL);
12508 argse.want_pointer = 1;
12509 gfc_conv_expr (&argse, atom_expr);
12510 gfc_add_block_to_block (&block, &argse.pre);
12511 gfc_add_block_to_block (&post_block, &argse.post);
12512 atom = argse.expr;
12514 gfc_init_se (&argse, NULL);
12515 if (flag_coarray == GFC_FCOARRAY_LIB
12516 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
12517 argse.want_pointer = 1;
12518 gfc_conv_expr (&argse, code->ext.actual->expr);
12519 gfc_add_block_to_block (&block, &argse.pre);
12520 gfc_add_block_to_block (&post_block, &argse.post);
12521 value = argse.expr;
12523 /* STAT= */
12524 if (code->ext.actual->next->next->expr != NULL)
12526 gcc_assert (code->ext.actual->next->next->expr->expr_type
12527 == EXPR_VARIABLE);
12528 gfc_init_se (&argse, NULL);
12529 if (flag_coarray == GFC_FCOARRAY_LIB)
12530 argse.want_pointer = 1;
12531 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
12532 gfc_add_block_to_block (&block, &argse.pre);
12533 gfc_add_block_to_block (&post_block, &argse.post);
12534 stat = argse.expr;
12536 else if (flag_coarray == GFC_FCOARRAY_LIB)
12537 stat = null_pointer_node;
12539 if (flag_coarray == GFC_FCOARRAY_LIB)
12541 tree image_index, caf_decl, offset, token;
12542 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
12544 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
12545 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
12546 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
12548 if (gfc_is_coindexed (atom_expr))
12549 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
12550 else
12551 image_index = integer_zero_node;
12553 gfc_init_se (&argse, NULL);
12554 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
12555 atom_expr);
12556 gfc_add_block_to_block (&block, &argse.pre);
12558 /* Different type, need type conversion. */
12559 if (!POINTER_TYPE_P (TREE_TYPE (value)))
12561 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
12562 orig_value = value;
12563 value = gfc_build_addr_expr (NULL_TREE, vardecl);
12566 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
12567 token, offset, image_index, value, stat,
12568 build_int_cst (integer_type_node,
12569 (int) atom_expr->ts.type),
12570 build_int_cst (integer_type_node,
12571 (int) atom_expr->ts.kind));
12572 gfc_add_expr_to_block (&block, tmp);
12573 if (vardecl != NULL_TREE)
12574 gfc_add_modify (&block, orig_value,
12575 fold_convert (TREE_TYPE (orig_value), vardecl));
12576 gfc_add_block_to_block (&block, &argse.post);
12577 gfc_add_block_to_block (&block, &post_block);
12578 return gfc_finish_block (&block);
12581 tmp = TREE_TYPE (TREE_TYPE (atom));
12582 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
12583 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
12584 + 1);
12585 tmp = builtin_decl_explicit (fn);
12586 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
12587 build_int_cst (integer_type_node,
12588 MEMMODEL_RELAXED));
12589 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
12591 if (stat != NULL_TREE)
12592 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
12593 gfc_add_block_to_block (&block, &post_block);
12594 return gfc_finish_block (&block);
12598 static tree
12599 conv_intrinsic_atomic_cas (gfc_code *code)
12601 gfc_se argse;
12602 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
12603 stmtblock_t block, post_block;
12604 built_in_function fn;
12605 gfc_expr *atom_expr = code->ext.actual->expr;
12607 if (atom_expr->expr_type == EXPR_FUNCTION
12608 && atom_expr->value.function.isym
12609 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
12610 atom_expr = atom_expr->value.function.actual->expr;
12612 gfc_init_block (&block);
12613 gfc_init_block (&post_block);
12614 gfc_init_se (&argse, NULL);
12615 argse.want_pointer = 1;
12616 gfc_conv_expr (&argse, atom_expr);
12617 atom = argse.expr;
12619 gfc_init_se (&argse, NULL);
12620 if (flag_coarray == GFC_FCOARRAY_LIB)
12621 argse.want_pointer = 1;
12622 gfc_conv_expr (&argse, code->ext.actual->next->expr);
12623 gfc_add_block_to_block (&block, &argse.pre);
12624 gfc_add_block_to_block (&post_block, &argse.post);
12625 old = argse.expr;
12627 gfc_init_se (&argse, NULL);
12628 if (flag_coarray == GFC_FCOARRAY_LIB)
12629 argse.want_pointer = 1;
12630 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
12631 gfc_add_block_to_block (&block, &argse.pre);
12632 gfc_add_block_to_block (&post_block, &argse.post);
12633 comp = argse.expr;
12635 gfc_init_se (&argse, NULL);
12636 if (flag_coarray == GFC_FCOARRAY_LIB
12637 && code->ext.actual->next->next->next->expr->ts.kind
12638 == atom_expr->ts.kind)
12639 argse.want_pointer = 1;
12640 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
12641 gfc_add_block_to_block (&block, &argse.pre);
12642 gfc_add_block_to_block (&post_block, &argse.post);
12643 new_val = argse.expr;
12645 /* STAT= */
12646 if (code->ext.actual->next->next->next->next->expr != NULL)
12648 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
12649 == EXPR_VARIABLE);
12650 gfc_init_se (&argse, NULL);
12651 if (flag_coarray == GFC_FCOARRAY_LIB)
12652 argse.want_pointer = 1;
12653 gfc_conv_expr_val (&argse,
12654 code->ext.actual->next->next->next->next->expr);
12655 gfc_add_block_to_block (&block, &argse.pre);
12656 gfc_add_block_to_block (&post_block, &argse.post);
12657 stat = argse.expr;
12659 else if (flag_coarray == GFC_FCOARRAY_LIB)
12660 stat = null_pointer_node;
12662 if (flag_coarray == GFC_FCOARRAY_LIB)
12664 tree image_index, caf_decl, offset, token;
12666 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
12667 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
12668 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
12670 if (gfc_is_coindexed (atom_expr))
12671 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
12672 else
12673 image_index = integer_zero_node;
12675 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
12677 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
12678 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
12679 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
12682 /* Convert a constant to a pointer. */
12683 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
12685 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
12686 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
12687 comp = gfc_build_addr_expr (NULL_TREE, tmp);
12690 gfc_init_se (&argse, NULL);
12691 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
12692 atom_expr);
12693 gfc_add_block_to_block (&block, &argse.pre);
12695 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
12696 token, offset, image_index, old, comp, new_val,
12697 stat, build_int_cst (integer_type_node,
12698 (int) atom_expr->ts.type),
12699 build_int_cst (integer_type_node,
12700 (int) atom_expr->ts.kind));
12701 gfc_add_expr_to_block (&block, tmp);
12702 gfc_add_block_to_block (&block, &argse.post);
12703 gfc_add_block_to_block (&block, &post_block);
12704 return gfc_finish_block (&block);
12707 tmp = TREE_TYPE (TREE_TYPE (atom));
12708 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
12709 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
12710 + 1);
12711 tmp = builtin_decl_explicit (fn);
12713 gfc_add_modify (&block, old, comp);
12714 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
12715 gfc_build_addr_expr (NULL, old),
12716 fold_convert (TREE_TYPE (old), new_val),
12717 boolean_false_node,
12718 build_int_cst (NULL, MEMMODEL_RELAXED),
12719 build_int_cst (NULL, MEMMODEL_RELAXED));
12720 gfc_add_expr_to_block (&block, tmp);
12722 if (stat != NULL_TREE)
12723 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
12724 gfc_add_block_to_block (&block, &post_block);
12725 return gfc_finish_block (&block);
12728 static tree
12729 conv_intrinsic_event_query (gfc_code *code)
12731 gfc_se se, argse;
12732 tree stat = NULL_TREE, stat2 = NULL_TREE;
12733 tree count = NULL_TREE, count2 = NULL_TREE;
12735 gfc_expr *event_expr = code->ext.actual->expr;
12737 if (code->ext.actual->next->next->expr)
12739 gcc_assert (code->ext.actual->next->next->expr->expr_type
12740 == EXPR_VARIABLE);
12741 gfc_init_se (&argse, NULL);
12742 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
12743 stat = argse.expr;
12745 else if (flag_coarray == GFC_FCOARRAY_LIB)
12746 stat = null_pointer_node;
12748 if (code->ext.actual->next->expr)
12750 gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
12751 gfc_init_se (&argse, NULL);
12752 gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
12753 count = argse.expr;
12756 gfc_start_block (&se.pre);
12757 if (flag_coarray == GFC_FCOARRAY_LIB)
12759 tree tmp, token, image_index;
12760 tree index = build_zero_cst (gfc_array_index_type);
12762 if (event_expr->expr_type == EXPR_FUNCTION
12763 && event_expr->value.function.isym
12764 && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
12765 event_expr = event_expr->value.function.actual->expr;
12767 tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
12769 if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
12770 || event_expr->symtree->n.sym->ts.u.derived->from_intmod
12771 != INTMOD_ISO_FORTRAN_ENV
12772 || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
12773 != ISOFORTRAN_EVENT_TYPE)
12775 gfc_error ("Sorry, the event component of derived type at %L is not "
12776 "yet supported", &event_expr->where);
12777 return NULL_TREE;
12780 if (gfc_is_coindexed (event_expr))
12782 gfc_error ("The event variable at %L shall not be coindexed",
12783 &event_expr->where);
12784 return NULL_TREE;
12787 image_index = integer_zero_node;
12789 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
12790 event_expr);
12792 /* For arrays, obtain the array index. */
12793 if (gfc_expr_attr (event_expr).dimension)
12795 tree desc, tmp, extent, lbound, ubound;
12796 gfc_array_ref *ar, ar2;
12797 int i;
12799 /* TODO: Extend this, once DT components are supported. */
12800 ar = &event_expr->ref->u.ar;
12801 ar2 = *ar;
12802 memset (ar, '\0', sizeof (*ar));
12803 ar->as = ar2.as;
12804 ar->type = AR_FULL;
12806 gfc_init_se (&argse, NULL);
12807 argse.descriptor_only = 1;
12808 gfc_conv_expr_descriptor (&argse, event_expr);
12809 gfc_add_block_to_block (&se.pre, &argse.pre);
12810 desc = argse.expr;
12811 *ar = ar2;
12813 extent = build_one_cst (gfc_array_index_type);
12814 for (i = 0; i < ar->dimen; i++)
12816 gfc_init_se (&argse, NULL);
12817 gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
12818 gfc_add_block_to_block (&argse.pre, &argse.pre);
12819 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
12820 tmp = fold_build2_loc (input_location, MINUS_EXPR,
12821 TREE_TYPE (lbound), argse.expr, lbound);
12822 tmp = fold_build2_loc (input_location, MULT_EXPR,
12823 TREE_TYPE (tmp), extent, tmp);
12824 index = fold_build2_loc (input_location, PLUS_EXPR,
12825 TREE_TYPE (tmp), index, tmp);
12826 if (i < ar->dimen - 1)
12828 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
12829 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
12830 extent = fold_build2_loc (input_location, MULT_EXPR,
12831 TREE_TYPE (tmp), extent, tmp);
12836 if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
12838 count2 = count;
12839 count = gfc_create_var (integer_type_node, "count");
12842 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
12844 stat2 = stat;
12845 stat = gfc_create_var (integer_type_node, "stat");
12848 index = fold_convert (size_type_node, index);
12849 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
12850 token, index, image_index, count
12851 ? gfc_build_addr_expr (NULL, count) : count,
12852 stat != null_pointer_node
12853 ? gfc_build_addr_expr (NULL, stat) : stat);
12854 gfc_add_expr_to_block (&se.pre, tmp);
12856 if (count2 != NULL_TREE)
12857 gfc_add_modify (&se.pre, count2,
12858 fold_convert (TREE_TYPE (count2), count));
12860 if (stat2 != NULL_TREE)
12861 gfc_add_modify (&se.pre, stat2,
12862 fold_convert (TREE_TYPE (stat2), stat));
12864 return gfc_finish_block (&se.pre);
12867 gfc_init_se (&argse, NULL);
12868 gfc_conv_expr_val (&argse, code->ext.actual->expr);
12869 gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
12871 if (stat != NULL_TREE)
12872 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
12874 return gfc_finish_block (&se.pre);
12878 /* This is a peculiar case because of the need to do dependency checking.
12879 It is called via trans-stmt.cc(gfc_trans_call), where it is picked out as
12880 a special case and this function called instead of
12881 gfc_conv_procedure_call. */
12882 void
12883 gfc_conv_intrinsic_mvbits (gfc_se *se, gfc_actual_arglist *actual_args,
12884 gfc_loopinfo *loop)
12886 gfc_actual_arglist *actual;
12887 gfc_se argse[5];
12888 gfc_expr *arg[5];
12889 gfc_ss *lss;
12890 int n;
12892 tree from, frompos, len, to, topos;
12893 tree lenmask, oldbits, newbits, bitsize;
12894 tree type, utype, above, mask1, mask2;
12896 if (loop)
12897 lss = loop->ss;
12898 else
12899 lss = gfc_ss_terminator;
12901 actual = actual_args;
12902 for (n = 0; n < 5; n++, actual = actual->next)
12904 arg[n] = actual->expr;
12905 gfc_init_se (&argse[n], NULL);
12907 if (lss != gfc_ss_terminator)
12909 gfc_copy_loopinfo_to_se (&argse[n], loop);
12910 /* Find the ss for the expression if it is there. */
12911 argse[n].ss = lss;
12912 gfc_mark_ss_chain_used (lss, 1);
12915 gfc_conv_expr (&argse[n], arg[n]);
12917 if (loop)
12918 lss = argse[n].ss;
12921 from = argse[0].expr;
12922 frompos = argse[1].expr;
12923 len = argse[2].expr;
12924 to = argse[3].expr;
12925 topos = argse[4].expr;
12927 /* The type of the result (TO). */
12928 type = TREE_TYPE (to);
12929 bitsize = build_int_cst (integer_type_node, TYPE_PRECISION (type));
12931 /* Optionally generate code for runtime argument check. */
12932 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
12934 tree nbits, below, ccond;
12935 tree fp = fold_convert (long_integer_type_node, frompos);
12936 tree ln = fold_convert (long_integer_type_node, len);
12937 tree tp = fold_convert (long_integer_type_node, topos);
12938 below = fold_build2_loc (input_location, LT_EXPR,
12939 logical_type_node, frompos,
12940 build_int_cst (TREE_TYPE (frompos), 0));
12941 above = fold_build2_loc (input_location, GT_EXPR,
12942 logical_type_node, frompos,
12943 fold_convert (TREE_TYPE (frompos), bitsize));
12944 ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
12945 logical_type_node, below, above);
12946 gfc_trans_runtime_check (true, false, ccond, &argse[1].pre,
12947 &arg[1]->where,
12948 "FROMPOS argument (%ld) out of range 0:%d "
12949 "in intrinsic MVBITS", fp, bitsize);
12950 below = fold_build2_loc (input_location, LT_EXPR,
12951 logical_type_node, len,
12952 build_int_cst (TREE_TYPE (len), 0));
12953 above = fold_build2_loc (input_location, GT_EXPR,
12954 logical_type_node, len,
12955 fold_convert (TREE_TYPE (len), bitsize));
12956 ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
12957 logical_type_node, below, above);
12958 gfc_trans_runtime_check (true, false, ccond, &argse[2].pre,
12959 &arg[2]->where,
12960 "LEN argument (%ld) out of range 0:%d "
12961 "in intrinsic MVBITS", ln, bitsize);
12962 below = fold_build2_loc (input_location, LT_EXPR,
12963 logical_type_node, topos,
12964 build_int_cst (TREE_TYPE (topos), 0));
12965 above = fold_build2_loc (input_location, GT_EXPR,
12966 logical_type_node, topos,
12967 fold_convert (TREE_TYPE (topos), bitsize));
12968 ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
12969 logical_type_node, below, above);
12970 gfc_trans_runtime_check (true, false, ccond, &argse[4].pre,
12971 &arg[4]->where,
12972 "TOPOS argument (%ld) out of range 0:%d "
12973 "in intrinsic MVBITS", tp, bitsize);
12975 /* The tests above ensure that FROMPOS, LEN and TOPOS fit into short
12976 integers. Additions below cannot overflow. */
12977 nbits = fold_convert (long_integer_type_node, bitsize);
12978 above = fold_build2_loc (input_location, PLUS_EXPR,
12979 long_integer_type_node, fp, ln);
12980 ccond = fold_build2_loc (input_location, GT_EXPR,
12981 logical_type_node, above, nbits);
12982 gfc_trans_runtime_check (true, false, ccond, &argse[1].pre,
12983 &arg[1]->where,
12984 "FROMPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
12985 "in intrinsic MVBITS", fp, ln, bitsize);
12986 above = fold_build2_loc (input_location, PLUS_EXPR,
12987 long_integer_type_node, tp, ln);
12988 ccond = fold_build2_loc (input_location, GT_EXPR,
12989 logical_type_node, above, nbits);
12990 gfc_trans_runtime_check (true, false, ccond, &argse[4].pre,
12991 &arg[4]->where,
12992 "TOPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
12993 "in intrinsic MVBITS", tp, ln, bitsize);
12996 for (n = 0; n < 5; n++)
12998 gfc_add_block_to_block (&se->pre, &argse[n].pre);
12999 gfc_add_block_to_block (&se->post, &argse[n].post);
13002 /* lenmask = (LEN >= bit_size (TYPE)) ? ~(TYPE)0 : ((TYPE)1 << LEN) - 1 */
13003 above = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
13004 len, fold_convert (TREE_TYPE (len), bitsize));
13005 mask1 = build_int_cst (type, -1);
13006 mask2 = fold_build2_loc (input_location, LSHIFT_EXPR, type,
13007 build_int_cst (type, 1), len);
13008 mask2 = fold_build2_loc (input_location, MINUS_EXPR, type,
13009 mask2, build_int_cst (type, 1));
13010 lenmask = fold_build3_loc (input_location, COND_EXPR, type,
13011 above, mask1, mask2);
13013 /* newbits = (((UTYPE)(FROM) >> FROMPOS) & lenmask) << TOPOS.
13014 * For valid frompos+len <= bit_size(FROM) the conversion to unsigned is
13015 * not strictly necessary; artificial bits from rshift will be masked. */
13016 utype = unsigned_type_for (type);
13017 newbits = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
13018 fold_convert (utype, from), frompos);
13019 newbits = fold_build2_loc (input_location, BIT_AND_EXPR, type,
13020 fold_convert (type, newbits), lenmask);
13021 newbits = fold_build2_loc (input_location, LSHIFT_EXPR, type,
13022 newbits, topos);
13024 /* oldbits = TO & (~(lenmask << TOPOS)). */
13025 oldbits = fold_build2_loc (input_location, LSHIFT_EXPR, type,
13026 lenmask, topos);
13027 oldbits = fold_build1_loc (input_location, BIT_NOT_EXPR, type, oldbits);
13028 oldbits = fold_build2_loc (input_location, BIT_AND_EXPR, type, oldbits, to);
13030 /* TO = newbits | oldbits. */
13031 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
13032 oldbits, newbits);
13034 /* Return the assignment. */
13035 se->expr = fold_build2_loc (input_location, MODIFY_EXPR,
13036 void_type_node, to, se->expr);
13040 static tree
13041 conv_intrinsic_move_alloc (gfc_code *code)
13043 stmtblock_t block;
13044 gfc_expr *from_expr, *to_expr;
13045 gfc_se from_se, to_se;
13046 tree tmp, to_tree, from_tree;
13047 bool coarray, from_is_class, from_is_scalar;
13049 gfc_start_block (&block);
13051 from_expr = code->ext.actual->expr;
13052 to_expr = code->ext.actual->next->expr;
13054 gfc_init_se (&from_se, NULL);
13055 gfc_init_se (&to_se, NULL);
13057 gcc_assert (from_expr->ts.type != BT_CLASS || to_expr->ts.type == BT_CLASS);
13058 coarray = from_expr->corank != 0;
13060 from_is_class = from_expr->ts.type == BT_CLASS;
13061 from_is_scalar = from_expr->rank == 0 && !coarray;
13062 if (to_expr->ts.type == BT_CLASS || from_is_scalar)
13064 from_se.want_pointer = 1;
13065 if (from_is_scalar)
13066 gfc_conv_expr (&from_se, from_expr);
13067 else
13068 gfc_conv_expr_descriptor (&from_se, from_expr);
13069 if (from_is_class)
13070 from_tree = gfc_class_data_get (from_se.expr);
13071 else
13073 gfc_symbol *vtab;
13074 from_tree = from_se.expr;
13076 if (to_expr->ts.type == BT_CLASS)
13078 vtab = gfc_find_vtab (&from_expr->ts);
13079 gcc_assert (vtab);
13080 from_se.expr = gfc_get_symbol_decl (vtab);
13083 gfc_add_block_to_block (&block, &from_se.pre);
13085 to_se.want_pointer = 1;
13086 if (to_expr->rank == 0)
13087 gfc_conv_expr (&to_se, to_expr);
13088 else
13089 gfc_conv_expr_descriptor (&to_se, to_expr);
13090 if (to_expr->ts.type == BT_CLASS)
13091 to_tree = gfc_class_data_get (to_se.expr);
13092 else
13093 to_tree = to_se.expr;
13094 gfc_add_block_to_block (&block, &to_se.pre);
13096 /* Deallocate "to". */
13097 if (to_expr->rank == 0)
13100 = gfc_deallocate_scalar_with_status (to_tree, NULL_TREE, NULL_TREE,
13101 true, to_expr, to_expr->ts);
13102 gfc_add_expr_to_block (&block, tmp);
13105 if (from_is_scalar)
13107 /* Assign (_data) pointers. */
13108 gfc_add_modify_loc (input_location, &block, to_tree,
13109 fold_convert (TREE_TYPE (to_tree), from_tree));
13111 /* Set "from" to NULL. */
13112 gfc_add_modify_loc (input_location, &block, from_tree,
13113 fold_convert (TREE_TYPE (from_tree),
13114 null_pointer_node));
13116 gfc_add_block_to_block (&block, &from_se.post);
13118 gfc_add_block_to_block (&block, &to_se.post);
13120 /* Set _vptr. */
13121 if (to_expr->ts.type == BT_CLASS)
13123 gfc_class_set_vptr (&block, to_se.expr, from_se.expr);
13124 if (from_is_class)
13125 gfc_reset_vptr (&block, from_expr);
13126 if (UNLIMITED_POLY (to_expr))
13128 tree to_len = gfc_class_len_get (to_se.class_container);
13129 tmp = from_expr->ts.type == BT_CHARACTER && from_se.string_length
13130 ? from_se.string_length
13131 : size_zero_node;
13132 gfc_add_modify_loc (input_location, &block, to_len,
13133 fold_convert (TREE_TYPE (to_len), tmp));
13137 if (from_is_scalar)
13139 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
13141 gfc_add_modify_loc (input_location, &block, to_se.string_length,
13142 fold_convert (TREE_TYPE (to_se.string_length),
13143 from_se.string_length));
13144 if (from_expr->ts.deferred)
13145 gfc_add_modify_loc (
13146 input_location, &block, from_se.string_length,
13147 build_int_cst (TREE_TYPE (from_se.string_length), 0));
13149 if (UNLIMITED_POLY (from_expr))
13150 gfc_reset_len (&block, from_expr);
13152 return gfc_finish_block (&block);
13155 gfc_init_se (&to_se, NULL);
13156 gfc_init_se (&from_se, NULL);
13159 /* Deallocate "to". */
13160 if (from_expr->rank == 0)
13162 to_se.want_coarray = 1;
13163 from_se.want_coarray = 1;
13165 gfc_conv_expr_descriptor (&to_se, to_expr);
13166 gfc_conv_expr_descriptor (&from_se, from_expr);
13168 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
13169 is an image control "statement", cf. IR F08/0040 in 12-006A. */
13170 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
13172 tree cond;
13174 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
13175 NULL_TREE, NULL_TREE, true, to_expr,
13176 GFC_CAF_COARRAY_DEALLOCATE_ONLY);
13177 gfc_add_expr_to_block (&block, tmp);
13179 tmp = gfc_conv_descriptor_data_get (to_se.expr);
13180 cond = fold_build2_loc (input_location, EQ_EXPR,
13181 logical_type_node, tmp,
13182 fold_convert (TREE_TYPE (tmp),
13183 null_pointer_node));
13184 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
13185 3, null_pointer_node, null_pointer_node,
13186 integer_zero_node);
13188 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
13189 tmp, build_empty_stmt (input_location));
13190 gfc_add_expr_to_block (&block, tmp);
13192 else
13194 if (to_expr->ts.type == BT_DERIVED
13195 && to_expr->ts.u.derived->attr.alloc_comp)
13197 tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
13198 to_se.expr, to_expr->rank);
13199 gfc_add_expr_to_block (&block, tmp);
13202 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
13203 NULL_TREE, NULL_TREE, true, to_expr,
13204 GFC_CAF_COARRAY_NOCOARRAY);
13205 gfc_add_expr_to_block (&block, tmp);
13208 /* Copy the array descriptor data. */
13209 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
13211 /* Set "from" to NULL. */
13212 tmp = gfc_conv_descriptor_data_get (from_se.expr);
13213 gfc_add_modify_loc (input_location, &block, tmp,
13214 fold_convert (TREE_TYPE (tmp), null_pointer_node));
13217 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
13219 gfc_add_modify_loc (input_location, &block, to_se.string_length,
13220 fold_convert (TREE_TYPE (to_se.string_length),
13221 from_se.string_length));
13222 if (from_expr->ts.deferred)
13223 gfc_add_modify_loc (input_location, &block, from_se.string_length,
13224 build_int_cst (TREE_TYPE (from_se.string_length), 0));
13227 return gfc_finish_block (&block);
13231 tree
13232 gfc_conv_intrinsic_subroutine (gfc_code *code)
13234 tree res;
13236 gcc_assert (code->resolved_isym);
13238 switch (code->resolved_isym->id)
13240 case GFC_ISYM_MOVE_ALLOC:
13241 res = conv_intrinsic_move_alloc (code);
13242 break;
13244 case GFC_ISYM_ATOMIC_CAS:
13245 res = conv_intrinsic_atomic_cas (code);
13246 break;
13248 case GFC_ISYM_ATOMIC_ADD:
13249 case GFC_ISYM_ATOMIC_AND:
13250 case GFC_ISYM_ATOMIC_DEF:
13251 case GFC_ISYM_ATOMIC_OR:
13252 case GFC_ISYM_ATOMIC_XOR:
13253 case GFC_ISYM_ATOMIC_FETCH_ADD:
13254 case GFC_ISYM_ATOMIC_FETCH_AND:
13255 case GFC_ISYM_ATOMIC_FETCH_OR:
13256 case GFC_ISYM_ATOMIC_FETCH_XOR:
13257 res = conv_intrinsic_atomic_op (code);
13258 break;
13260 case GFC_ISYM_ATOMIC_REF:
13261 res = conv_intrinsic_atomic_ref (code);
13262 break;
13264 case GFC_ISYM_EVENT_QUERY:
13265 res = conv_intrinsic_event_query (code);
13266 break;
13268 case GFC_ISYM_C_F_POINTER:
13269 case GFC_ISYM_C_F_PROCPOINTER:
13270 res = conv_isocbinding_subroutine (code);
13271 break;
13273 case GFC_ISYM_CAF_SEND:
13274 res = conv_caf_send (code);
13275 break;
13277 case GFC_ISYM_CO_BROADCAST:
13278 case GFC_ISYM_CO_MIN:
13279 case GFC_ISYM_CO_MAX:
13280 case GFC_ISYM_CO_REDUCE:
13281 case GFC_ISYM_CO_SUM:
13282 res = conv_co_collective (code);
13283 break;
13285 case GFC_ISYM_FREE:
13286 res = conv_intrinsic_free (code);
13287 break;
13289 case GFC_ISYM_RANDOM_INIT:
13290 res = conv_intrinsic_random_init (code);
13291 break;
13293 case GFC_ISYM_KILL:
13294 res = conv_intrinsic_kill_sub (code);
13295 break;
13297 case GFC_ISYM_MVBITS:
13298 res = NULL_TREE;
13299 break;
13301 case GFC_ISYM_SYSTEM_CLOCK:
13302 res = conv_intrinsic_system_clock (code);
13303 break;
13305 default:
13306 res = NULL_TREE;
13307 break;
13310 return res;
13313 #include "gt-fortran-trans-intrinsic.h"