PR rtl-optimization/82913
[official-gcc.git] / gcc / fortran / trans-intrinsic.c
blobed4496c845df88753fd4e592677c42a7fcb134b7
1 /* Intrinsic translation
2 Copyright (C) 2002-2017 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* trans-intrinsic.c-- generate GENERIC trees for calls to intrinsics. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "memmodel.h"
28 #include "tm.h" /* For UNITS_PER_WORD. */
29 #include "tree.h"
30 #include "gfortran.h"
31 #include "trans.h"
32 #include "stringpool.h"
33 #include "fold-const.h"
34 #include "tree-nested.h"
35 #include "stor-layout.h"
36 #include "toplev.h" /* For rest_of_decl_compilation. */
37 #include "arith.h"
38 #include "trans-const.h"
39 #include "trans-types.h"
40 #include "trans-array.h"
41 #include "dependency.h" /* For CAF array alias analysis. */
42 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
44 /* This maps Fortran intrinsic math functions to external library or GCC
45 builtin functions. */
46 typedef struct GTY(()) gfc_intrinsic_map_t {
47 /* The explicit enum is required to work around inadequacies in the
48 garbage collection/gengtype parsing mechanism. */
49 enum gfc_isym_id id;
51 /* Enum value from the "language-independent", aka C-centric, part
52 of gcc, or END_BUILTINS of no such value set. */
53 enum built_in_function float_built_in;
54 enum built_in_function double_built_in;
55 enum built_in_function long_double_built_in;
56 enum built_in_function complex_float_built_in;
57 enum built_in_function complex_double_built_in;
58 enum built_in_function complex_long_double_built_in;
60 /* True if the naming pattern is to prepend "c" for complex and
61 append "f" for kind=4. False if the naming pattern is to
62 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
63 bool libm_name;
65 /* True if a complex version of the function exists. */
66 bool complex_available;
68 /* True if the function should be marked const. */
69 bool is_constant;
71 /* The base library name of this function. */
72 const char *name;
74 /* Cache decls created for the various operand types. */
75 tree real4_decl;
76 tree real8_decl;
77 tree real10_decl;
78 tree real16_decl;
79 tree complex4_decl;
80 tree complex8_decl;
81 tree complex10_decl;
82 tree complex16_decl;
84 gfc_intrinsic_map_t;
86 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
87 defines complex variants of all of the entries in mathbuiltins.def
88 except for atan2. */
89 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
90 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
91 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
92 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
93 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
95 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
96 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
97 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
98 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
99 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
101 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
102 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
103 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
104 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
105 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
107 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
108 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
109 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
110 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
111 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
113 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
115 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
116 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
117 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
118 #include "mathbuiltins.def"
120 /* Functions in libgfortran. */
121 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
123 /* End the list. */
124 LIB_FUNCTION (NONE, NULL, false)
127 #undef OTHER_BUILTIN
128 #undef LIB_FUNCTION
129 #undef DEFINE_MATH_BUILTIN
130 #undef DEFINE_MATH_BUILTIN_C
133 enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
136 /* Find the correct variant of a given builtin from its argument. */
137 static tree
138 builtin_decl_for_precision (enum built_in_function base_built_in,
139 int precision)
141 enum built_in_function i = END_BUILTINS;
143 gfc_intrinsic_map_t *m;
144 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
147 if (precision == TYPE_PRECISION (float_type_node))
148 i = m->float_built_in;
149 else if (precision == TYPE_PRECISION (double_type_node))
150 i = m->double_built_in;
151 else if (precision == TYPE_PRECISION (long_double_type_node))
152 i = m->long_double_built_in;
153 else if (precision == TYPE_PRECISION (gfc_float128_type_node))
155 /* Special treatment, because it is not exactly a built-in, but
156 a library function. */
157 return m->real16_decl;
160 return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
164 tree
165 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
166 int kind)
168 int i = gfc_validate_kind (BT_REAL, kind, false);
170 if (gfc_real_kinds[i].c_float128)
172 /* For __float128, the story is a bit different, because we return
173 a decl to a library function rather than a built-in. */
174 gfc_intrinsic_map_t *m;
175 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
178 return m->real16_decl;
181 return builtin_decl_for_precision (double_built_in,
182 gfc_real_kinds[i].mode_precision);
186 /* Evaluate the arguments to an intrinsic function. The value
187 of NARGS may be less than the actual number of arguments in EXPR
188 to allow optional "KIND" arguments that are not included in the
189 generated code to be ignored. */
191 static void
192 gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
193 tree *argarray, int nargs)
195 gfc_actual_arglist *actual;
196 gfc_expr *e;
197 gfc_intrinsic_arg *formal;
198 gfc_se argse;
199 int curr_arg;
201 formal = expr->value.function.isym->formal;
202 actual = expr->value.function.actual;
204 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
205 actual = actual->next,
206 formal = formal ? formal->next : NULL)
208 gcc_assert (actual);
209 e = actual->expr;
210 /* Skip omitted optional arguments. */
211 if (!e)
213 --curr_arg;
214 continue;
217 /* Evaluate the parameter. This will substitute scalarized
218 references automatically. */
219 gfc_init_se (&argse, se);
221 if (e->ts.type == BT_CHARACTER)
223 gfc_conv_expr (&argse, e);
224 gfc_conv_string_parameter (&argse);
225 argarray[curr_arg++] = argse.string_length;
226 gcc_assert (curr_arg < nargs);
228 else
229 gfc_conv_expr_val (&argse, e);
231 /* If an optional argument is itself an optional dummy argument,
232 check its presence and substitute a null if absent. */
233 if (e->expr_type == EXPR_VARIABLE
234 && e->symtree->n.sym->attr.optional
235 && formal
236 && formal->optional)
237 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
239 gfc_add_block_to_block (&se->pre, &argse.pre);
240 gfc_add_block_to_block (&se->post, &argse.post);
241 argarray[curr_arg] = argse.expr;
245 /* Count the number of actual arguments to the intrinsic function EXPR
246 including any "hidden" string length arguments. */
248 static unsigned int
249 gfc_intrinsic_argument_list_length (gfc_expr *expr)
251 int n = 0;
252 gfc_actual_arglist *actual;
254 for (actual = expr->value.function.actual; actual; actual = actual->next)
256 if (!actual->expr)
257 continue;
259 if (actual->expr->ts.type == BT_CHARACTER)
260 n += 2;
261 else
262 n++;
265 return n;
269 /* Conversions between different types are output by the frontend as
270 intrinsic functions. We implement these directly with inline code. */
272 static void
273 gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
275 tree type;
276 tree *args;
277 int nargs;
279 nargs = gfc_intrinsic_argument_list_length (expr);
280 args = XALLOCAVEC (tree, nargs);
282 /* Evaluate all the arguments passed. Whilst we're only interested in the
283 first one here, there are other parts of the front-end that assume this
284 and will trigger an ICE if it's not the case. */
285 type = gfc_typenode_for_spec (&expr->ts);
286 gcc_assert (expr->value.function.actual->expr);
287 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
289 /* Conversion between character kinds involves a call to a library
290 function. */
291 if (expr->ts.type == BT_CHARACTER)
293 tree fndecl, var, addr, tmp;
295 if (expr->ts.kind == 1
296 && expr->value.function.actual->expr->ts.kind == 4)
297 fndecl = gfor_fndecl_convert_char4_to_char1;
298 else if (expr->ts.kind == 4
299 && expr->value.function.actual->expr->ts.kind == 1)
300 fndecl = gfor_fndecl_convert_char1_to_char4;
301 else
302 gcc_unreachable ();
304 /* Create the variable storing the converted value. */
305 type = gfc_get_pchar_type (expr->ts.kind);
306 var = gfc_create_var (type, "str");
307 addr = gfc_build_addr_expr (build_pointer_type (type), var);
309 /* Call the library function that will perform the conversion. */
310 gcc_assert (nargs >= 2);
311 tmp = build_call_expr_loc (input_location,
312 fndecl, 3, addr, args[0], args[1]);
313 gfc_add_expr_to_block (&se->pre, tmp);
315 /* Free the temporary afterwards. */
316 tmp = gfc_call_free (var);
317 gfc_add_expr_to_block (&se->post, tmp);
319 se->expr = var;
320 se->string_length = args[0];
322 return;
325 /* Conversion from complex to non-complex involves taking the real
326 component of the value. */
327 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
328 && expr->ts.type != BT_COMPLEX)
330 tree artype;
332 artype = TREE_TYPE (TREE_TYPE (args[0]));
333 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
334 args[0]);
337 se->expr = convert (type, args[0]);
340 /* This is needed because the gcc backend only implements
341 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
342 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
343 Similarly for CEILING. */
345 static tree
346 build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
348 tree tmp;
349 tree cond;
350 tree argtype;
351 tree intval;
353 argtype = TREE_TYPE (arg);
354 arg = gfc_evaluate_now (arg, pblock);
356 intval = convert (type, arg);
357 intval = gfc_evaluate_now (intval, pblock);
359 tmp = convert (argtype, intval);
360 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
361 logical_type_node, tmp, arg);
363 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
364 intval, build_int_cst (type, 1));
365 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
366 return tmp;
370 /* Round to nearest integer, away from zero. */
372 static tree
373 build_round_expr (tree arg, tree restype)
375 tree argtype;
376 tree fn;
377 int argprec, resprec;
379 argtype = TREE_TYPE (arg);
380 argprec = TYPE_PRECISION (argtype);
381 resprec = TYPE_PRECISION (restype);
383 /* Depending on the type of the result, choose the int intrinsic
384 (iround, available only as a builtin, therefore cannot use it for
385 __float128), long int intrinsic (lround family) or long long
386 intrinsic (llround). We might also need to convert the result
387 afterwards. */
388 if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
389 fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
390 else if (resprec <= LONG_TYPE_SIZE)
391 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
392 else if (resprec <= LONG_LONG_TYPE_SIZE)
393 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
394 else
395 gcc_unreachable ();
397 return fold_convert (restype, build_call_expr_loc (input_location,
398 fn, 1, arg));
402 /* Convert a real to an integer using a specific rounding mode.
403 Ideally we would just build the corresponding GENERIC node,
404 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
406 static tree
407 build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
408 enum rounding_mode op)
410 switch (op)
412 case RND_FLOOR:
413 return build_fixbound_expr (pblock, arg, type, 0);
415 case RND_CEIL:
416 return build_fixbound_expr (pblock, arg, type, 1);
418 case RND_ROUND:
419 return build_round_expr (arg, type);
421 case RND_TRUNC:
422 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
424 default:
425 gcc_unreachable ();
430 /* Round a real value using the specified rounding mode.
431 We use a temporary integer of that same kind size as the result.
432 Values larger than those that can be represented by this kind are
433 unchanged, as they will not be accurate enough to represent the
434 rounding.
435 huge = HUGE (KIND (a))
436 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
439 static void
440 gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
442 tree type;
443 tree itype;
444 tree arg[2];
445 tree tmp;
446 tree cond;
447 tree decl;
448 mpfr_t huge;
449 int n, nargs;
450 int kind;
452 kind = expr->ts.kind;
453 nargs = gfc_intrinsic_argument_list_length (expr);
455 decl = NULL_TREE;
456 /* We have builtin functions for some cases. */
457 switch (op)
459 case RND_ROUND:
460 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
461 break;
463 case RND_TRUNC:
464 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
465 break;
467 default:
468 gcc_unreachable ();
471 /* Evaluate the argument. */
472 gcc_assert (expr->value.function.actual->expr);
473 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
475 /* Use a builtin function if one exists. */
476 if (decl != NULL_TREE)
478 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
479 return;
482 /* This code is probably redundant, but we'll keep it lying around just
483 in case. */
484 type = gfc_typenode_for_spec (&expr->ts);
485 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
487 /* Test if the value is too large to handle sensibly. */
488 gfc_set_model_kind (kind);
489 mpfr_init (huge);
490 n = gfc_validate_kind (BT_INTEGER, kind, false);
491 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
492 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
493 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, arg[0],
494 tmp);
496 mpfr_neg (huge, huge, GFC_RND_MODE);
497 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
498 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, arg[0],
499 tmp);
500 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node,
501 cond, tmp);
502 itype = gfc_get_int_type (kind);
504 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
505 tmp = convert (type, tmp);
506 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
507 arg[0]);
508 mpfr_clear (huge);
512 /* Convert to an integer using the specified rounding mode. */
514 static void
515 gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
517 tree type;
518 tree *args;
519 int nargs;
521 nargs = gfc_intrinsic_argument_list_length (expr);
522 args = XALLOCAVEC (tree, nargs);
524 /* Evaluate the argument, we process all arguments even though we only
525 use the first one for code generation purposes. */
526 type = gfc_typenode_for_spec (&expr->ts);
527 gcc_assert (expr->value.function.actual->expr);
528 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
530 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
532 /* Conversion to a different integer kind. */
533 se->expr = convert (type, args[0]);
535 else
537 /* Conversion from complex to non-complex involves taking the real
538 component of the value. */
539 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
540 && expr->ts.type != BT_COMPLEX)
542 tree artype;
544 artype = TREE_TYPE (TREE_TYPE (args[0]));
545 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
546 args[0]);
549 se->expr = build_fix_expr (&se->pre, args[0], type, op);
554 /* Get the imaginary component of a value. */
556 static void
557 gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
559 tree arg;
561 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
562 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
563 TREE_TYPE (TREE_TYPE (arg)), arg);
567 /* Get the complex conjugate of a value. */
569 static void
570 gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
572 tree arg;
574 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
575 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
580 static tree
581 define_quad_builtin (const char *name, tree type, bool is_const)
583 tree fndecl;
584 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
585 type);
587 /* Mark the decl as external. */
588 DECL_EXTERNAL (fndecl) = 1;
589 TREE_PUBLIC (fndecl) = 1;
591 /* Mark it __attribute__((const)). */
592 TREE_READONLY (fndecl) = is_const;
594 rest_of_decl_compilation (fndecl, 1, 0);
596 return fndecl;
601 /* Initialize function decls for library functions. The external functions
602 are created as required. Builtin functions are added here. */
604 void
605 gfc_build_intrinsic_lib_fndecls (void)
607 gfc_intrinsic_map_t *m;
608 tree quad_decls[END_BUILTINS + 1];
610 if (gfc_real16_is_float128)
612 /* If we have soft-float types, we create the decls for their
613 C99-like library functions. For now, we only handle __float128
614 q-suffixed functions. */
616 tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
617 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
619 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
621 type = gfc_float128_type_node;
622 complex_type = gfc_complex_float128_type_node;
623 /* type (*) (type) */
624 func_1 = build_function_type_list (type, type, NULL_TREE);
625 /* int (*) (type) */
626 func_iround = build_function_type_list (integer_type_node,
627 type, NULL_TREE);
628 /* long (*) (type) */
629 func_lround = build_function_type_list (long_integer_type_node,
630 type, NULL_TREE);
631 /* long long (*) (type) */
632 func_llround = build_function_type_list (long_long_integer_type_node,
633 type, NULL_TREE);
634 /* type (*) (type, type) */
635 func_2 = build_function_type_list (type, type, type, NULL_TREE);
636 /* type (*) (type, &int) */
637 func_frexp
638 = build_function_type_list (type,
639 type,
640 build_pointer_type (integer_type_node),
641 NULL_TREE);
642 /* type (*) (type, int) */
643 func_scalbn = build_function_type_list (type,
644 type, integer_type_node, NULL_TREE);
645 /* type (*) (complex type) */
646 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
647 /* complex type (*) (complex type, complex type) */
648 func_cpow
649 = build_function_type_list (complex_type,
650 complex_type, complex_type, NULL_TREE);
652 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
653 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
654 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
656 /* Only these built-ins are actually needed here. These are used directly
657 from the code, when calling builtin_decl_for_precision() or
658 builtin_decl_for_float_type(). The others are all constructed by
659 gfc_get_intrinsic_lib_fndecl(). */
660 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
661 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
663 #include "mathbuiltins.def"
665 #undef OTHER_BUILTIN
666 #undef LIB_FUNCTION
667 #undef DEFINE_MATH_BUILTIN
668 #undef DEFINE_MATH_BUILTIN_C
670 /* There is one built-in we defined manually, because it gets called
671 with builtin_decl_for_precision() or builtin_decl_for_float_type()
672 even though it is not an OTHER_BUILTIN: it is SQRT. */
673 quad_decls[BUILT_IN_SQRT] = define_quad_builtin ("sqrtq", func_1, true);
677 /* Add GCC builtin functions. */
678 for (m = gfc_intrinsic_map;
679 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
681 if (m->float_built_in != END_BUILTINS)
682 m->real4_decl = builtin_decl_explicit (m->float_built_in);
683 if (m->complex_float_built_in != END_BUILTINS)
684 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
685 if (m->double_built_in != END_BUILTINS)
686 m->real8_decl = builtin_decl_explicit (m->double_built_in);
687 if (m->complex_double_built_in != END_BUILTINS)
688 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
690 /* If real(kind=10) exists, it is always long double. */
691 if (m->long_double_built_in != END_BUILTINS)
692 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
693 if (m->complex_long_double_built_in != END_BUILTINS)
694 m->complex10_decl
695 = builtin_decl_explicit (m->complex_long_double_built_in);
697 if (!gfc_real16_is_float128)
699 if (m->long_double_built_in != END_BUILTINS)
700 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
701 if (m->complex_long_double_built_in != END_BUILTINS)
702 m->complex16_decl
703 = builtin_decl_explicit (m->complex_long_double_built_in);
705 else if (quad_decls[m->double_built_in] != NULL_TREE)
707 /* Quad-precision function calls are constructed when first
708 needed by builtin_decl_for_precision(), except for those
709 that will be used directly (define by OTHER_BUILTIN). */
710 m->real16_decl = quad_decls[m->double_built_in];
712 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
714 /* Same thing for the complex ones. */
715 m->complex16_decl = quad_decls[m->double_built_in];
721 /* Create a fndecl for a simple intrinsic library function. */
723 static tree
724 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
726 tree type;
727 vec<tree, va_gc> *argtypes;
728 tree fndecl;
729 gfc_actual_arglist *actual;
730 tree *pdecl;
731 gfc_typespec *ts;
732 char name[GFC_MAX_SYMBOL_LEN + 3];
734 ts = &expr->ts;
735 if (ts->type == BT_REAL)
737 switch (ts->kind)
739 case 4:
740 pdecl = &m->real4_decl;
741 break;
742 case 8:
743 pdecl = &m->real8_decl;
744 break;
745 case 10:
746 pdecl = &m->real10_decl;
747 break;
748 case 16:
749 pdecl = &m->real16_decl;
750 break;
751 default:
752 gcc_unreachable ();
755 else if (ts->type == BT_COMPLEX)
757 gcc_assert (m->complex_available);
759 switch (ts->kind)
761 case 4:
762 pdecl = &m->complex4_decl;
763 break;
764 case 8:
765 pdecl = &m->complex8_decl;
766 break;
767 case 10:
768 pdecl = &m->complex10_decl;
769 break;
770 case 16:
771 pdecl = &m->complex16_decl;
772 break;
773 default:
774 gcc_unreachable ();
777 else
778 gcc_unreachable ();
780 if (*pdecl)
781 return *pdecl;
783 if (m->libm_name)
785 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
786 if (gfc_real_kinds[n].c_float)
787 snprintf (name, sizeof (name), "%s%s%s",
788 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
789 else if (gfc_real_kinds[n].c_double)
790 snprintf (name, sizeof (name), "%s%s",
791 ts->type == BT_COMPLEX ? "c" : "", m->name);
792 else if (gfc_real_kinds[n].c_long_double)
793 snprintf (name, sizeof (name), "%s%s%s",
794 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
795 else if (gfc_real_kinds[n].c_float128)
796 snprintf (name, sizeof (name), "%s%s%s",
797 ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
798 else
799 gcc_unreachable ();
801 else
803 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
804 ts->type == BT_COMPLEX ? 'c' : 'r',
805 ts->kind);
808 argtypes = NULL;
809 for (actual = expr->value.function.actual; actual; actual = actual->next)
811 type = gfc_typenode_for_spec (&actual->expr->ts);
812 vec_safe_push (argtypes, type);
814 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
815 fndecl = build_decl (input_location,
816 FUNCTION_DECL, get_identifier (name), type);
818 /* Mark the decl as external. */
819 DECL_EXTERNAL (fndecl) = 1;
820 TREE_PUBLIC (fndecl) = 1;
822 /* Mark it __attribute__((const)), if possible. */
823 TREE_READONLY (fndecl) = m->is_constant;
825 rest_of_decl_compilation (fndecl, 1, 0);
827 (*pdecl) = fndecl;
828 return fndecl;
832 /* Convert an intrinsic function into an external or builtin call. */
834 static void
835 gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
837 gfc_intrinsic_map_t *m;
838 tree fndecl;
839 tree rettype;
840 tree *args;
841 unsigned int num_args;
842 gfc_isym_id id;
844 id = expr->value.function.isym->id;
845 /* Find the entry for this function. */
846 for (m = gfc_intrinsic_map;
847 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
849 if (id == m->id)
850 break;
853 if (m->id == GFC_ISYM_NONE)
855 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
856 expr->value.function.name, id);
859 /* Get the decl and generate the call. */
860 num_args = gfc_intrinsic_argument_list_length (expr);
861 args = XALLOCAVEC (tree, num_args);
863 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
864 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
865 rettype = TREE_TYPE (TREE_TYPE (fndecl));
867 fndecl = build_addr (fndecl);
868 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
872 /* If bounds-checking is enabled, create code to verify at runtime that the
873 string lengths for both expressions are the same (needed for e.g. MERGE).
874 If bounds-checking is not enabled, does nothing. */
876 void
877 gfc_trans_same_strlen_check (const char* intr_name, locus* where,
878 tree a, tree b, stmtblock_t* target)
880 tree cond;
881 tree name;
883 /* If bounds-checking is disabled, do nothing. */
884 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
885 return;
887 /* Compare the two string lengths. */
888 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, a, b);
890 /* Output the runtime-check. */
891 name = gfc_build_cstring_const (intr_name);
892 name = gfc_build_addr_expr (pchar_type_node, name);
893 gfc_trans_runtime_check (true, false, cond, target, where,
894 "Unequal character lengths (%ld/%ld) in %s",
895 fold_convert (long_integer_type_node, a),
896 fold_convert (long_integer_type_node, b), name);
900 /* The EXPONENT(X) intrinsic function is translated into
901 int ret;
902 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
903 so that if X is a NaN or infinity, the result is HUGE(0).
906 static void
907 gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
909 tree arg, type, res, tmp, frexp, cond, huge;
910 int i;
912 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
913 expr->value.function.actual->expr->ts.kind);
915 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
916 arg = gfc_evaluate_now (arg, &se->pre);
918 i = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
919 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_c_int_kind);
920 cond = build_call_expr_loc (input_location,
921 builtin_decl_explicit (BUILT_IN_ISFINITE),
922 1, arg);
924 res = gfc_create_var (integer_type_node, NULL);
925 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
926 gfc_build_addr_expr (NULL_TREE, res));
927 tmp = fold_build2_loc (input_location, COMPOUND_EXPR, integer_type_node,
928 tmp, res);
929 se->expr = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
930 cond, tmp, huge);
932 type = gfc_typenode_for_spec (&expr->ts);
933 se->expr = fold_convert (type, se->expr);
937 /* Fill in the following structure
938 struct caf_vector_t {
939 size_t nvec; // size of the vector
940 union {
941 struct {
942 void *vector;
943 int kind;
944 } v;
945 struct {
946 ptrdiff_t lower_bound;
947 ptrdiff_t upper_bound;
948 ptrdiff_t stride;
949 } triplet;
950 } u;
951 } */
953 static void
954 conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
955 tree lower, tree upper, tree stride,
956 tree vector, int kind, tree nvec)
958 tree field, type, tmp;
960 desc = gfc_build_array_ref (desc, gfc_rank_cst[i], NULL_TREE);
961 type = TREE_TYPE (desc);
963 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
964 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
965 desc, field, NULL_TREE);
966 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), nvec));
968 /* Access union. */
969 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
970 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
971 desc, field, NULL_TREE);
972 type = TREE_TYPE (desc);
974 /* Access the inner struct. */
975 field = gfc_advance_chain (TYPE_FIELDS (type), vector != NULL_TREE ? 0 : 1);
976 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
977 desc, field, NULL_TREE);
978 type = TREE_TYPE (desc);
980 if (vector != NULL_TREE)
982 /* Set vector and kind. */
983 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
984 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
985 desc, field, NULL_TREE);
986 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), vector));
987 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
988 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
989 desc, field, NULL_TREE);
990 gfc_add_modify (block, tmp, build_int_cst (integer_type_node, kind));
992 else
994 /* Set dim.lower/upper/stride. */
995 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
996 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
997 desc, field, NULL_TREE);
998 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), lower));
1000 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1001 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1002 desc, field, NULL_TREE);
1003 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), upper));
1005 field = gfc_advance_chain (TYPE_FIELDS (type), 2);
1006 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1007 desc, field, NULL_TREE);
1008 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), stride));
1013 static tree
1014 conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
1016 gfc_se argse;
1017 tree var, lower, upper = NULL_TREE, stride = NULL_TREE, vector, nvec;
1018 tree lbound, ubound, tmp;
1019 int i;
1021 var = gfc_create_var (gfc_get_caf_vector_type (ar->dimen), "vector");
1023 for (i = 0; i < ar->dimen; i++)
1024 switch (ar->dimen_type[i])
1026 case DIMEN_RANGE:
1027 if (ar->end[i])
1029 gfc_init_se (&argse, NULL);
1030 gfc_conv_expr (&argse, ar->end[i]);
1031 gfc_add_block_to_block (block, &argse.pre);
1032 upper = gfc_evaluate_now (argse.expr, block);
1034 else
1035 upper = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1036 if (ar->stride[i])
1038 gfc_init_se (&argse, NULL);
1039 gfc_conv_expr (&argse, ar->stride[i]);
1040 gfc_add_block_to_block (block, &argse.pre);
1041 stride = gfc_evaluate_now (argse.expr, block);
1043 else
1044 stride = gfc_index_one_node;
1046 /* Fall through. */
1047 case DIMEN_ELEMENT:
1048 if (ar->start[i])
1050 gfc_init_se (&argse, NULL);
1051 gfc_conv_expr (&argse, ar->start[i]);
1052 gfc_add_block_to_block (block, &argse.pre);
1053 lower = gfc_evaluate_now (argse.expr, block);
1055 else
1056 lower = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1057 if (ar->dimen_type[i] == DIMEN_ELEMENT)
1059 upper = lower;
1060 stride = gfc_index_one_node;
1062 vector = NULL_TREE;
1063 nvec = size_zero_node;
1064 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1065 vector, 0, nvec);
1066 break;
1068 case DIMEN_VECTOR:
1069 gfc_init_se (&argse, NULL);
1070 argse.descriptor_only = 1;
1071 gfc_conv_expr_descriptor (&argse, ar->start[i]);
1072 gfc_add_block_to_block (block, &argse.pre);
1073 vector = argse.expr;
1074 lbound = gfc_conv_descriptor_lbound_get (vector, gfc_rank_cst[0]);
1075 ubound = gfc_conv_descriptor_ubound_get (vector, gfc_rank_cst[0]);
1076 nvec = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1077 tmp = gfc_conv_descriptor_stride_get (vector, gfc_rank_cst[0]);
1078 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1079 TREE_TYPE (nvec), nvec, tmp);
1080 lower = gfc_index_zero_node;
1081 upper = gfc_index_zero_node;
1082 stride = gfc_index_zero_node;
1083 vector = gfc_conv_descriptor_data_get (vector);
1084 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1085 vector, ar->start[i]->ts.kind, nvec);
1086 break;
1087 default:
1088 gcc_unreachable();
1090 return gfc_build_addr_expr (NULL_TREE, var);
1094 static tree
1095 compute_component_offset (tree field, tree type)
1097 tree tmp;
1098 if (DECL_FIELD_BIT_OFFSET (field) != NULL_TREE
1099 && !integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
1101 tmp = fold_build2 (TRUNC_DIV_EXPR, type,
1102 DECL_FIELD_BIT_OFFSET (field),
1103 bitsize_unit_node);
1104 return fold_build2 (PLUS_EXPR, type, DECL_FIELD_OFFSET (field), tmp);
1106 else
1107 return DECL_FIELD_OFFSET (field);
1111 static tree
1112 conv_expr_ref_to_caf_ref (stmtblock_t *block, gfc_expr *expr)
1114 gfc_ref *ref = expr->ref, *last_comp_ref;
1115 tree caf_ref = NULL_TREE, prev_caf_ref = NULL_TREE, reference_type, tmp, tmp2,
1116 field, last_type, inner_struct, mode, mode_rhs, dim_array, dim, dim_type,
1117 start, end, stride, vector, nvec;
1118 gfc_se se;
1119 bool ref_static_array = false;
1120 tree last_component_ref_tree = NULL_TREE;
1121 int i, last_type_n;
1123 if (expr->symtree)
1125 last_component_ref_tree = expr->symtree->n.sym->backend_decl;
1126 ref_static_array = !expr->symtree->n.sym->attr.allocatable
1127 && !expr->symtree->n.sym->attr.pointer;
1130 /* Prevent uninit-warning. */
1131 reference_type = NULL_TREE;
1133 /* Skip refs upto the first coarray-ref. */
1134 last_comp_ref = NULL;
1135 while (ref && (ref->type != REF_ARRAY || ref->u.ar.codimen == 0))
1137 /* Remember the type of components skipped. */
1138 if (ref->type == REF_COMPONENT)
1139 last_comp_ref = ref;
1140 ref = ref->next;
1142 /* When a component was skipped, get the type information of the last
1143 component ref, else get the type from the symbol. */
1144 if (last_comp_ref)
1146 last_type = gfc_typenode_for_spec (&last_comp_ref->u.c.component->ts);
1147 last_type_n = last_comp_ref->u.c.component->ts.type;
1149 else
1151 last_type = gfc_typenode_for_spec (&expr->symtree->n.sym->ts);
1152 last_type_n = expr->symtree->n.sym->ts.type;
1155 while (ref)
1157 if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0
1158 && ref->u.ar.dimen == 0)
1160 /* Skip pure coindexes. */
1161 ref = ref->next;
1162 continue;
1164 tmp = gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
1165 reference_type = TREE_TYPE (tmp);
1167 if (caf_ref == NULL_TREE)
1168 caf_ref = tmp;
1170 /* Construct the chain of refs. */
1171 if (prev_caf_ref != NULL_TREE)
1173 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1174 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1175 TREE_TYPE (field), prev_caf_ref, field,
1176 NULL_TREE);
1177 gfc_add_modify (block, tmp2, gfc_build_addr_expr (TREE_TYPE (field),
1178 tmp));
1180 prev_caf_ref = tmp;
1182 switch (ref->type)
1184 case REF_COMPONENT:
1185 last_type = gfc_typenode_for_spec (&ref->u.c.component->ts);
1186 last_type_n = ref->u.c.component->ts.type;
1187 /* Set the type of the ref. */
1188 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1189 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1190 TREE_TYPE (field), prev_caf_ref, field,
1191 NULL_TREE);
1192 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1193 GFC_CAF_REF_COMPONENT));
1195 /* Ref the c in union u. */
1196 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1197 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1198 TREE_TYPE (field), prev_caf_ref, field,
1199 NULL_TREE);
1200 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 0);
1201 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1202 TREE_TYPE (field), tmp, field,
1203 NULL_TREE);
1205 /* Set the offset. */
1206 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1207 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1208 TREE_TYPE (field), inner_struct, field,
1209 NULL_TREE);
1210 /* Computing the offset is somewhat harder. The bit_offset has to be
1211 taken into account. When the bit_offset in the field_decl is non-
1212 null, divide it by the bitsize_unit and add it to the regular
1213 offset. */
1214 tmp2 = compute_component_offset (ref->u.c.component->backend_decl,
1215 TREE_TYPE (tmp));
1216 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1218 /* Set caf_token_offset. */
1219 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 1);
1220 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1221 TREE_TYPE (field), inner_struct, field,
1222 NULL_TREE);
1223 if ((ref->u.c.component->attr.allocatable
1224 || ref->u.c.component->attr.pointer)
1225 && ref->u.c.component->attr.dimension)
1227 tree arr_desc_token_offset;
1228 /* Get the token field from the descriptor. */
1229 arr_desc_token_offset = TREE_OPERAND (
1230 gfc_conv_descriptor_token (ref->u.c.component->backend_decl), 1);
1231 arr_desc_token_offset
1232 = compute_component_offset (arr_desc_token_offset,
1233 TREE_TYPE (tmp));
1234 tmp2 = fold_build2_loc (input_location, PLUS_EXPR,
1235 TREE_TYPE (tmp2), tmp2,
1236 arr_desc_token_offset);
1238 else if (ref->u.c.component->caf_token)
1239 tmp2 = compute_component_offset (ref->u.c.component->caf_token,
1240 TREE_TYPE (tmp));
1241 else
1242 tmp2 = integer_zero_node;
1243 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1245 /* Remember whether this ref was to a non-allocatable/non-pointer
1246 component so the next array ref can be tailored correctly. */
1247 ref_static_array = !ref->u.c.component->attr.allocatable
1248 && !ref->u.c.component->attr.pointer;
1249 last_component_ref_tree = ref_static_array
1250 ? ref->u.c.component->backend_decl : NULL_TREE;
1251 break;
1252 case REF_ARRAY:
1253 if (ref_static_array && ref->u.ar.as->type == AS_DEFERRED)
1254 ref_static_array = false;
1255 /* Set the type of the ref. */
1256 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1257 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1258 TREE_TYPE (field), prev_caf_ref, field,
1259 NULL_TREE);
1260 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1261 ref_static_array
1262 ? GFC_CAF_REF_STATIC_ARRAY
1263 : GFC_CAF_REF_ARRAY));
1265 /* Ref the a in union u. */
1266 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1267 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1268 TREE_TYPE (field), prev_caf_ref, field,
1269 NULL_TREE);
1270 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 1);
1271 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1272 TREE_TYPE (field), tmp, field,
1273 NULL_TREE);
1275 /* Set the static_array_type in a for static arrays. */
1276 if (ref_static_array)
1278 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)),
1280 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1281 TREE_TYPE (field), inner_struct, field,
1282 NULL_TREE);
1283 gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (tmp),
1284 last_type_n));
1286 /* Ref the mode in the inner_struct. */
1287 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1288 mode = fold_build3_loc (input_location, COMPONENT_REF,
1289 TREE_TYPE (field), inner_struct, field,
1290 NULL_TREE);
1291 /* Ref the dim in the inner_struct. */
1292 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 2);
1293 dim_array = fold_build3_loc (input_location, COMPONENT_REF,
1294 TREE_TYPE (field), inner_struct, field,
1295 NULL_TREE);
1296 for (i = 0; i < ref->u.ar.dimen; ++i)
1298 /* Ref dim i. */
1299 dim = gfc_build_array_ref (dim_array, gfc_rank_cst[i], NULL_TREE);
1300 dim_type = TREE_TYPE (dim);
1301 mode_rhs = start = end = stride = NULL_TREE;
1302 switch (ref->u.ar.dimen_type[i])
1304 case DIMEN_RANGE:
1305 if (ref->u.ar.end[i])
1307 gfc_init_se (&se, NULL);
1308 gfc_conv_expr (&se, ref->u.ar.end[i]);
1309 gfc_add_block_to_block (block, &se.pre);
1310 if (ref_static_array)
1312 /* Make the index zero-based, when reffing a static
1313 array. */
1314 end = se.expr;
1315 gfc_init_se (&se, NULL);
1316 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1317 gfc_add_block_to_block (block, &se.pre);
1318 se.expr = fold_build2 (MINUS_EXPR,
1319 gfc_array_index_type,
1320 end, fold_convert (
1321 gfc_array_index_type,
1322 se.expr));
1324 end = gfc_evaluate_now (fold_convert (
1325 gfc_array_index_type,
1326 se.expr),
1327 block);
1329 else if (ref_static_array)
1330 end = fold_build2 (MINUS_EXPR,
1331 gfc_array_index_type,
1332 gfc_conv_array_ubound (
1333 last_component_ref_tree, i),
1334 gfc_conv_array_lbound (
1335 last_component_ref_tree, i));
1336 else
1338 end = NULL_TREE;
1339 mode_rhs = build_int_cst (unsigned_char_type_node,
1340 GFC_CAF_ARR_REF_OPEN_END);
1342 if (ref->u.ar.stride[i])
1344 gfc_init_se (&se, NULL);
1345 gfc_conv_expr (&se, ref->u.ar.stride[i]);
1346 gfc_add_block_to_block (block, &se.pre);
1347 stride = gfc_evaluate_now (fold_convert (
1348 gfc_array_index_type,
1349 se.expr),
1350 block);
1351 if (ref_static_array)
1353 /* Make the index zero-based, when reffing a static
1354 array. */
1355 stride = fold_build2 (MULT_EXPR,
1356 gfc_array_index_type,
1357 gfc_conv_array_stride (
1358 last_component_ref_tree,
1360 stride);
1361 gcc_assert (end != NULL_TREE);
1362 /* Multiply with the product of array's stride and
1363 the step of the ref to a virtual upper bound.
1364 We can not compute the actual upper bound here or
1365 the caflib would compute the extend
1366 incorrectly. */
1367 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1368 end, gfc_conv_array_stride (
1369 last_component_ref_tree,
1370 i));
1371 end = gfc_evaluate_now (end, block);
1372 stride = gfc_evaluate_now (stride, block);
1375 else if (ref_static_array)
1377 stride = gfc_conv_array_stride (last_component_ref_tree,
1379 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1380 end, stride);
1381 end = gfc_evaluate_now (end, block);
1383 else
1384 /* Always set a ref stride of one to make caflib's
1385 handling easier. */
1386 stride = gfc_index_one_node;
1388 /* Fall through. */
1389 case DIMEN_ELEMENT:
1390 if (ref->u.ar.start[i])
1392 gfc_init_se (&se, NULL);
1393 gfc_conv_expr (&se, ref->u.ar.start[i]);
1394 gfc_add_block_to_block (block, &se.pre);
1395 if (ref_static_array)
1397 /* Make the index zero-based, when reffing a static
1398 array. */
1399 start = fold_convert (gfc_array_index_type, se.expr);
1400 gfc_init_se (&se, NULL);
1401 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1402 gfc_add_block_to_block (block, &se.pre);
1403 se.expr = fold_build2 (MINUS_EXPR,
1404 gfc_array_index_type,
1405 start, fold_convert (
1406 gfc_array_index_type,
1407 se.expr));
1408 /* Multiply with the stride. */
1409 se.expr = fold_build2 (MULT_EXPR,
1410 gfc_array_index_type,
1411 se.expr,
1412 gfc_conv_array_stride (
1413 last_component_ref_tree,
1414 i));
1416 start = gfc_evaluate_now (fold_convert (
1417 gfc_array_index_type,
1418 se.expr),
1419 block);
1420 if (mode_rhs == NULL_TREE)
1421 mode_rhs = build_int_cst (unsigned_char_type_node,
1422 ref->u.ar.dimen_type[i]
1423 == DIMEN_ELEMENT
1424 ? GFC_CAF_ARR_REF_SINGLE
1425 : GFC_CAF_ARR_REF_RANGE);
1427 else if (ref_static_array)
1429 start = integer_zero_node;
1430 mode_rhs = build_int_cst (unsigned_char_type_node,
1431 ref->u.ar.start[i] == NULL
1432 ? GFC_CAF_ARR_REF_FULL
1433 : GFC_CAF_ARR_REF_RANGE);
1435 else if (end == NULL_TREE)
1436 mode_rhs = build_int_cst (unsigned_char_type_node,
1437 GFC_CAF_ARR_REF_FULL);
1438 else
1439 mode_rhs = build_int_cst (unsigned_char_type_node,
1440 GFC_CAF_ARR_REF_OPEN_START);
1442 /* Ref the s in dim. */
1443 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 0);
1444 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1445 TREE_TYPE (field), dim, field,
1446 NULL_TREE);
1448 /* Set start in s. */
1449 if (start != NULL_TREE)
1451 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1453 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1454 TREE_TYPE (field), tmp, field,
1455 NULL_TREE);
1456 gfc_add_modify (block, tmp2,
1457 fold_convert (TREE_TYPE (tmp2), start));
1460 /* Set end in s. */
1461 if (end != NULL_TREE)
1463 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1465 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1466 TREE_TYPE (field), tmp, field,
1467 NULL_TREE);
1468 gfc_add_modify (block, tmp2,
1469 fold_convert (TREE_TYPE (tmp2), end));
1472 /* Set end in s. */
1473 if (stride != NULL_TREE)
1475 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1477 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1478 TREE_TYPE (field), tmp, field,
1479 NULL_TREE);
1480 gfc_add_modify (block, tmp2,
1481 fold_convert (TREE_TYPE (tmp2), stride));
1483 break;
1484 case DIMEN_VECTOR:
1485 /* TODO: In case of static array. */
1486 gcc_assert (!ref_static_array);
1487 mode_rhs = build_int_cst (unsigned_char_type_node,
1488 GFC_CAF_ARR_REF_VECTOR);
1489 gfc_init_se (&se, NULL);
1490 se.descriptor_only = 1;
1491 gfc_conv_expr_descriptor (&se, ref->u.ar.start[i]);
1492 gfc_add_block_to_block (block, &se.pre);
1493 vector = se.expr;
1494 tmp = gfc_conv_descriptor_lbound_get (vector,
1495 gfc_rank_cst[0]);
1496 tmp2 = gfc_conv_descriptor_ubound_get (vector,
1497 gfc_rank_cst[0]);
1498 nvec = gfc_conv_array_extent_dim (tmp, tmp2, NULL);
1499 tmp = gfc_conv_descriptor_stride_get (vector,
1500 gfc_rank_cst[0]);
1501 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1502 TREE_TYPE (nvec), nvec, tmp);
1503 vector = gfc_conv_descriptor_data_get (vector);
1505 /* Ref the v in dim. */
1506 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 1);
1507 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1508 TREE_TYPE (field), dim, field,
1509 NULL_TREE);
1511 /* Set vector in v. */
1512 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 0);
1513 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1514 TREE_TYPE (field), tmp, field,
1515 NULL_TREE);
1516 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1517 vector));
1519 /* Set nvec in v. */
1520 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 1);
1521 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1522 TREE_TYPE (field), tmp, field,
1523 NULL_TREE);
1524 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1525 nvec));
1527 /* Set kind in v. */
1528 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 2);
1529 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1530 TREE_TYPE (field), tmp, field,
1531 NULL_TREE);
1532 gfc_add_modify (block, tmp2, build_int_cst (integer_type_node,
1533 ref->u.ar.start[i]->ts.kind));
1534 break;
1535 default:
1536 gcc_unreachable ();
1538 /* Set the mode for dim i. */
1539 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1540 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp),
1541 mode_rhs));
1544 /* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
1545 if (i < GFC_MAX_DIMENSIONS)
1547 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1548 gfc_add_modify (block, tmp,
1549 build_int_cst (unsigned_char_type_node,
1550 GFC_CAF_ARR_REF_NONE));
1552 break;
1553 default:
1554 gcc_unreachable ();
1557 /* Set the size of the current type. */
1558 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 2);
1559 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1560 prev_caf_ref, field, NULL_TREE);
1561 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1562 TYPE_SIZE_UNIT (last_type)));
1564 ref = ref->next;
1567 if (prev_caf_ref != NULL_TREE)
1569 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1570 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1571 prev_caf_ref, field, NULL_TREE);
1572 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1573 null_pointer_node));
1575 return caf_ref != NULL_TREE ? gfc_build_addr_expr (NULL_TREE, caf_ref)
1576 : NULL_TREE;
1579 /* Get data from a remote coarray. */
1581 static void
1582 gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
1583 tree may_require_tmp, bool may_realloc,
1584 symbol_attribute *caf_attr)
1586 gfc_expr *array_expr, *tmp_stat;
1587 gfc_se argse;
1588 tree caf_decl, token, offset, image_index, tmp;
1589 tree res_var, dst_var, type, kind, vec, stat;
1590 tree caf_reference;
1591 symbol_attribute caf_attr_store;
1593 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1595 if (se->ss && se->ss->info->useflags)
1597 /* Access the previously obtained result. */
1598 gfc_conv_tmp_array_ref (se);
1599 return;
1602 /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1603 array_expr = (lhs == NULL_TREE) ? expr->value.function.actual->expr : expr;
1604 type = gfc_typenode_for_spec (&array_expr->ts);
1606 if (caf_attr == NULL)
1608 caf_attr_store = gfc_caf_attr (array_expr);
1609 caf_attr = &caf_attr_store;
1612 res_var = lhs;
1613 dst_var = lhs;
1615 vec = null_pointer_node;
1616 tmp_stat = gfc_find_stat_co (expr);
1618 if (tmp_stat)
1620 gfc_se stat_se;
1621 gfc_init_se (&stat_se, NULL);
1622 gfc_conv_expr_reference (&stat_se, tmp_stat);
1623 stat = stat_se.expr;
1624 gfc_add_block_to_block (&se->pre, &stat_se.pre);
1625 gfc_add_block_to_block (&se->post, &stat_se.post);
1627 else
1628 stat = null_pointer_node;
1630 /* Only use the new get_by_ref () where it is necessary. I.e., when the lhs
1631 is reallocatable or the right-hand side has allocatable components. */
1632 if (caf_attr->alloc_comp || caf_attr->pointer_comp || may_realloc)
1634 /* Get using caf_get_by_ref. */
1635 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, array_expr);
1637 if (caf_reference != NULL_TREE)
1639 if (lhs == NULL_TREE)
1641 if (array_expr->ts.type == BT_CHARACTER)
1642 gfc_init_se (&argse, NULL);
1643 if (array_expr->rank == 0)
1645 symbol_attribute attr;
1646 gfc_clear_attr (&attr);
1647 if (array_expr->ts.type == BT_CHARACTER)
1649 res_var = gfc_conv_string_tmp (se,
1650 build_pointer_type (type),
1651 array_expr->ts.u.cl->backend_decl);
1652 argse.string_length = array_expr->ts.u.cl->backend_decl;
1654 else
1655 res_var = gfc_create_var (type, "caf_res");
1656 dst_var = gfc_conv_scalar_to_descriptor (se, res_var, attr);
1657 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1659 else
1661 /* Create temporary. */
1662 if (array_expr->ts.type == BT_CHARACTER)
1663 gfc_conv_expr_descriptor (&argse, array_expr);
1664 may_realloc = gfc_trans_create_temp_array (&se->pre,
1665 &se->post,
1666 se->ss, type,
1667 NULL_TREE, false,
1668 false, false,
1669 &array_expr->where)
1670 == NULL_TREE;
1671 res_var = se->ss->info->data.array.descriptor;
1672 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1673 if (may_realloc)
1675 tmp = gfc_conv_descriptor_data_get (res_var);
1676 tmp = gfc_deallocate_with_status (tmp, NULL_TREE,
1677 NULL_TREE, NULL_TREE,
1678 NULL_TREE, true,
1679 NULL,
1680 GFC_CAF_COARRAY_NOCOARRAY);
1681 gfc_add_expr_to_block (&se->post, tmp);
1686 kind = build_int_cst (integer_type_node, expr->ts.kind);
1687 if (lhs_kind == NULL_TREE)
1688 lhs_kind = kind;
1690 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1691 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1692 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1693 image_index = gfc_caf_get_image_index (&se->pre, array_expr,
1694 caf_decl);
1695 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
1696 array_expr);
1698 /* No overlap possible as we have generated a temporary. */
1699 if (lhs == NULL_TREE)
1700 may_require_tmp = boolean_false_node;
1702 /* It guarantees memory consistency within the same segment. */
1703 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1704 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1705 gfc_build_string_const (1, ""), NULL_TREE,
1706 NULL_TREE, tree_cons (NULL_TREE, tmp, NULL_TREE),
1707 NULL_TREE);
1708 ASM_VOLATILE_P (tmp) = 1;
1709 gfc_add_expr_to_block (&se->pre, tmp);
1711 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get_by_ref,
1712 9, token, image_index, dst_var,
1713 caf_reference, lhs_kind, kind,
1714 may_require_tmp,
1715 may_realloc ? boolean_true_node :
1716 boolean_false_node,
1717 stat);
1719 gfc_add_expr_to_block (&se->pre, tmp);
1721 if (se->ss)
1722 gfc_advance_se_ss_chain (se);
1724 se->expr = res_var;
1725 if (array_expr->ts.type == BT_CHARACTER)
1726 se->string_length = argse.string_length;
1728 return;
1732 gfc_init_se (&argse, NULL);
1733 if (array_expr->rank == 0)
1735 symbol_attribute attr;
1737 gfc_clear_attr (&attr);
1738 gfc_conv_expr (&argse, array_expr);
1740 if (lhs == NULL_TREE)
1742 gfc_clear_attr (&attr);
1743 if (array_expr->ts.type == BT_CHARACTER)
1744 res_var = gfc_conv_string_tmp (se, build_pointer_type (type),
1745 argse.string_length);
1746 else
1747 res_var = gfc_create_var (type, "caf_res");
1748 dst_var = gfc_conv_scalar_to_descriptor (&argse, res_var, attr);
1749 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1751 argse.expr = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
1752 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1754 else
1756 /* If has_vector, pass descriptor for whole array and the
1757 vector bounds separately. */
1758 gfc_array_ref *ar, ar2;
1759 bool has_vector = false;
1761 if (gfc_is_coindexed (expr) && gfc_has_vector_subscript (expr))
1763 has_vector = true;
1764 ar = gfc_find_array_ref (expr);
1765 ar2 = *ar;
1766 memset (ar, '\0', sizeof (*ar));
1767 ar->as = ar2.as;
1768 ar->type = AR_FULL;
1770 // TODO: Check whether argse.want_coarray = 1 can help with the below.
1771 gfc_conv_expr_descriptor (&argse, array_expr);
1772 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1773 has the wrong type if component references are done. */
1774 gfc_add_modify (&argse.pre, gfc_conv_descriptor_dtype (argse.expr),
1775 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1776 : array_expr->rank,
1777 type));
1778 if (has_vector)
1780 vec = conv_caf_vector_subscript (&argse.pre, argse.expr, &ar2);
1781 *ar = ar2;
1784 if (lhs == NULL_TREE)
1786 /* Create temporary. */
1787 for (int n = 0; n < se->ss->loop->dimen; n++)
1788 if (se->loop->to[n] == NULL_TREE)
1790 se->loop->from[n] = gfc_conv_descriptor_lbound_get (argse.expr,
1791 gfc_rank_cst[n]);
1792 se->loop->to[n] = gfc_conv_descriptor_ubound_get (argse.expr,
1793 gfc_rank_cst[n]);
1795 gfc_trans_create_temp_array (&argse.pre, &argse.post, se->ss, type,
1796 NULL_TREE, false, true, false,
1797 &array_expr->where);
1798 res_var = se->ss->info->data.array.descriptor;
1799 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1801 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1804 kind = build_int_cst (integer_type_node, expr->ts.kind);
1805 if (lhs_kind == NULL_TREE)
1806 lhs_kind = kind;
1808 gfc_add_block_to_block (&se->pre, &argse.pre);
1809 gfc_add_block_to_block (&se->post, &argse.post);
1811 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1812 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1813 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1814 image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
1815 gfc_get_caf_token_offset (se, &token, &offset, caf_decl, argse.expr,
1816 array_expr);
1818 /* No overlap possible as we have generated a temporary. */
1819 if (lhs == NULL_TREE)
1820 may_require_tmp = boolean_false_node;
1822 /* It guarantees memory consistency within the same segment. */
1823 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1824 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1825 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1826 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1827 ASM_VOLATILE_P (tmp) = 1;
1828 gfc_add_expr_to_block (&se->pre, tmp);
1830 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 10,
1831 token, offset, image_index, argse.expr, vec,
1832 dst_var, kind, lhs_kind, may_require_tmp, stat);
1834 gfc_add_expr_to_block (&se->pre, tmp);
1836 if (se->ss)
1837 gfc_advance_se_ss_chain (se);
1839 se->expr = res_var;
1840 if (array_expr->ts.type == BT_CHARACTER)
1841 se->string_length = argse.string_length;
1845 /* Send data to a remote coarray. */
1847 static tree
1848 conv_caf_send (gfc_code *code) {
1849 gfc_expr *lhs_expr, *rhs_expr, *tmp_stat;
1850 gfc_se lhs_se, rhs_se;
1851 stmtblock_t block;
1852 tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
1853 tree may_require_tmp, src_stat, dst_stat;
1854 tree lhs_type = NULL_TREE;
1855 tree vec = null_pointer_node, rhs_vec = null_pointer_node;
1856 symbol_attribute lhs_caf_attr, rhs_caf_attr;
1858 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
1860 lhs_expr = code->ext.actual->expr;
1861 rhs_expr = code->ext.actual->next->expr;
1862 may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, false) == 0
1863 ? boolean_false_node : boolean_true_node;
1864 gfc_init_block (&block);
1866 lhs_caf_attr = gfc_caf_attr (lhs_expr);
1867 rhs_caf_attr = gfc_caf_attr (rhs_expr);
1868 src_stat = dst_stat = null_pointer_node;
1870 /* LHS. */
1871 gfc_init_se (&lhs_se, NULL);
1872 if (lhs_expr->rank == 0)
1874 if (lhs_expr->ts.type == BT_CHARACTER && lhs_expr->ts.deferred)
1876 lhs_se.expr = gfc_get_tree_for_caf_expr (lhs_expr);
1877 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1879 else
1881 symbol_attribute attr;
1882 gfc_clear_attr (&attr);
1883 gfc_conv_expr (&lhs_se, lhs_expr);
1884 lhs_type = TREE_TYPE (lhs_se.expr);
1885 lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr,
1886 attr);
1887 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1890 else if ((lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
1891 && lhs_caf_attr.codimension)
1893 lhs_se.want_pointer = 1;
1894 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1895 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1896 has the wrong type if component references are done. */
1897 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1898 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1899 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1900 gfc_get_dtype_rank_type (
1901 gfc_has_vector_subscript (lhs_expr)
1902 ? gfc_find_array_ref (lhs_expr)->dimen
1903 : lhs_expr->rank,
1904 lhs_type));
1906 else
1908 /* If has_vector, pass descriptor for whole array and the
1909 vector bounds separately. */
1910 gfc_array_ref *ar, ar2;
1911 bool has_vector = false;
1913 if (gfc_is_coindexed (lhs_expr) && gfc_has_vector_subscript (lhs_expr))
1915 has_vector = true;
1916 ar = gfc_find_array_ref (lhs_expr);
1917 ar2 = *ar;
1918 memset (ar, '\0', sizeof (*ar));
1919 ar->as = ar2.as;
1920 ar->type = AR_FULL;
1922 lhs_se.want_pointer = 1;
1923 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1924 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1925 has the wrong type if component references are done. */
1926 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1927 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1928 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1929 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1930 : lhs_expr->rank,
1931 lhs_type));
1932 if (has_vector)
1934 vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
1935 *ar = ar2;
1939 lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
1941 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
1942 temporary and a loop. */
1943 if (!gfc_is_coindexed (lhs_expr)
1944 && (!lhs_caf_attr.codimension
1945 || !(lhs_expr->rank > 0
1946 && (lhs_caf_attr.allocatable || lhs_caf_attr.pointer))))
1948 bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
1949 gcc_assert (gfc_is_coindexed (rhs_expr));
1950 gfc_init_se (&rhs_se, NULL);
1951 if (lhs_expr->rank == 0 && lhs_caf_attr.allocatable)
1953 gfc_se scal_se;
1954 gfc_init_se (&scal_se, NULL);
1955 scal_se.want_pointer = 1;
1956 gfc_conv_expr (&scal_se, lhs_expr);
1957 /* Ensure scalar on lhs is allocated. */
1958 gfc_add_block_to_block (&block, &scal_se.pre);
1960 gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
1961 TYPE_SIZE_UNIT (
1962 gfc_typenode_for_spec (&lhs_expr->ts)),
1963 NULL_TREE);
1964 tmp = fold_build2 (EQ_EXPR, logical_type_node, scal_se.expr,
1965 null_pointer_node);
1966 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1967 tmp, gfc_finish_block (&scal_se.pre),
1968 build_empty_stmt (input_location));
1969 gfc_add_expr_to_block (&block, tmp);
1971 else
1972 lhs_may_realloc = lhs_may_realloc
1973 && gfc_full_array_ref_p (lhs_expr->ref, NULL);
1974 gfc_add_block_to_block (&block, &lhs_se.pre);
1975 gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
1976 may_require_tmp, lhs_may_realloc,
1977 &rhs_caf_attr);
1978 gfc_add_block_to_block (&block, &rhs_se.pre);
1979 gfc_add_block_to_block (&block, &rhs_se.post);
1980 gfc_add_block_to_block (&block, &lhs_se.post);
1981 return gfc_finish_block (&block);
1984 gfc_add_block_to_block (&block, &lhs_se.pre);
1986 /* Obtain token, offset and image index for the LHS. */
1987 caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
1988 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1989 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1990 image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
1991 tmp = lhs_se.expr;
1992 if (lhs_caf_attr.alloc_comp)
1993 gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL_TREE,
1994 NULL);
1995 else
1996 gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
1997 lhs_expr);
1998 lhs_se.expr = tmp;
2000 /* RHS. */
2001 gfc_init_se (&rhs_se, NULL);
2002 if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
2003 && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
2004 rhs_expr = rhs_expr->value.function.actual->expr;
2005 if (rhs_expr->rank == 0)
2007 symbol_attribute attr;
2008 gfc_clear_attr (&attr);
2009 gfc_conv_expr (&rhs_se, rhs_expr);
2010 rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
2011 rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
2013 else if ((rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2014 && rhs_caf_attr.codimension)
2016 tree tmp2;
2017 rhs_se.want_pointer = 1;
2018 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2019 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2020 has the wrong type if component references are done. */
2021 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2022 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2023 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2024 gfc_get_dtype_rank_type (
2025 gfc_has_vector_subscript (rhs_expr)
2026 ? gfc_find_array_ref (rhs_expr)->dimen
2027 : rhs_expr->rank,
2028 tmp2));
2030 else
2032 /* If has_vector, pass descriptor for whole array and the
2033 vector bounds separately. */
2034 gfc_array_ref *ar, ar2;
2035 bool has_vector = false;
2036 tree tmp2;
2038 if (gfc_is_coindexed (rhs_expr) && gfc_has_vector_subscript (rhs_expr))
2040 has_vector = true;
2041 ar = gfc_find_array_ref (rhs_expr);
2042 ar2 = *ar;
2043 memset (ar, '\0', sizeof (*ar));
2044 ar->as = ar2.as;
2045 ar->type = AR_FULL;
2047 rhs_se.want_pointer = 1;
2048 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2049 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2050 has the wrong type if component references are done. */
2051 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2052 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2053 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2054 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2055 : rhs_expr->rank,
2056 tmp2));
2057 if (has_vector)
2059 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
2060 *ar = ar2;
2064 gfc_add_block_to_block (&block, &rhs_se.pre);
2066 rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
2068 tmp_stat = gfc_find_stat_co (lhs_expr);
2070 if (tmp_stat)
2072 gfc_se stat_se;
2073 gfc_init_se (&stat_se, NULL);
2074 gfc_conv_expr_reference (&stat_se, tmp_stat);
2075 dst_stat = stat_se.expr;
2076 gfc_add_block_to_block (&block, &stat_se.pre);
2077 gfc_add_block_to_block (&block, &stat_se.post);
2080 if (!gfc_is_coindexed (rhs_expr))
2082 if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
2084 tree reference, dst_realloc;
2085 reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2086 dst_realloc = lhs_caf_attr.allocatable ? boolean_true_node
2087 : boolean_false_node;
2088 tmp = build_call_expr_loc (input_location,
2089 gfor_fndecl_caf_send_by_ref,
2090 9, token, image_index, rhs_se.expr,
2091 reference, lhs_kind, rhs_kind,
2092 may_require_tmp, dst_realloc, src_stat);
2094 else
2095 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 10,
2096 token, offset, image_index, lhs_se.expr, vec,
2097 rhs_se.expr, lhs_kind, rhs_kind,
2098 may_require_tmp, src_stat);
2100 else
2102 tree rhs_token, rhs_offset, rhs_image_index;
2104 /* It guarantees memory consistency within the same segment. */
2105 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2106 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2107 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2108 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2109 ASM_VOLATILE_P (tmp) = 1;
2110 gfc_add_expr_to_block (&block, tmp);
2112 caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
2113 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2114 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2115 rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
2116 tmp = rhs_se.expr;
2117 if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2119 tmp_stat = gfc_find_stat_co (lhs_expr);
2121 if (tmp_stat)
2123 gfc_se stat_se;
2124 gfc_init_se (&stat_se, NULL);
2125 gfc_conv_expr_reference (&stat_se, tmp_stat);
2126 src_stat = stat_se.expr;
2127 gfc_add_block_to_block (&block, &stat_se.pre);
2128 gfc_add_block_to_block (&block, &stat_se.post);
2131 gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL, caf_decl,
2132 NULL_TREE, NULL);
2133 tree lhs_reference, rhs_reference;
2134 lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2135 rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
2136 tmp = build_call_expr_loc (input_location,
2137 gfor_fndecl_caf_sendget_by_ref, 11,
2138 token, image_index, lhs_reference,
2139 rhs_token, rhs_image_index, rhs_reference,
2140 lhs_kind, rhs_kind, may_require_tmp,
2141 dst_stat, src_stat);
2143 else
2145 gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
2146 tmp, rhs_expr);
2147 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
2148 14, token, offset, image_index,
2149 lhs_se.expr, vec, rhs_token, rhs_offset,
2150 rhs_image_index, tmp, rhs_vec, lhs_kind,
2151 rhs_kind, may_require_tmp, src_stat);
2154 gfc_add_expr_to_block (&block, tmp);
2155 gfc_add_block_to_block (&block, &lhs_se.post);
2156 gfc_add_block_to_block (&block, &rhs_se.post);
2158 /* It guarantees memory consistency within the same segment. */
2159 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2160 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2161 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2162 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2163 ASM_VOLATILE_P (tmp) = 1;
2164 gfc_add_expr_to_block (&block, tmp);
2166 return gfc_finish_block (&block);
2170 static void
2171 trans_this_image (gfc_se * se, gfc_expr *expr)
2173 stmtblock_t loop;
2174 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
2175 lbound, ubound, extent, ml;
2176 gfc_se argse;
2177 int rank, corank;
2178 gfc_expr *distance = expr->value.function.actual->next->next->expr;
2180 if (expr->value.function.actual->expr
2181 && !gfc_is_coarray (expr->value.function.actual->expr))
2182 distance = expr->value.function.actual->expr;
2184 /* The case -fcoarray=single is handled elsewhere. */
2185 gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
2187 /* Argument-free version: THIS_IMAGE(). */
2188 if (distance || expr->value.function.actual->expr == NULL)
2190 if (distance)
2192 gfc_init_se (&argse, NULL);
2193 gfc_conv_expr_val (&argse, distance);
2194 gfc_add_block_to_block (&se->pre, &argse.pre);
2195 gfc_add_block_to_block (&se->post, &argse.post);
2196 tmp = fold_convert (integer_type_node, argse.expr);
2198 else
2199 tmp = integer_zero_node;
2200 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2201 tmp);
2202 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2203 tmp);
2204 return;
2207 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2209 type = gfc_get_int_type (gfc_default_integer_kind);
2210 corank = gfc_get_corank (expr->value.function.actual->expr);
2211 rank = expr->value.function.actual->expr->rank;
2213 /* Obtain the descriptor of the COARRAY. */
2214 gfc_init_se (&argse, NULL);
2215 argse.want_coarray = 1;
2216 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2217 gfc_add_block_to_block (&se->pre, &argse.pre);
2218 gfc_add_block_to_block (&se->post, &argse.post);
2219 desc = argse.expr;
2221 if (se->ss)
2223 /* Create an implicit second parameter from the loop variable. */
2224 gcc_assert (!expr->value.function.actual->next->expr);
2225 gcc_assert (corank > 0);
2226 gcc_assert (se->loop->dimen == 1);
2227 gcc_assert (se->ss->info->expr == expr);
2229 dim_arg = se->loop->loopvar[0];
2230 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
2231 gfc_array_index_type, dim_arg,
2232 build_int_cst (TREE_TYPE (dim_arg), 1));
2233 gfc_advance_se_ss_chain (se);
2235 else
2237 /* Use the passed DIM= argument. */
2238 gcc_assert (expr->value.function.actual->next->expr);
2239 gfc_init_se (&argse, NULL);
2240 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
2241 gfc_array_index_type);
2242 gfc_add_block_to_block (&se->pre, &argse.pre);
2243 dim_arg = argse.expr;
2245 if (INTEGER_CST_P (dim_arg))
2247 if (wi::ltu_p (wi::to_wide (dim_arg), 1)
2248 || wi::gtu_p (wi::to_wide (dim_arg),
2249 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2250 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2251 "dimension index", expr->value.function.isym->name,
2252 &expr->where);
2254 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2256 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
2257 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2258 dim_arg,
2259 build_int_cst (TREE_TYPE (dim_arg), 1));
2260 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2261 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2262 dim_arg, tmp);
2263 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2264 logical_type_node, cond, tmp);
2265 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2266 gfc_msg_fault);
2270 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2271 one always has a dim_arg argument.
2273 m = this_image() - 1
2274 if (corank == 1)
2276 sub(1) = m + lcobound(corank)
2277 return;
2279 i = rank
2280 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2281 for (;;)
2283 extent = gfc_extent(i)
2284 ml = m
2285 m = m/extent
2286 if (i >= min_var)
2287 goto exit_label
2290 exit_label:
2291 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2292 : m + lcobound(corank)
2295 /* this_image () - 1. */
2296 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2297 integer_zero_node);
2298 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
2299 fold_convert (type, tmp), build_int_cst (type, 1));
2300 if (corank == 1)
2302 /* sub(1) = m + lcobound(corank). */
2303 lbound = gfc_conv_descriptor_lbound_get (desc,
2304 build_int_cst (TREE_TYPE (gfc_array_index_type),
2305 corank+rank-1));
2306 lbound = fold_convert (type, lbound);
2307 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2309 se->expr = tmp;
2310 return;
2313 m = gfc_create_var (type, NULL);
2314 ml = gfc_create_var (type, NULL);
2315 loop_var = gfc_create_var (integer_type_node, NULL);
2316 min_var = gfc_create_var (integer_type_node, NULL);
2318 /* m = this_image () - 1. */
2319 gfc_add_modify (&se->pre, m, tmp);
2321 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2322 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2323 fold_convert (integer_type_node, dim_arg),
2324 build_int_cst (integer_type_node, rank - 1));
2325 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
2326 build_int_cst (integer_type_node, rank + corank - 2),
2327 tmp);
2328 gfc_add_modify (&se->pre, min_var, tmp);
2330 /* i = rank. */
2331 tmp = build_int_cst (integer_type_node, rank);
2332 gfc_add_modify (&se->pre, loop_var, tmp);
2334 exit_label = gfc_build_label_decl (NULL_TREE);
2335 TREE_USED (exit_label) = 1;
2337 /* Loop body. */
2338 gfc_init_block (&loop);
2340 /* ml = m. */
2341 gfc_add_modify (&loop, ml, m);
2343 /* extent = ... */
2344 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
2345 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
2346 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2347 extent = fold_convert (type, extent);
2349 /* m = m/extent. */
2350 gfc_add_modify (&loop, m,
2351 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
2352 m, extent));
2354 /* Exit condition: if (i >= min_var) goto exit_label. */
2355 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, loop_var,
2356 min_var);
2357 tmp = build1_v (GOTO_EXPR, exit_label);
2358 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
2359 build_empty_stmt (input_location));
2360 gfc_add_expr_to_block (&loop, tmp);
2362 /* Increment loop variable: i++. */
2363 gfc_add_modify (&loop, loop_var,
2364 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2365 loop_var,
2366 build_int_cst (integer_type_node, 1)));
2368 /* Making the loop... actually loop! */
2369 tmp = gfc_finish_block (&loop);
2370 tmp = build1_v (LOOP_EXPR, tmp);
2371 gfc_add_expr_to_block (&se->pre, tmp);
2373 /* The exit label. */
2374 tmp = build1_v (LABEL_EXPR, exit_label);
2375 gfc_add_expr_to_block (&se->pre, tmp);
2377 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2378 : m + lcobound(corank) */
2380 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, dim_arg,
2381 build_int_cst (TREE_TYPE (dim_arg), corank));
2383 lbound = gfc_conv_descriptor_lbound_get (desc,
2384 fold_build2_loc (input_location, PLUS_EXPR,
2385 gfc_array_index_type, dim_arg,
2386 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
2387 lbound = fold_convert (type, lbound);
2389 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
2390 fold_build2_loc (input_location, MULT_EXPR, type,
2391 m, extent));
2392 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2394 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
2395 fold_build2_loc (input_location, PLUS_EXPR, type,
2396 m, lbound));
2400 /* Convert a call to image_status. */
2402 static void
2403 conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
2405 unsigned int num_args;
2406 tree *args, tmp;
2408 num_args = gfc_intrinsic_argument_list_length (expr);
2409 args = XALLOCAVEC (tree, num_args);
2410 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2411 /* In args[0] the number of the image the status is desired for has to be
2412 given. */
2414 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2416 tree arg;
2417 arg = gfc_evaluate_now (args[0], &se->pre);
2418 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2419 fold_convert (integer_type_node, arg),
2420 integer_one_node);
2421 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2422 tmp, integer_zero_node,
2423 build_int_cst (integer_type_node,
2424 GFC_STAT_STOPPED_IMAGE));
2426 else if (flag_coarray == GFC_FCOARRAY_LIB)
2427 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
2428 args[0], build_int_cst (integer_type_node, -1));
2429 else
2430 gcc_unreachable ();
2432 se->expr = tmp;
2436 static void
2437 trans_image_index (gfc_se * se, gfc_expr *expr)
2439 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
2440 tmp, invalid_bound;
2441 gfc_se argse, subse;
2442 int rank, corank, codim;
2444 type = gfc_get_int_type (gfc_default_integer_kind);
2445 corank = gfc_get_corank (expr->value.function.actual->expr);
2446 rank = expr->value.function.actual->expr->rank;
2448 /* Obtain the descriptor of the COARRAY. */
2449 gfc_init_se (&argse, NULL);
2450 argse.want_coarray = 1;
2451 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2452 gfc_add_block_to_block (&se->pre, &argse.pre);
2453 gfc_add_block_to_block (&se->post, &argse.post);
2454 desc = argse.expr;
2456 /* Obtain a handle to the SUB argument. */
2457 gfc_init_se (&subse, NULL);
2458 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
2459 gfc_add_block_to_block (&se->pre, &subse.pre);
2460 gfc_add_block_to_block (&se->post, &subse.post);
2461 subdesc = build_fold_indirect_ref_loc (input_location,
2462 gfc_conv_descriptor_data_get (subse.expr));
2464 /* Fortran 2008 does not require that the values remain in the cobounds,
2465 thus we need explicitly check this - and return 0 if they are exceeded. */
2467 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2468 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
2469 invalid_bound = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2470 fold_convert (gfc_array_index_type, tmp),
2471 lbound);
2473 for (codim = corank + rank - 2; codim >= rank; codim--)
2475 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2476 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2477 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2478 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2479 fold_convert (gfc_array_index_type, tmp),
2480 lbound);
2481 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2482 logical_type_node, invalid_bound, cond);
2483 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2484 fold_convert (gfc_array_index_type, tmp),
2485 ubound);
2486 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2487 logical_type_node, invalid_bound, cond);
2490 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
2492 /* See Fortran 2008, C.10 for the following algorithm. */
2494 /* coindex = sub(corank) - lcobound(n). */
2495 coindex = fold_convert (gfc_array_index_type,
2496 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
2497 NULL));
2498 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2499 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2500 fold_convert (gfc_array_index_type, coindex),
2501 lbound);
2503 for (codim = corank + rank - 2; codim >= rank; codim--)
2505 tree extent, ubound;
2507 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2508 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2509 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2510 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2512 /* coindex *= extent. */
2513 coindex = fold_build2_loc (input_location, MULT_EXPR,
2514 gfc_array_index_type, coindex, extent);
2516 /* coindex += sub(codim). */
2517 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2518 coindex = fold_build2_loc (input_location, PLUS_EXPR,
2519 gfc_array_index_type, coindex,
2520 fold_convert (gfc_array_index_type, tmp));
2522 /* coindex -= lbound(codim). */
2523 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2524 coindex = fold_build2_loc (input_location, MINUS_EXPR,
2525 gfc_array_index_type, coindex, lbound);
2528 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
2529 fold_convert(type, coindex),
2530 build_int_cst (type, 1));
2532 /* Return 0 if "coindex" exceeds num_images(). */
2534 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2535 num_images = build_int_cst (type, 1);
2536 else
2538 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2539 integer_zero_node,
2540 build_int_cst (integer_type_node, -1));
2541 num_images = fold_convert (type, tmp);
2544 tmp = gfc_create_var (type, NULL);
2545 gfc_add_modify (&se->pre, tmp, coindex);
2547 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, tmp,
2548 num_images);
2549 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
2550 cond,
2551 fold_convert (logical_type_node, invalid_bound));
2552 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
2553 build_int_cst (type, 0), tmp);
2557 static void
2558 trans_num_images (gfc_se * se, gfc_expr *expr)
2560 tree tmp, distance, failed;
2561 gfc_se argse;
2563 if (expr->value.function.actual->expr)
2565 gfc_init_se (&argse, NULL);
2566 gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
2567 gfc_add_block_to_block (&se->pre, &argse.pre);
2568 gfc_add_block_to_block (&se->post, &argse.post);
2569 distance = fold_convert (integer_type_node, argse.expr);
2571 else
2572 distance = integer_zero_node;
2574 if (expr->value.function.actual->next->expr)
2576 gfc_init_se (&argse, NULL);
2577 gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
2578 gfc_add_block_to_block (&se->pre, &argse.pre);
2579 gfc_add_block_to_block (&se->post, &argse.post);
2580 failed = fold_convert (integer_type_node, argse.expr);
2582 else
2583 failed = build_int_cst (integer_type_node, -1);
2585 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2586 distance, failed);
2587 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2591 static void
2592 gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
2594 gfc_se argse;
2596 gfc_init_se (&argse, NULL);
2597 argse.data_not_needed = 1;
2598 argse.descriptor_only = 1;
2600 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2601 gfc_add_block_to_block (&se->pre, &argse.pre);
2602 gfc_add_block_to_block (&se->post, &argse.post);
2604 se->expr = gfc_conv_descriptor_rank (argse.expr);
2608 /* Evaluate a single upper or lower bound. */
2609 /* TODO: bound intrinsic generates way too much unnecessary code. */
2611 static void
2612 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
2614 gfc_actual_arglist *arg;
2615 gfc_actual_arglist *arg2;
2616 tree desc;
2617 tree type;
2618 tree bound;
2619 tree tmp;
2620 tree cond, cond1, cond3, cond4, size;
2621 tree ubound;
2622 tree lbound;
2623 gfc_se argse;
2624 gfc_array_spec * as;
2625 bool assumed_rank_lb_one;
2627 arg = expr->value.function.actual;
2628 arg2 = arg->next;
2630 if (se->ss)
2632 /* Create an implicit second parameter from the loop variable. */
2633 gcc_assert (!arg2->expr);
2634 gcc_assert (se->loop->dimen == 1);
2635 gcc_assert (se->ss->info->expr == expr);
2636 gfc_advance_se_ss_chain (se);
2637 bound = se->loop->loopvar[0];
2638 bound = fold_build2_loc (input_location, MINUS_EXPR,
2639 gfc_array_index_type, bound,
2640 se->loop->from[0]);
2642 else
2644 /* use the passed argument. */
2645 gcc_assert (arg2->expr);
2646 gfc_init_se (&argse, NULL);
2647 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2648 gfc_add_block_to_block (&se->pre, &argse.pre);
2649 bound = argse.expr;
2650 /* Convert from one based to zero based. */
2651 bound = fold_build2_loc (input_location, MINUS_EXPR,
2652 gfc_array_index_type, bound,
2653 gfc_index_one_node);
2656 /* TODO: don't re-evaluate the descriptor on each iteration. */
2657 /* Get a descriptor for the first parameter. */
2658 gfc_init_se (&argse, NULL);
2659 gfc_conv_expr_descriptor (&argse, arg->expr);
2660 gfc_add_block_to_block (&se->pre, &argse.pre);
2661 gfc_add_block_to_block (&se->post, &argse.post);
2663 desc = argse.expr;
2665 as = gfc_get_full_arrayspec_from_expr (arg->expr);
2667 if (INTEGER_CST_P (bound))
2669 if (((!as || as->type != AS_ASSUMED_RANK)
2670 && wi::geu_p (wi::to_wide (bound),
2671 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
2672 || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS))
2673 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2674 "dimension index", upper ? "UBOUND" : "LBOUND",
2675 &expr->where);
2678 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
2680 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2682 bound = gfc_evaluate_now (bound, &se->pre);
2683 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2684 bound, build_int_cst (TREE_TYPE (bound), 0));
2685 if (as && as->type == AS_ASSUMED_RANK)
2686 tmp = gfc_conv_descriptor_rank (desc);
2687 else
2688 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
2689 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2690 bound, fold_convert(TREE_TYPE (bound), tmp));
2691 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2692 logical_type_node, cond, tmp);
2693 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2694 gfc_msg_fault);
2698 /* Take care of the lbound shift for assumed-rank arrays, which are
2699 nonallocatable and nonpointers. Those has a lbound of 1. */
2700 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
2701 && ((arg->expr->ts.type != BT_CLASS
2702 && !arg->expr->symtree->n.sym->attr.allocatable
2703 && !arg->expr->symtree->n.sym->attr.pointer)
2704 || (arg->expr->ts.type == BT_CLASS
2705 && !CLASS_DATA (arg->expr)->attr.allocatable
2706 && !CLASS_DATA (arg->expr)->attr.class_pointer));
2708 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
2709 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
2711 /* 13.14.53: Result value for LBOUND
2713 Case (i): For an array section or for an array expression other than a
2714 whole array or array structure component, LBOUND(ARRAY, DIM)
2715 has the value 1. For a whole array or array structure
2716 component, LBOUND(ARRAY, DIM) has the value:
2717 (a) equal to the lower bound for subscript DIM of ARRAY if
2718 dimension DIM of ARRAY does not have extent zero
2719 or if ARRAY is an assumed-size array of rank DIM,
2720 or (b) 1 otherwise.
2722 13.14.113: Result value for UBOUND
2724 Case (i): For an array section or for an array expression other than a
2725 whole array or array structure component, UBOUND(ARRAY, DIM)
2726 has the value equal to the number of elements in the given
2727 dimension; otherwise, it has a value equal to the upper bound
2728 for subscript DIM of ARRAY if dimension DIM of ARRAY does
2729 not have size zero and has value zero if dimension DIM has
2730 size zero. */
2732 if (!upper && assumed_rank_lb_one)
2733 se->expr = gfc_index_one_node;
2734 else if (as)
2736 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
2738 cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2739 ubound, lbound);
2740 cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
2741 stride, gfc_index_zero_node);
2742 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2743 logical_type_node, cond3, cond1);
2744 cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2745 stride, gfc_index_zero_node);
2747 if (upper)
2749 tree cond5;
2750 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2751 logical_type_node, cond3, cond4);
2752 cond5 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2753 gfc_index_one_node, lbound);
2754 cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2755 logical_type_node, cond4, cond5);
2757 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2758 logical_type_node, cond, cond5);
2760 if (assumed_rank_lb_one)
2762 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2763 gfc_array_index_type, ubound, lbound);
2764 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2765 gfc_array_index_type, tmp, gfc_index_one_node);
2767 else
2768 tmp = ubound;
2770 se->expr = fold_build3_loc (input_location, COND_EXPR,
2771 gfc_array_index_type, cond,
2772 tmp, gfc_index_zero_node);
2774 else
2776 if (as->type == AS_ASSUMED_SIZE)
2777 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2778 bound, build_int_cst (TREE_TYPE (bound),
2779 arg->expr->rank - 1));
2780 else
2781 cond = logical_false_node;
2783 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2784 logical_type_node, cond3, cond4);
2785 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2786 logical_type_node, cond, cond1);
2788 se->expr = fold_build3_loc (input_location, COND_EXPR,
2789 gfc_array_index_type, cond,
2790 lbound, gfc_index_one_node);
2793 else
2795 if (upper)
2797 size = fold_build2_loc (input_location, MINUS_EXPR,
2798 gfc_array_index_type, ubound, lbound);
2799 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
2800 gfc_array_index_type, size,
2801 gfc_index_one_node);
2802 se->expr = fold_build2_loc (input_location, MAX_EXPR,
2803 gfc_array_index_type, se->expr,
2804 gfc_index_zero_node);
2806 else
2807 se->expr = gfc_index_one_node;
2810 type = gfc_typenode_for_spec (&expr->ts);
2811 se->expr = convert (type, se->expr);
2815 static void
2816 conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
2818 gfc_actual_arglist *arg;
2819 gfc_actual_arglist *arg2;
2820 gfc_se argse;
2821 tree bound, resbound, resbound2, desc, cond, tmp;
2822 tree type;
2823 int corank;
2825 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
2826 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
2827 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
2829 arg = expr->value.function.actual;
2830 arg2 = arg->next;
2832 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
2833 corank = gfc_get_corank (arg->expr);
2835 gfc_init_se (&argse, NULL);
2836 argse.want_coarray = 1;
2838 gfc_conv_expr_descriptor (&argse, arg->expr);
2839 gfc_add_block_to_block (&se->pre, &argse.pre);
2840 gfc_add_block_to_block (&se->post, &argse.post);
2841 desc = argse.expr;
2843 if (se->ss)
2845 /* Create an implicit second parameter from the loop variable. */
2846 gcc_assert (!arg2->expr);
2847 gcc_assert (corank > 0);
2848 gcc_assert (se->loop->dimen == 1);
2849 gcc_assert (se->ss->info->expr == expr);
2851 bound = se->loop->loopvar[0];
2852 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2853 bound, gfc_rank_cst[arg->expr->rank]);
2854 gfc_advance_se_ss_chain (se);
2856 else
2858 /* use the passed argument. */
2859 gcc_assert (arg2->expr);
2860 gfc_init_se (&argse, NULL);
2861 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2862 gfc_add_block_to_block (&se->pre, &argse.pre);
2863 bound = argse.expr;
2865 if (INTEGER_CST_P (bound))
2867 if (wi::ltu_p (wi::to_wide (bound), 1)
2868 || wi::gtu_p (wi::to_wide (bound),
2869 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2870 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2871 "dimension index", expr->value.function.isym->name,
2872 &expr->where);
2874 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2876 bound = gfc_evaluate_now (bound, &se->pre);
2877 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2878 bound, build_int_cst (TREE_TYPE (bound), 1));
2879 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2880 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2881 bound, tmp);
2882 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2883 logical_type_node, cond, tmp);
2884 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2885 gfc_msg_fault);
2889 /* Subtract 1 to get to zero based and add dimensions. */
2890 switch (arg->expr->rank)
2892 case 0:
2893 bound = fold_build2_loc (input_location, MINUS_EXPR,
2894 gfc_array_index_type, bound,
2895 gfc_index_one_node);
2896 case 1:
2897 break;
2898 default:
2899 bound = fold_build2_loc (input_location, PLUS_EXPR,
2900 gfc_array_index_type, bound,
2901 gfc_rank_cst[arg->expr->rank - 1]);
2905 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
2907 /* Handle UCOBOUND with special handling of the last codimension. */
2908 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
2910 /* Last codimension: For -fcoarray=single just return
2911 the lcobound - otherwise add
2912 ceiling (real (num_images ()) / real (size)) - 1
2913 = (num_images () + size - 1) / size - 1
2914 = (num_images - 1) / size(),
2915 where size is the product of the extent of all but the last
2916 codimension. */
2918 if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
2920 tree cosize;
2922 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
2923 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
2924 2, integer_zero_node,
2925 build_int_cst (integer_type_node, -1));
2926 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2927 gfc_array_index_type,
2928 fold_convert (gfc_array_index_type, tmp),
2929 build_int_cst (gfc_array_index_type, 1));
2930 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
2931 gfc_array_index_type, tmp,
2932 fold_convert (gfc_array_index_type, cosize));
2933 resbound = fold_build2_loc (input_location, PLUS_EXPR,
2934 gfc_array_index_type, resbound, tmp);
2936 else if (flag_coarray != GFC_FCOARRAY_SINGLE)
2938 /* ubound = lbound + num_images() - 1. */
2939 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
2940 2, integer_zero_node,
2941 build_int_cst (integer_type_node, -1));
2942 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2943 gfc_array_index_type,
2944 fold_convert (gfc_array_index_type, tmp),
2945 build_int_cst (gfc_array_index_type, 1));
2946 resbound = fold_build2_loc (input_location, PLUS_EXPR,
2947 gfc_array_index_type, resbound, tmp);
2950 if (corank > 1)
2952 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2953 bound,
2954 build_int_cst (TREE_TYPE (bound),
2955 arg->expr->rank + corank - 1));
2957 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
2958 se->expr = fold_build3_loc (input_location, COND_EXPR,
2959 gfc_array_index_type, cond,
2960 resbound, resbound2);
2962 else
2963 se->expr = resbound;
2965 else
2966 se->expr = resbound;
2968 type = gfc_typenode_for_spec (&expr->ts);
2969 se->expr = convert (type, se->expr);
2973 static void
2974 conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
2976 gfc_actual_arglist *array_arg;
2977 gfc_actual_arglist *dim_arg;
2978 gfc_se argse;
2979 tree desc, tmp;
2981 array_arg = expr->value.function.actual;
2982 dim_arg = array_arg->next;
2984 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
2986 gfc_init_se (&argse, NULL);
2987 gfc_conv_expr_descriptor (&argse, array_arg->expr);
2988 gfc_add_block_to_block (&se->pre, &argse.pre);
2989 gfc_add_block_to_block (&se->post, &argse.post);
2990 desc = argse.expr;
2992 gcc_assert (dim_arg->expr);
2993 gfc_init_se (&argse, NULL);
2994 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
2995 gfc_add_block_to_block (&se->pre, &argse.pre);
2996 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2997 argse.expr, gfc_index_one_node);
2998 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
3002 static void
3003 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
3005 tree arg, cabs;
3007 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3009 switch (expr->value.function.actual->expr->ts.type)
3011 case BT_INTEGER:
3012 case BT_REAL:
3013 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
3014 arg);
3015 break;
3017 case BT_COMPLEX:
3018 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
3019 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
3020 break;
3022 default:
3023 gcc_unreachable ();
3028 /* Create a complex value from one or two real components. */
3030 static void
3031 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
3033 tree real;
3034 tree imag;
3035 tree type;
3036 tree *args;
3037 unsigned int num_args;
3039 num_args = gfc_intrinsic_argument_list_length (expr);
3040 args = XALLOCAVEC (tree, num_args);
3042 type = gfc_typenode_for_spec (&expr->ts);
3043 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3044 real = convert (TREE_TYPE (type), args[0]);
3045 if (both)
3046 imag = convert (TREE_TYPE (type), args[1]);
3047 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
3049 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
3050 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
3051 imag = convert (TREE_TYPE (type), imag);
3053 else
3054 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
3056 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
3060 /* Remainder function MOD(A, P) = A - INT(A / P) * P
3061 MODULO(A, P) = A - FLOOR (A / P) * P
3063 The obvious algorithms above are numerically instable for large
3064 arguments, hence these intrinsics are instead implemented via calls
3065 to the fmod family of functions. It is the responsibility of the
3066 user to ensure that the second argument is non-zero. */
3068 static void
3069 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
3071 tree type;
3072 tree tmp;
3073 tree test;
3074 tree test2;
3075 tree fmod;
3076 tree zero;
3077 tree args[2];
3079 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3081 switch (expr->ts.type)
3083 case BT_INTEGER:
3084 /* Integer case is easy, we've got a builtin op. */
3085 type = TREE_TYPE (args[0]);
3087 if (modulo)
3088 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
3089 args[0], args[1]);
3090 else
3091 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3092 args[0], args[1]);
3093 break;
3095 case BT_REAL:
3096 fmod = NULL_TREE;
3097 /* Check if we have a builtin fmod. */
3098 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
3100 /* The builtin should always be available. */
3101 gcc_assert (fmod != NULL_TREE);
3103 tmp = build_addr (fmod);
3104 se->expr = build_call_array_loc (input_location,
3105 TREE_TYPE (TREE_TYPE (fmod)),
3106 tmp, 2, args);
3107 if (modulo == 0)
3108 return;
3110 type = TREE_TYPE (args[0]);
3112 args[0] = gfc_evaluate_now (args[0], &se->pre);
3113 args[1] = gfc_evaluate_now (args[1], &se->pre);
3115 /* Definition:
3116 modulo = arg - floor (arg/arg2) * arg2
3118 In order to calculate the result accurately, we use the fmod
3119 function as follows.
3121 res = fmod (arg, arg2);
3122 if (res)
3124 if ((arg < 0) xor (arg2 < 0))
3125 res += arg2;
3127 else
3128 res = copysign (0., arg2);
3130 => As two nested ternary exprs:
3132 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3133 : copysign (0., arg2);
3137 zero = gfc_build_const (type, integer_zero_node);
3138 tmp = gfc_evaluate_now (se->expr, &se->pre);
3139 if (!flag_signed_zeros)
3141 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3142 args[0], zero);
3143 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3144 args[1], zero);
3145 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3146 logical_type_node, test, test2);
3147 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3148 tmp, zero);
3149 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3150 logical_type_node, test, test2);
3151 test = gfc_evaluate_now (test, &se->pre);
3152 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3153 fold_build2_loc (input_location,
3154 PLUS_EXPR,
3155 type, tmp, args[1]),
3156 tmp);
3158 else
3160 tree expr1, copysign, cscall;
3161 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
3162 expr->ts.kind);
3163 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3164 args[0], zero);
3165 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3166 args[1], zero);
3167 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3168 logical_type_node, test, test2);
3169 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
3170 fold_build2_loc (input_location,
3171 PLUS_EXPR,
3172 type, tmp, args[1]),
3173 tmp);
3174 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3175 tmp, zero);
3176 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
3177 args[1]);
3178 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3179 expr1, cscall);
3181 return;
3183 default:
3184 gcc_unreachable ();
3188 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3189 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3190 where the right shifts are logical (i.e. 0's are shifted in).
3191 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3192 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3193 DSHIFTL(I,J,0) = I
3194 DSHIFTL(I,J,BITSIZE) = J
3195 DSHIFTR(I,J,0) = J
3196 DSHIFTR(I,J,BITSIZE) = I. */
3198 static void
3199 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
3201 tree type, utype, stype, arg1, arg2, shift, res, left, right;
3202 tree args[3], cond, tmp;
3203 int bitsize;
3205 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3207 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
3208 type = TREE_TYPE (args[0]);
3209 bitsize = TYPE_PRECISION (type);
3210 utype = unsigned_type_for (type);
3211 stype = TREE_TYPE (args[2]);
3213 arg1 = gfc_evaluate_now (args[0], &se->pre);
3214 arg2 = gfc_evaluate_now (args[1], &se->pre);
3215 shift = gfc_evaluate_now (args[2], &se->pre);
3217 /* The generic case. */
3218 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
3219 build_int_cst (stype, bitsize), shift);
3220 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3221 arg1, dshiftl ? shift : tmp);
3223 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
3224 fold_convert (utype, arg2), dshiftl ? tmp : shift);
3225 right = fold_convert (type, right);
3227 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
3229 /* Special cases. */
3230 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3231 build_int_cst (stype, 0));
3232 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3233 dshiftl ? arg1 : arg2, res);
3235 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
3236 build_int_cst (stype, bitsize));
3237 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3238 dshiftl ? arg2 : arg1, res);
3240 se->expr = res;
3244 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3246 static void
3247 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
3249 tree val;
3250 tree tmp;
3251 tree type;
3252 tree zero;
3253 tree args[2];
3255 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3256 type = TREE_TYPE (args[0]);
3258 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
3259 val = gfc_evaluate_now (val, &se->pre);
3261 zero = gfc_build_const (type, integer_zero_node);
3262 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node, val, zero);
3263 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
3267 /* SIGN(A, B) is absolute value of A times sign of B.
3268 The real value versions use library functions to ensure the correct
3269 handling of negative zero. Integer case implemented as:
3270 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3273 static void
3274 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
3276 tree tmp;
3277 tree type;
3278 tree args[2];
3280 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3281 if (expr->ts.type == BT_REAL)
3283 tree abs;
3285 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
3286 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
3288 /* We explicitly have to ignore the minus sign. We do so by using
3289 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3290 if (!flag_sign_zero
3291 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
3293 tree cond, zero;
3294 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
3295 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3296 args[1], zero);
3297 se->expr = fold_build3_loc (input_location, COND_EXPR,
3298 TREE_TYPE (args[0]), cond,
3299 build_call_expr_loc (input_location, abs, 1,
3300 args[0]),
3301 build_call_expr_loc (input_location, tmp, 2,
3302 args[0], args[1]));
3304 else
3305 se->expr = build_call_expr_loc (input_location, tmp, 2,
3306 args[0], args[1]);
3307 return;
3310 /* Having excluded floating point types, we know we are now dealing
3311 with signed integer types. */
3312 type = TREE_TYPE (args[0]);
3314 /* Args[0] is used multiple times below. */
3315 args[0] = gfc_evaluate_now (args[0], &se->pre);
3317 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3318 the signs of A and B are the same, and of all ones if they differ. */
3319 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
3320 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
3321 build_int_cst (type, TYPE_PRECISION (type) - 1));
3322 tmp = gfc_evaluate_now (tmp, &se->pre);
3324 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3325 is all ones (i.e. -1). */
3326 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
3327 fold_build2_loc (input_location, PLUS_EXPR,
3328 type, args[0], tmp), tmp);
3332 /* Test for the presence of an optional argument. */
3334 static void
3335 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
3337 gfc_expr *arg;
3339 arg = expr->value.function.actual->expr;
3340 gcc_assert (arg->expr_type == EXPR_VARIABLE);
3341 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
3342 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3346 /* Calculate the double precision product of two single precision values. */
3348 static void
3349 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
3351 tree type;
3352 tree args[2];
3354 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3356 /* Convert the args to double precision before multiplying. */
3357 type = gfc_typenode_for_spec (&expr->ts);
3358 args[0] = convert (type, args[0]);
3359 args[1] = convert (type, args[1]);
3360 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
3361 args[1]);
3365 /* Return a length one character string containing an ascii character. */
3367 static void
3368 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
3370 tree arg[2];
3371 tree var;
3372 tree type;
3373 unsigned int num_args;
3375 num_args = gfc_intrinsic_argument_list_length (expr);
3376 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
3378 type = gfc_get_char_type (expr->ts.kind);
3379 var = gfc_create_var (type, "char");
3381 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
3382 gfc_add_modify (&se->pre, var, arg[0]);
3383 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
3384 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
3388 static void
3389 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
3391 tree var;
3392 tree len;
3393 tree tmp;
3394 tree cond;
3395 tree fndecl;
3396 tree *args;
3397 unsigned int num_args;
3399 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3400 args = XALLOCAVEC (tree, num_args);
3402 var = gfc_create_var (pchar_type_node, "pstr");
3403 len = gfc_create_var (gfc_charlen_type_node, "len");
3405 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3406 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3407 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3409 fndecl = build_addr (gfor_fndecl_ctime);
3410 tmp = build_call_array_loc (input_location,
3411 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
3412 fndecl, num_args, args);
3413 gfc_add_expr_to_block (&se->pre, tmp);
3415 /* Free the temporary afterwards, if necessary. */
3416 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3417 len, build_int_cst (TREE_TYPE (len), 0));
3418 tmp = gfc_call_free (var);
3419 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3420 gfc_add_expr_to_block (&se->post, tmp);
3422 se->expr = var;
3423 se->string_length = len;
3427 static void
3428 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
3430 tree var;
3431 tree len;
3432 tree tmp;
3433 tree cond;
3434 tree fndecl;
3435 tree *args;
3436 unsigned int num_args;
3438 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3439 args = XALLOCAVEC (tree, num_args);
3441 var = gfc_create_var (pchar_type_node, "pstr");
3442 len = gfc_create_var (gfc_charlen_type_node, "len");
3444 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3445 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3446 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3448 fndecl = build_addr (gfor_fndecl_fdate);
3449 tmp = build_call_array_loc (input_location,
3450 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
3451 fndecl, num_args, args);
3452 gfc_add_expr_to_block (&se->pre, tmp);
3454 /* Free the temporary afterwards, if necessary. */
3455 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3456 len, build_int_cst (TREE_TYPE (len), 0));
3457 tmp = gfc_call_free (var);
3458 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3459 gfc_add_expr_to_block (&se->post, tmp);
3461 se->expr = var;
3462 se->string_length = len;
3466 /* Generate a direct call to free() for the FREE subroutine. */
3468 static tree
3469 conv_intrinsic_free (gfc_code *code)
3471 stmtblock_t block;
3472 gfc_se argse;
3473 tree arg, call;
3475 gfc_init_se (&argse, NULL);
3476 gfc_conv_expr (&argse, code->ext.actual->expr);
3477 arg = fold_convert (ptr_type_node, argse.expr);
3479 gfc_init_block (&block);
3480 call = build_call_expr_loc (input_location,
3481 builtin_decl_explicit (BUILT_IN_FREE), 1, arg);
3482 gfc_add_expr_to_block (&block, call);
3483 return gfc_finish_block (&block);
3487 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3488 conversions. */
3490 static tree
3491 conv_intrinsic_system_clock (gfc_code *code)
3493 stmtblock_t block;
3494 gfc_se count_se, count_rate_se, count_max_se;
3495 tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
3496 tree tmp;
3497 int least;
3499 gfc_expr *count = code->ext.actual->expr;
3500 gfc_expr *count_rate = code->ext.actual->next->expr;
3501 gfc_expr *count_max = code->ext.actual->next->next->expr;
3503 /* Evaluate our arguments. */
3504 if (count)
3506 gfc_init_se (&count_se, NULL);
3507 gfc_conv_expr (&count_se, count);
3510 if (count_rate)
3512 gfc_init_se (&count_rate_se, NULL);
3513 gfc_conv_expr (&count_rate_se, count_rate);
3516 if (count_max)
3518 gfc_init_se (&count_max_se, NULL);
3519 gfc_conv_expr (&count_max_se, count_max);
3522 /* Find the smallest kind found of the arguments. */
3523 least = 16;
3524 least = (count && count->ts.kind < least) ? count->ts.kind : least;
3525 least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
3526 : least;
3527 least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
3528 : least;
3530 /* Prepare temporary variables. */
3532 if (count)
3534 if (least >= 8)
3535 arg1 = gfc_create_var (gfc_get_int_type (8), "count");
3536 else if (least == 4)
3537 arg1 = gfc_create_var (gfc_get_int_type (4), "count");
3538 else if (count->ts.kind == 1)
3539 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
3540 count->ts.kind);
3541 else
3542 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
3543 count->ts.kind);
3546 if (count_rate)
3548 if (least >= 8)
3549 arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
3550 else if (least == 4)
3551 arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
3552 else
3553 arg2 = integer_zero_node;
3556 if (count_max)
3558 if (least >= 8)
3559 arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
3560 else if (least == 4)
3561 arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
3562 else
3563 arg3 = integer_zero_node;
3566 /* Make the function call. */
3567 gfc_init_block (&block);
3569 if (least <= 2)
3571 if (least == 1)
3573 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3574 : null_pointer_node;
3575 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3576 : null_pointer_node;
3577 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3578 : null_pointer_node;
3581 if (least == 2)
3583 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3584 : null_pointer_node;
3585 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3586 : null_pointer_node;
3587 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3588 : null_pointer_node;
3591 else
3593 if (least == 4)
3595 tmp = build_call_expr_loc (input_location,
3596 gfor_fndecl_system_clock4, 3,
3597 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3598 : null_pointer_node,
3599 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3600 : null_pointer_node,
3601 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3602 : null_pointer_node);
3603 gfc_add_expr_to_block (&block, tmp);
3605 /* Handle kind>=8, 10, or 16 arguments */
3606 if (least >= 8)
3608 tmp = build_call_expr_loc (input_location,
3609 gfor_fndecl_system_clock8, 3,
3610 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3611 : null_pointer_node,
3612 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3613 : null_pointer_node,
3614 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3615 : null_pointer_node);
3616 gfc_add_expr_to_block (&block, tmp);
3620 /* And store values back if needed. */
3621 if (arg1 && arg1 != count_se.expr)
3622 gfc_add_modify (&block, count_se.expr,
3623 fold_convert (TREE_TYPE (count_se.expr), arg1));
3624 if (arg2 && arg2 != count_rate_se.expr)
3625 gfc_add_modify (&block, count_rate_se.expr,
3626 fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
3627 if (arg3 && arg3 != count_max_se.expr)
3628 gfc_add_modify (&block, count_max_se.expr,
3629 fold_convert (TREE_TYPE (count_max_se.expr), arg3));
3631 return gfc_finish_block (&block);
3635 /* Return a character string containing the tty name. */
3637 static void
3638 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
3640 tree var;
3641 tree len;
3642 tree tmp;
3643 tree cond;
3644 tree fndecl;
3645 tree *args;
3646 unsigned int num_args;
3648 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3649 args = XALLOCAVEC (tree, num_args);
3651 var = gfc_create_var (pchar_type_node, "pstr");
3652 len = gfc_create_var (gfc_charlen_type_node, "len");
3654 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3655 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3656 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3658 fndecl = build_addr (gfor_fndecl_ttynam);
3659 tmp = build_call_array_loc (input_location,
3660 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
3661 fndecl, num_args, args);
3662 gfc_add_expr_to_block (&se->pre, tmp);
3664 /* Free the temporary afterwards, if necessary. */
3665 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3666 len, build_int_cst (TREE_TYPE (len), 0));
3667 tmp = gfc_call_free (var);
3668 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3669 gfc_add_expr_to_block (&se->post, tmp);
3671 se->expr = var;
3672 se->string_length = len;
3676 /* Get the minimum/maximum value of all the parameters.
3677 minmax (a1, a2, a3, ...)
3679 mvar = a1;
3680 if (a2 .op. mvar || isnan (mvar))
3681 mvar = a2;
3682 if (a3 .op. mvar || isnan (mvar))
3683 mvar = a3;
3685 return mvar
3689 /* TODO: Mismatching types can occur when specific names are used.
3690 These should be handled during resolution. */
3691 static void
3692 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
3694 tree tmp;
3695 tree mvar;
3696 tree val;
3697 tree thencase;
3698 tree *args;
3699 tree type;
3700 gfc_actual_arglist *argexpr;
3701 unsigned int i, nargs;
3703 nargs = gfc_intrinsic_argument_list_length (expr);
3704 args = XALLOCAVEC (tree, nargs);
3706 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
3707 type = gfc_typenode_for_spec (&expr->ts);
3709 argexpr = expr->value.function.actual;
3710 if (TREE_TYPE (args[0]) != type)
3711 args[0] = convert (type, args[0]);
3712 /* Only evaluate the argument once. */
3713 if (!VAR_P (args[0]) && !TREE_CONSTANT (args[0]))
3714 args[0] = gfc_evaluate_now (args[0], &se->pre);
3716 mvar = gfc_create_var (type, "M");
3717 gfc_add_modify (&se->pre, mvar, args[0]);
3718 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
3720 tree cond, isnan;
3722 val = args[i];
3724 /* Handle absent optional arguments by ignoring the comparison. */
3725 if (argexpr->expr->expr_type == EXPR_VARIABLE
3726 && argexpr->expr->symtree->n.sym->attr.optional
3727 && TREE_CODE (val) == INDIRECT_REF)
3728 cond = fold_build2_loc (input_location,
3729 NE_EXPR, logical_type_node,
3730 TREE_OPERAND (val, 0),
3731 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
3732 else
3734 cond = NULL_TREE;
3736 /* Only evaluate the argument once. */
3737 if (!VAR_P (val) && !TREE_CONSTANT (val))
3738 val = gfc_evaluate_now (val, &se->pre);
3741 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
3743 tmp = fold_build2_loc (input_location, op, logical_type_node,
3744 convert (type, val), mvar);
3746 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
3747 __builtin_isnan might be made dependent on that module being loaded,
3748 to help performance of programs that don't rely on IEEE semantics. */
3749 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
3751 isnan = build_call_expr_loc (input_location,
3752 builtin_decl_explicit (BUILT_IN_ISNAN),
3753 1, mvar);
3754 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3755 logical_type_node, tmp,
3756 fold_convert (logical_type_node, isnan));
3758 tmp = build3_v (COND_EXPR, tmp, thencase,
3759 build_empty_stmt (input_location));
3761 if (cond != NULL_TREE)
3762 tmp = build3_v (COND_EXPR, cond, tmp,
3763 build_empty_stmt (input_location));
3765 gfc_add_expr_to_block (&se->pre, tmp);
3766 argexpr = argexpr->next;
3768 se->expr = mvar;
3772 /* Generate library calls for MIN and MAX intrinsics for character
3773 variables. */
3774 static void
3775 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
3777 tree *args;
3778 tree var, len, fndecl, tmp, cond, function;
3779 unsigned int nargs;
3781 nargs = gfc_intrinsic_argument_list_length (expr);
3782 args = XALLOCAVEC (tree, nargs + 4);
3783 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
3785 /* Create the result variables. */
3786 len = gfc_create_var (gfc_charlen_type_node, "len");
3787 args[0] = gfc_build_addr_expr (NULL_TREE, len);
3788 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
3789 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
3790 args[2] = build_int_cst (integer_type_node, op);
3791 args[3] = build_int_cst (integer_type_node, nargs / 2);
3793 if (expr->ts.kind == 1)
3794 function = gfor_fndecl_string_minmax;
3795 else if (expr->ts.kind == 4)
3796 function = gfor_fndecl_string_minmax_char4;
3797 else
3798 gcc_unreachable ();
3800 /* Make the function call. */
3801 fndecl = build_addr (function);
3802 tmp = build_call_array_loc (input_location,
3803 TREE_TYPE (TREE_TYPE (function)), fndecl,
3804 nargs + 4, args);
3805 gfc_add_expr_to_block (&se->pre, tmp);
3807 /* Free the temporary afterwards, if necessary. */
3808 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3809 len, build_int_cst (TREE_TYPE (len), 0));
3810 tmp = gfc_call_free (var);
3811 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3812 gfc_add_expr_to_block (&se->post, tmp);
3814 se->expr = var;
3815 se->string_length = len;
3819 /* Create a symbol node for this intrinsic. The symbol from the frontend
3820 has the generic name. */
3822 static gfc_symbol *
3823 gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
3825 gfc_symbol *sym;
3827 /* TODO: Add symbols for intrinsic function to the global namespace. */
3828 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
3829 sym = gfc_new_symbol (expr->value.function.name, NULL);
3831 sym->ts = expr->ts;
3832 sym->attr.external = 1;
3833 sym->attr.function = 1;
3834 sym->attr.always_explicit = 1;
3835 sym->attr.proc = PROC_INTRINSIC;
3836 sym->attr.flavor = FL_PROCEDURE;
3837 sym->result = sym;
3838 if (expr->rank > 0)
3840 sym->attr.dimension = 1;
3841 sym->as = gfc_get_array_spec ();
3842 sym->as->type = AS_ASSUMED_SHAPE;
3843 sym->as->rank = expr->rank;
3846 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
3847 ignore_optional ? expr->value.function.actual
3848 : NULL);
3850 return sym;
3853 /* Generate a call to an external intrinsic function. */
3854 static void
3855 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
3857 gfc_symbol *sym;
3858 vec<tree, va_gc> *append_args;
3860 gcc_assert (!se->ss || se->ss->info->expr == expr);
3862 if (se->ss)
3863 gcc_assert (expr->rank > 0);
3864 else
3865 gcc_assert (expr->rank == 0);
3867 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
3869 /* Calls to libgfortran_matmul need to be appended special arguments,
3870 to be able to call the BLAS ?gemm functions if required and possible. */
3871 append_args = NULL;
3872 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
3873 && sym->ts.type != BT_LOGICAL)
3875 tree cint = gfc_get_int_type (gfc_c_int_kind);
3877 if (flag_external_blas
3878 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
3879 && (sym->ts.kind == 4 || sym->ts.kind == 8))
3881 tree gemm_fndecl;
3883 if (sym->ts.type == BT_REAL)
3885 if (sym->ts.kind == 4)
3886 gemm_fndecl = gfor_fndecl_sgemm;
3887 else
3888 gemm_fndecl = gfor_fndecl_dgemm;
3890 else
3892 if (sym->ts.kind == 4)
3893 gemm_fndecl = gfor_fndecl_cgemm;
3894 else
3895 gemm_fndecl = gfor_fndecl_zgemm;
3898 vec_alloc (append_args, 3);
3899 append_args->quick_push (build_int_cst (cint, 1));
3900 append_args->quick_push (build_int_cst (cint,
3901 flag_blas_matmul_limit));
3902 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
3903 gemm_fndecl));
3905 else
3907 vec_alloc (append_args, 3);
3908 append_args->quick_push (build_int_cst (cint, 0));
3909 append_args->quick_push (build_int_cst (cint, 0));
3910 append_args->quick_push (null_pointer_node);
3914 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
3915 append_args);
3916 gfc_free_symbol (sym);
3919 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
3920 Implemented as
3921 any(a)
3923 forall (i=...)
3924 if (a[i] != 0)
3925 return 1
3926 end forall
3927 return 0
3929 all(a)
3931 forall (i=...)
3932 if (a[i] == 0)
3933 return 0
3934 end forall
3935 return 1
3938 static void
3939 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
3941 tree resvar;
3942 stmtblock_t block;
3943 stmtblock_t body;
3944 tree type;
3945 tree tmp;
3946 tree found;
3947 gfc_loopinfo loop;
3948 gfc_actual_arglist *actual;
3949 gfc_ss *arrayss;
3950 gfc_se arrayse;
3951 tree exit_label;
3953 if (se->ss)
3955 gfc_conv_intrinsic_funcall (se, expr);
3956 return;
3959 actual = expr->value.function.actual;
3960 type = gfc_typenode_for_spec (&expr->ts);
3961 /* Initialize the result. */
3962 resvar = gfc_create_var (type, "test");
3963 if (op == EQ_EXPR)
3964 tmp = convert (type, boolean_true_node);
3965 else
3966 tmp = convert (type, boolean_false_node);
3967 gfc_add_modify (&se->pre, resvar, tmp);
3969 /* Walk the arguments. */
3970 arrayss = gfc_walk_expr (actual->expr);
3971 gcc_assert (arrayss != gfc_ss_terminator);
3973 /* Initialize the scalarizer. */
3974 gfc_init_loopinfo (&loop);
3975 exit_label = gfc_build_label_decl (NULL_TREE);
3976 TREE_USED (exit_label) = 1;
3977 gfc_add_ss_to_loop (&loop, arrayss);
3979 /* Initialize the loop. */
3980 gfc_conv_ss_startstride (&loop);
3981 gfc_conv_loop_setup (&loop, &expr->where);
3983 gfc_mark_ss_chain_used (arrayss, 1);
3984 /* Generate the loop body. */
3985 gfc_start_scalarized_body (&loop, &body);
3987 /* If the condition matches then set the return value. */
3988 gfc_start_block (&block);
3989 if (op == EQ_EXPR)
3990 tmp = convert (type, boolean_false_node);
3991 else
3992 tmp = convert (type, boolean_true_node);
3993 gfc_add_modify (&block, resvar, tmp);
3995 /* And break out of the loop. */
3996 tmp = build1_v (GOTO_EXPR, exit_label);
3997 gfc_add_expr_to_block (&block, tmp);
3999 found = gfc_finish_block (&block);
4001 /* Check this element. */
4002 gfc_init_se (&arrayse, NULL);
4003 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4004 arrayse.ss = arrayss;
4005 gfc_conv_expr_val (&arrayse, actual->expr);
4007 gfc_add_block_to_block (&body, &arrayse.pre);
4008 tmp = fold_build2_loc (input_location, op, logical_type_node, arrayse.expr,
4009 build_int_cst (TREE_TYPE (arrayse.expr), 0));
4010 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
4011 gfc_add_expr_to_block (&body, tmp);
4012 gfc_add_block_to_block (&body, &arrayse.post);
4014 gfc_trans_scalarizing_loops (&loop, &body);
4016 /* Add the exit label. */
4017 tmp = build1_v (LABEL_EXPR, exit_label);
4018 gfc_add_expr_to_block (&loop.pre, tmp);
4020 gfc_add_block_to_block (&se->pre, &loop.pre);
4021 gfc_add_block_to_block (&se->pre, &loop.post);
4022 gfc_cleanup_loop (&loop);
4024 se->expr = resvar;
4027 /* COUNT(A) = Number of true elements in A. */
4028 static void
4029 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
4031 tree resvar;
4032 tree type;
4033 stmtblock_t body;
4034 tree tmp;
4035 gfc_loopinfo loop;
4036 gfc_actual_arglist *actual;
4037 gfc_ss *arrayss;
4038 gfc_se arrayse;
4040 if (se->ss)
4042 gfc_conv_intrinsic_funcall (se, expr);
4043 return;
4046 actual = expr->value.function.actual;
4048 type = gfc_typenode_for_spec (&expr->ts);
4049 /* Initialize the result. */
4050 resvar = gfc_create_var (type, "count");
4051 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4053 /* Walk the arguments. */
4054 arrayss = gfc_walk_expr (actual->expr);
4055 gcc_assert (arrayss != gfc_ss_terminator);
4057 /* Initialize the scalarizer. */
4058 gfc_init_loopinfo (&loop);
4059 gfc_add_ss_to_loop (&loop, arrayss);
4061 /* Initialize the loop. */
4062 gfc_conv_ss_startstride (&loop);
4063 gfc_conv_loop_setup (&loop, &expr->where);
4065 gfc_mark_ss_chain_used (arrayss, 1);
4066 /* Generate the loop body. */
4067 gfc_start_scalarized_body (&loop, &body);
4069 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
4070 resvar, build_int_cst (TREE_TYPE (resvar), 1));
4071 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
4073 gfc_init_se (&arrayse, NULL);
4074 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4075 arrayse.ss = arrayss;
4076 gfc_conv_expr_val (&arrayse, actual->expr);
4077 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
4078 build_empty_stmt (input_location));
4080 gfc_add_block_to_block (&body, &arrayse.pre);
4081 gfc_add_expr_to_block (&body, tmp);
4082 gfc_add_block_to_block (&body, &arrayse.post);
4084 gfc_trans_scalarizing_loops (&loop, &body);
4086 gfc_add_block_to_block (&se->pre, &loop.pre);
4087 gfc_add_block_to_block (&se->pre, &loop.post);
4088 gfc_cleanup_loop (&loop);
4090 se->expr = resvar;
4094 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4095 struct and return the corresponding loopinfo. */
4097 static gfc_loopinfo *
4098 enter_nested_loop (gfc_se *se)
4100 se->ss = se->ss->nested_ss;
4101 gcc_assert (se->ss == se->ss->loop->ss);
4103 return se->ss->loop;
4107 /* Inline implementation of the sum and product intrinsics. */
4108 static void
4109 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
4110 bool norm2)
4112 tree resvar;
4113 tree scale = NULL_TREE;
4114 tree type;
4115 stmtblock_t body;
4116 stmtblock_t block;
4117 tree tmp;
4118 gfc_loopinfo loop, *ploop;
4119 gfc_actual_arglist *arg_array, *arg_mask;
4120 gfc_ss *arrayss = NULL;
4121 gfc_ss *maskss = NULL;
4122 gfc_se arrayse;
4123 gfc_se maskse;
4124 gfc_se *parent_se;
4125 gfc_expr *arrayexpr;
4126 gfc_expr *maskexpr;
4128 if (expr->rank > 0)
4130 gcc_assert (gfc_inline_intrinsic_function_p (expr));
4131 parent_se = se;
4133 else
4134 parent_se = NULL;
4136 type = gfc_typenode_for_spec (&expr->ts);
4137 /* Initialize the result. */
4138 resvar = gfc_create_var (type, "val");
4139 if (norm2)
4141 /* result = 0.0;
4142 scale = 1.0. */
4143 scale = gfc_create_var (type, "scale");
4144 gfc_add_modify (&se->pre, scale,
4145 gfc_build_const (type, integer_one_node));
4146 tmp = gfc_build_const (type, integer_zero_node);
4148 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4149 tmp = gfc_build_const (type, integer_zero_node);
4150 else if (op == NE_EXPR)
4151 /* PARITY. */
4152 tmp = convert (type, boolean_false_node);
4153 else if (op == BIT_AND_EXPR)
4154 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
4155 type, integer_one_node));
4156 else
4157 tmp = gfc_build_const (type, integer_one_node);
4159 gfc_add_modify (&se->pre, resvar, tmp);
4161 arg_array = expr->value.function.actual;
4163 arrayexpr = arg_array->expr;
4165 if (op == NE_EXPR || norm2)
4166 /* PARITY and NORM2. */
4167 maskexpr = NULL;
4168 else
4170 arg_mask = arg_array->next->next;
4171 gcc_assert (arg_mask != NULL);
4172 maskexpr = arg_mask->expr;
4175 if (expr->rank == 0)
4177 /* Walk the arguments. */
4178 arrayss = gfc_walk_expr (arrayexpr);
4179 gcc_assert (arrayss != gfc_ss_terminator);
4181 if (maskexpr && maskexpr->rank > 0)
4183 maskss = gfc_walk_expr (maskexpr);
4184 gcc_assert (maskss != gfc_ss_terminator);
4186 else
4187 maskss = NULL;
4189 /* Initialize the scalarizer. */
4190 gfc_init_loopinfo (&loop);
4191 gfc_add_ss_to_loop (&loop, arrayss);
4192 if (maskexpr && maskexpr->rank > 0)
4193 gfc_add_ss_to_loop (&loop, maskss);
4195 /* Initialize the loop. */
4196 gfc_conv_ss_startstride (&loop);
4197 gfc_conv_loop_setup (&loop, &expr->where);
4199 gfc_mark_ss_chain_used (arrayss, 1);
4200 if (maskexpr && maskexpr->rank > 0)
4201 gfc_mark_ss_chain_used (maskss, 1);
4203 ploop = &loop;
4205 else
4206 /* All the work has been done in the parent loops. */
4207 ploop = enter_nested_loop (se);
4209 gcc_assert (ploop);
4211 /* Generate the loop body. */
4212 gfc_start_scalarized_body (ploop, &body);
4214 /* If we have a mask, only add this element if the mask is set. */
4215 if (maskexpr && maskexpr->rank > 0)
4217 gfc_init_se (&maskse, parent_se);
4218 gfc_copy_loopinfo_to_se (&maskse, ploop);
4219 if (expr->rank == 0)
4220 maskse.ss = maskss;
4221 gfc_conv_expr_val (&maskse, maskexpr);
4222 gfc_add_block_to_block (&body, &maskse.pre);
4224 gfc_start_block (&block);
4226 else
4227 gfc_init_block (&block);
4229 /* Do the actual summation/product. */
4230 gfc_init_se (&arrayse, parent_se);
4231 gfc_copy_loopinfo_to_se (&arrayse, ploop);
4232 if (expr->rank == 0)
4233 arrayse.ss = arrayss;
4234 gfc_conv_expr_val (&arrayse, arrayexpr);
4235 gfc_add_block_to_block (&block, &arrayse.pre);
4237 if (norm2)
4239 /* if (x (i) != 0.0)
4241 absX = abs(x(i))
4242 if (absX > scale)
4244 val = scale/absX;
4245 result = 1.0 + result * val * val;
4246 scale = absX;
4248 else
4250 val = absX/scale;
4251 result += val * val;
4253 } */
4254 tree res1, res2, cond, absX, val;
4255 stmtblock_t ifblock1, ifblock2, ifblock3;
4257 gfc_init_block (&ifblock1);
4259 absX = gfc_create_var (type, "absX");
4260 gfc_add_modify (&ifblock1, absX,
4261 fold_build1_loc (input_location, ABS_EXPR, type,
4262 arrayse.expr));
4263 val = gfc_create_var (type, "val");
4264 gfc_add_expr_to_block (&ifblock1, val);
4266 gfc_init_block (&ifblock2);
4267 gfc_add_modify (&ifblock2, val,
4268 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
4269 absX));
4270 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4271 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
4272 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
4273 gfc_build_const (type, integer_one_node));
4274 gfc_add_modify (&ifblock2, resvar, res1);
4275 gfc_add_modify (&ifblock2, scale, absX);
4276 res1 = gfc_finish_block (&ifblock2);
4278 gfc_init_block (&ifblock3);
4279 gfc_add_modify (&ifblock3, val,
4280 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
4281 scale));
4282 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4283 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
4284 gfc_add_modify (&ifblock3, resvar, res2);
4285 res2 = gfc_finish_block (&ifblock3);
4287 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
4288 absX, scale);
4289 tmp = build3_v (COND_EXPR, cond, res1, res2);
4290 gfc_add_expr_to_block (&ifblock1, tmp);
4291 tmp = gfc_finish_block (&ifblock1);
4293 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
4294 arrayse.expr,
4295 gfc_build_const (type, integer_zero_node));
4297 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4298 gfc_add_expr_to_block (&block, tmp);
4300 else
4302 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
4303 gfc_add_modify (&block, resvar, tmp);
4306 gfc_add_block_to_block (&block, &arrayse.post);
4308 if (maskexpr && maskexpr->rank > 0)
4310 /* We enclose the above in if (mask) {...} . */
4312 tmp = gfc_finish_block (&block);
4313 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4314 build_empty_stmt (input_location));
4316 else
4317 tmp = gfc_finish_block (&block);
4318 gfc_add_expr_to_block (&body, tmp);
4320 gfc_trans_scalarizing_loops (ploop, &body);
4322 /* For a scalar mask, enclose the loop in an if statement. */
4323 if (maskexpr && maskexpr->rank == 0)
4325 gfc_init_block (&block);
4326 gfc_add_block_to_block (&block, &ploop->pre);
4327 gfc_add_block_to_block (&block, &ploop->post);
4328 tmp = gfc_finish_block (&block);
4330 if (expr->rank > 0)
4332 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
4333 build_empty_stmt (input_location));
4334 gfc_advance_se_ss_chain (se);
4336 else
4338 gcc_assert (expr->rank == 0);
4339 gfc_init_se (&maskse, NULL);
4340 gfc_conv_expr_val (&maskse, maskexpr);
4341 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4342 build_empty_stmt (input_location));
4345 gfc_add_expr_to_block (&block, tmp);
4346 gfc_add_block_to_block (&se->pre, &block);
4347 gcc_assert (se->post.head == NULL);
4349 else
4351 gfc_add_block_to_block (&se->pre, &ploop->pre);
4352 gfc_add_block_to_block (&se->pre, &ploop->post);
4355 if (expr->rank == 0)
4356 gfc_cleanup_loop (ploop);
4358 if (norm2)
4360 /* result = scale * sqrt(result). */
4361 tree sqrt;
4362 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
4363 resvar = build_call_expr_loc (input_location,
4364 sqrt, 1, resvar);
4365 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
4368 se->expr = resvar;
4372 /* Inline implementation of the dot_product intrinsic. This function
4373 is based on gfc_conv_intrinsic_arith (the previous function). */
4374 static void
4375 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
4377 tree resvar;
4378 tree type;
4379 stmtblock_t body;
4380 stmtblock_t block;
4381 tree tmp;
4382 gfc_loopinfo loop;
4383 gfc_actual_arglist *actual;
4384 gfc_ss *arrayss1, *arrayss2;
4385 gfc_se arrayse1, arrayse2;
4386 gfc_expr *arrayexpr1, *arrayexpr2;
4388 type = gfc_typenode_for_spec (&expr->ts);
4390 /* Initialize the result. */
4391 resvar = gfc_create_var (type, "val");
4392 if (expr->ts.type == BT_LOGICAL)
4393 tmp = build_int_cst (type, 0);
4394 else
4395 tmp = gfc_build_const (type, integer_zero_node);
4397 gfc_add_modify (&se->pre, resvar, tmp);
4399 /* Walk argument #1. */
4400 actual = expr->value.function.actual;
4401 arrayexpr1 = actual->expr;
4402 arrayss1 = gfc_walk_expr (arrayexpr1);
4403 gcc_assert (arrayss1 != gfc_ss_terminator);
4405 /* Walk argument #2. */
4406 actual = actual->next;
4407 arrayexpr2 = actual->expr;
4408 arrayss2 = gfc_walk_expr (arrayexpr2);
4409 gcc_assert (arrayss2 != gfc_ss_terminator);
4411 /* Initialize the scalarizer. */
4412 gfc_init_loopinfo (&loop);
4413 gfc_add_ss_to_loop (&loop, arrayss1);
4414 gfc_add_ss_to_loop (&loop, arrayss2);
4416 /* Initialize the loop. */
4417 gfc_conv_ss_startstride (&loop);
4418 gfc_conv_loop_setup (&loop, &expr->where);
4420 gfc_mark_ss_chain_used (arrayss1, 1);
4421 gfc_mark_ss_chain_used (arrayss2, 1);
4423 /* Generate the loop body. */
4424 gfc_start_scalarized_body (&loop, &body);
4425 gfc_init_block (&block);
4427 /* Make the tree expression for [conjg(]array1[)]. */
4428 gfc_init_se (&arrayse1, NULL);
4429 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
4430 arrayse1.ss = arrayss1;
4431 gfc_conv_expr_val (&arrayse1, arrayexpr1);
4432 if (expr->ts.type == BT_COMPLEX)
4433 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
4434 arrayse1.expr);
4435 gfc_add_block_to_block (&block, &arrayse1.pre);
4437 /* Make the tree expression for array2. */
4438 gfc_init_se (&arrayse2, NULL);
4439 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
4440 arrayse2.ss = arrayss2;
4441 gfc_conv_expr_val (&arrayse2, arrayexpr2);
4442 gfc_add_block_to_block (&block, &arrayse2.pre);
4444 /* Do the actual product and sum. */
4445 if (expr->ts.type == BT_LOGICAL)
4447 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
4448 arrayse1.expr, arrayse2.expr);
4449 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
4451 else
4453 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
4454 arrayse2.expr);
4455 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
4457 gfc_add_modify (&block, resvar, tmp);
4459 /* Finish up the loop block and the loop. */
4460 tmp = gfc_finish_block (&block);
4461 gfc_add_expr_to_block (&body, tmp);
4463 gfc_trans_scalarizing_loops (&loop, &body);
4464 gfc_add_block_to_block (&se->pre, &loop.pre);
4465 gfc_add_block_to_block (&se->pre, &loop.post);
4466 gfc_cleanup_loop (&loop);
4468 se->expr = resvar;
4472 /* Emit code for minloc or maxloc intrinsic. There are many different cases
4473 we need to handle. For performance reasons we sometimes create two
4474 loops instead of one, where the second one is much simpler.
4475 Examples for minloc intrinsic:
4476 1) Result is an array, a call is generated
4477 2) Array mask is used and NaNs need to be supported:
4478 limit = Infinity;
4479 pos = 0;
4480 S = from;
4481 while (S <= to) {
4482 if (mask[S]) {
4483 if (pos == 0) pos = S + (1 - from);
4484 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4486 S++;
4488 goto lab2;
4489 lab1:;
4490 while (S <= to) {
4491 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4492 S++;
4494 lab2:;
4495 3) NaNs need to be supported, but it is known at compile time or cheaply
4496 at runtime whether array is nonempty or not:
4497 limit = Infinity;
4498 pos = 0;
4499 S = from;
4500 while (S <= to) {
4501 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4502 S++;
4504 if (from <= to) pos = 1;
4505 goto lab2;
4506 lab1:;
4507 while (S <= to) {
4508 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4509 S++;
4511 lab2:;
4512 4) NaNs aren't supported, array mask is used:
4513 limit = infinities_supported ? Infinity : huge (limit);
4514 pos = 0;
4515 S = from;
4516 while (S <= to) {
4517 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4518 S++;
4520 goto lab2;
4521 lab1:;
4522 while (S <= to) {
4523 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4524 S++;
4526 lab2:;
4527 5) Same without array mask:
4528 limit = infinities_supported ? Infinity : huge (limit);
4529 pos = (from <= to) ? 1 : 0;
4530 S = from;
4531 while (S <= to) {
4532 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4533 S++;
4535 For 3) and 5), if mask is scalar, this all goes into a conditional,
4536 setting pos = 0; in the else branch. */
4538 static void
4539 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
4541 stmtblock_t body;
4542 stmtblock_t block;
4543 stmtblock_t ifblock;
4544 stmtblock_t elseblock;
4545 tree limit;
4546 tree type;
4547 tree tmp;
4548 tree cond;
4549 tree elsetmp;
4550 tree ifbody;
4551 tree offset;
4552 tree nonempty;
4553 tree lab1, lab2;
4554 gfc_loopinfo loop;
4555 gfc_actual_arglist *actual;
4556 gfc_ss *arrayss;
4557 gfc_ss *maskss;
4558 gfc_se arrayse;
4559 gfc_se maskse;
4560 gfc_expr *arrayexpr;
4561 gfc_expr *maskexpr;
4562 tree pos;
4563 int n;
4565 if (se->ss)
4567 gfc_conv_intrinsic_funcall (se, expr);
4568 return;
4571 /* Initialize the result. */
4572 pos = gfc_create_var (gfc_array_index_type, "pos");
4573 offset = gfc_create_var (gfc_array_index_type, "offset");
4574 type = gfc_typenode_for_spec (&expr->ts);
4576 /* Walk the arguments. */
4577 actual = expr->value.function.actual;
4578 arrayexpr = actual->expr;
4579 arrayss = gfc_walk_expr (arrayexpr);
4580 gcc_assert (arrayss != gfc_ss_terminator);
4582 actual = actual->next->next;
4583 gcc_assert (actual);
4584 maskexpr = actual->expr;
4585 nonempty = NULL;
4586 if (maskexpr && maskexpr->rank != 0)
4588 maskss = gfc_walk_expr (maskexpr);
4589 gcc_assert (maskss != gfc_ss_terminator);
4591 else
4593 mpz_t asize;
4594 if (gfc_array_size (arrayexpr, &asize))
4596 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
4597 mpz_clear (asize);
4598 nonempty = fold_build2_loc (input_location, GT_EXPR,
4599 logical_type_node, nonempty,
4600 gfc_index_zero_node);
4602 maskss = NULL;
4605 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
4606 switch (arrayexpr->ts.type)
4608 case BT_REAL:
4609 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
4610 break;
4612 case BT_INTEGER:
4613 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
4614 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
4615 arrayexpr->ts.kind);
4616 break;
4618 default:
4619 gcc_unreachable ();
4622 /* We start with the most negative possible value for MAXLOC, and the most
4623 positive possible value for MINLOC. The most negative possible value is
4624 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
4625 possible value is HUGE in both cases. */
4626 if (op == GT_EXPR)
4627 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
4628 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
4629 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
4630 build_int_cst (TREE_TYPE (tmp), 1));
4632 gfc_add_modify (&se->pre, limit, tmp);
4634 /* Initialize the scalarizer. */
4635 gfc_init_loopinfo (&loop);
4636 gfc_add_ss_to_loop (&loop, arrayss);
4637 if (maskss)
4638 gfc_add_ss_to_loop (&loop, maskss);
4640 /* Initialize the loop. */
4641 gfc_conv_ss_startstride (&loop);
4643 /* The code generated can have more than one loop in sequence (see the
4644 comment at the function header). This doesn't work well with the
4645 scalarizer, which changes arrays' offset when the scalarization loops
4646 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
4647 are currently inlined in the scalar case only (for which loop is of rank
4648 one). As there is no dependency to care about in that case, there is no
4649 temporary, so that we can use the scalarizer temporary code to handle
4650 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
4651 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
4652 to restore offset.
4653 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
4654 should eventually go away. We could either create two loops properly,
4655 or find another way to save/restore the array offsets between the two
4656 loops (without conflicting with temporary management), or use a single
4657 loop minmaxloc implementation. See PR 31067. */
4658 loop.temp_dim = loop.dimen;
4659 gfc_conv_loop_setup (&loop, &expr->where);
4661 gcc_assert (loop.dimen == 1);
4662 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
4663 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
4664 loop.from[0], loop.to[0]);
4666 lab1 = NULL;
4667 lab2 = NULL;
4668 /* Initialize the position to zero, following Fortran 2003. We are free
4669 to do this because Fortran 95 allows the result of an entirely false
4670 mask to be processor dependent. If we know at compile time the array
4671 is non-empty and no MASK is used, we can initialize to 1 to simplify
4672 the inner loop. */
4673 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
4674 gfc_add_modify (&loop.pre, pos,
4675 fold_build3_loc (input_location, COND_EXPR,
4676 gfc_array_index_type,
4677 nonempty, gfc_index_one_node,
4678 gfc_index_zero_node));
4679 else
4681 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
4682 lab1 = gfc_build_label_decl (NULL_TREE);
4683 TREE_USED (lab1) = 1;
4684 lab2 = gfc_build_label_decl (NULL_TREE);
4685 TREE_USED (lab2) = 1;
4688 /* An offset must be added to the loop
4689 counter to obtain the required position. */
4690 gcc_assert (loop.from[0]);
4692 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4693 gfc_index_one_node, loop.from[0]);
4694 gfc_add_modify (&loop.pre, offset, tmp);
4696 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
4697 if (maskss)
4698 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
4699 /* Generate the loop body. */
4700 gfc_start_scalarized_body (&loop, &body);
4702 /* If we have a mask, only check this element if the mask is set. */
4703 if (maskss)
4705 gfc_init_se (&maskse, NULL);
4706 gfc_copy_loopinfo_to_se (&maskse, &loop);
4707 maskse.ss = maskss;
4708 gfc_conv_expr_val (&maskse, maskexpr);
4709 gfc_add_block_to_block (&body, &maskse.pre);
4711 gfc_start_block (&block);
4713 else
4714 gfc_init_block (&block);
4716 /* Compare with the current limit. */
4717 gfc_init_se (&arrayse, NULL);
4718 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4719 arrayse.ss = arrayss;
4720 gfc_conv_expr_val (&arrayse, arrayexpr);
4721 gfc_add_block_to_block (&block, &arrayse.pre);
4723 /* We do the following if this is a more extreme value. */
4724 gfc_start_block (&ifblock);
4726 /* Assign the value to the limit... */
4727 gfc_add_modify (&ifblock, limit, arrayse.expr);
4729 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
4731 stmtblock_t ifblock2;
4732 tree ifbody2;
4734 gfc_start_block (&ifblock2);
4735 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4736 loop.loopvar[0], offset);
4737 gfc_add_modify (&ifblock2, pos, tmp);
4738 ifbody2 = gfc_finish_block (&ifblock2);
4739 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pos,
4740 gfc_index_zero_node);
4741 tmp = build3_v (COND_EXPR, cond, ifbody2,
4742 build_empty_stmt (input_location));
4743 gfc_add_expr_to_block (&block, tmp);
4746 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4747 loop.loopvar[0], offset);
4748 gfc_add_modify (&ifblock, pos, tmp);
4750 if (lab1)
4751 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
4753 ifbody = gfc_finish_block (&ifblock);
4755 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
4757 if (lab1)
4758 cond = fold_build2_loc (input_location,
4759 op == GT_EXPR ? GE_EXPR : LE_EXPR,
4760 logical_type_node, arrayse.expr, limit);
4761 else
4762 cond = fold_build2_loc (input_location, op, logical_type_node,
4763 arrayse.expr, limit);
4765 ifbody = build3_v (COND_EXPR, cond, ifbody,
4766 build_empty_stmt (input_location));
4768 gfc_add_expr_to_block (&block, ifbody);
4770 if (maskss)
4772 /* We enclose the above in if (mask) {...}. */
4773 tmp = gfc_finish_block (&block);
4775 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4776 build_empty_stmt (input_location));
4778 else
4779 tmp = gfc_finish_block (&block);
4780 gfc_add_expr_to_block (&body, tmp);
4782 if (lab1)
4784 gfc_trans_scalarized_loop_boundary (&loop, &body);
4786 if (HONOR_NANS (DECL_MODE (limit)))
4788 if (nonempty != NULL)
4790 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
4791 tmp = build3_v (COND_EXPR, nonempty, ifbody,
4792 build_empty_stmt (input_location));
4793 gfc_add_expr_to_block (&loop.code[0], tmp);
4797 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
4798 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
4800 /* If we have a mask, only check this element if the mask is set. */
4801 if (maskss)
4803 gfc_init_se (&maskse, NULL);
4804 gfc_copy_loopinfo_to_se (&maskse, &loop);
4805 maskse.ss = maskss;
4806 gfc_conv_expr_val (&maskse, maskexpr);
4807 gfc_add_block_to_block (&body, &maskse.pre);
4809 gfc_start_block (&block);
4811 else
4812 gfc_init_block (&block);
4814 /* Compare with the current limit. */
4815 gfc_init_se (&arrayse, NULL);
4816 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4817 arrayse.ss = arrayss;
4818 gfc_conv_expr_val (&arrayse, arrayexpr);
4819 gfc_add_block_to_block (&block, &arrayse.pre);
4821 /* We do the following if this is a more extreme value. */
4822 gfc_start_block (&ifblock);
4824 /* Assign the value to the limit... */
4825 gfc_add_modify (&ifblock, limit, arrayse.expr);
4827 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4828 loop.loopvar[0], offset);
4829 gfc_add_modify (&ifblock, pos, tmp);
4831 ifbody = gfc_finish_block (&ifblock);
4833 cond = fold_build2_loc (input_location, op, logical_type_node,
4834 arrayse.expr, limit);
4836 tmp = build3_v (COND_EXPR, cond, ifbody,
4837 build_empty_stmt (input_location));
4838 gfc_add_expr_to_block (&block, tmp);
4840 if (maskss)
4842 /* We enclose the above in if (mask) {...}. */
4843 tmp = gfc_finish_block (&block);
4845 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4846 build_empty_stmt (input_location));
4848 else
4849 tmp = gfc_finish_block (&block);
4850 gfc_add_expr_to_block (&body, tmp);
4851 /* Avoid initializing loopvar[0] again, it should be left where
4852 it finished by the first loop. */
4853 loop.from[0] = loop.loopvar[0];
4856 gfc_trans_scalarizing_loops (&loop, &body);
4858 if (lab2)
4859 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
4861 /* For a scalar mask, enclose the loop in an if statement. */
4862 if (maskexpr && maskss == NULL)
4864 gfc_init_se (&maskse, NULL);
4865 gfc_conv_expr_val (&maskse, maskexpr);
4866 gfc_init_block (&block);
4867 gfc_add_block_to_block (&block, &loop.pre);
4868 gfc_add_block_to_block (&block, &loop.post);
4869 tmp = gfc_finish_block (&block);
4871 /* For the else part of the scalar mask, just initialize
4872 the pos variable the same way as above. */
4874 gfc_init_block (&elseblock);
4875 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
4876 elsetmp = gfc_finish_block (&elseblock);
4878 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
4879 gfc_add_expr_to_block (&block, tmp);
4880 gfc_add_block_to_block (&se->pre, &block);
4882 else
4884 gfc_add_block_to_block (&se->pre, &loop.pre);
4885 gfc_add_block_to_block (&se->pre, &loop.post);
4887 gfc_cleanup_loop (&loop);
4889 se->expr = convert (type, pos);
4892 /* Emit code for minval or maxval intrinsic. There are many different cases
4893 we need to handle. For performance reasons we sometimes create two
4894 loops instead of one, where the second one is much simpler.
4895 Examples for minval intrinsic:
4896 1) Result is an array, a call is generated
4897 2) Array mask is used and NaNs need to be supported, rank 1:
4898 limit = Infinity;
4899 nonempty = false;
4900 S = from;
4901 while (S <= to) {
4902 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
4903 S++;
4905 limit = nonempty ? NaN : huge (limit);
4906 lab:
4907 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
4908 3) NaNs need to be supported, but it is known at compile time or cheaply
4909 at runtime whether array is nonempty or not, rank 1:
4910 limit = Infinity;
4911 S = from;
4912 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
4913 limit = (from <= to) ? NaN : huge (limit);
4914 lab:
4915 while (S <= to) { limit = min (a[S], limit); S++; }
4916 4) Array mask is used and NaNs need to be supported, rank > 1:
4917 limit = Infinity;
4918 nonempty = false;
4919 fast = false;
4920 S1 = from1;
4921 while (S1 <= to1) {
4922 S2 = from2;
4923 while (S2 <= to2) {
4924 if (mask[S1][S2]) {
4925 if (fast) limit = min (a[S1][S2], limit);
4926 else {
4927 nonempty = true;
4928 if (a[S1][S2] <= limit) {
4929 limit = a[S1][S2];
4930 fast = true;
4934 S2++;
4936 S1++;
4938 if (!fast)
4939 limit = nonempty ? NaN : huge (limit);
4940 5) NaNs need to be supported, but it is known at compile time or cheaply
4941 at runtime whether array is nonempty or not, rank > 1:
4942 limit = Infinity;
4943 fast = false;
4944 S1 = from1;
4945 while (S1 <= to1) {
4946 S2 = from2;
4947 while (S2 <= to2) {
4948 if (fast) limit = min (a[S1][S2], limit);
4949 else {
4950 if (a[S1][S2] <= limit) {
4951 limit = a[S1][S2];
4952 fast = true;
4955 S2++;
4957 S1++;
4959 if (!fast)
4960 limit = (nonempty_array) ? NaN : huge (limit);
4961 6) NaNs aren't supported, but infinities are. Array mask is used:
4962 limit = Infinity;
4963 nonempty = false;
4964 S = from;
4965 while (S <= to) {
4966 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
4967 S++;
4969 limit = nonempty ? limit : huge (limit);
4970 7) Same without array mask:
4971 limit = Infinity;
4972 S = from;
4973 while (S <= to) { limit = min (a[S], limit); S++; }
4974 limit = (from <= to) ? limit : huge (limit);
4975 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
4976 limit = huge (limit);
4977 S = from;
4978 while (S <= to) { limit = min (a[S], limit); S++); }
4980 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
4981 with array mask instead).
4982 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
4983 setting limit = huge (limit); in the else branch. */
4985 static void
4986 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
4988 tree limit;
4989 tree type;
4990 tree tmp;
4991 tree ifbody;
4992 tree nonempty;
4993 tree nonempty_var;
4994 tree lab;
4995 tree fast;
4996 tree huge_cst = NULL, nan_cst = NULL;
4997 stmtblock_t body;
4998 stmtblock_t block, block2;
4999 gfc_loopinfo loop;
5000 gfc_actual_arglist *actual;
5001 gfc_ss *arrayss;
5002 gfc_ss *maskss;
5003 gfc_se arrayse;
5004 gfc_se maskse;
5005 gfc_expr *arrayexpr;
5006 gfc_expr *maskexpr;
5007 int n;
5009 if (se->ss)
5011 gfc_conv_intrinsic_funcall (se, expr);
5012 return;
5015 type = gfc_typenode_for_spec (&expr->ts);
5016 /* Initialize the result. */
5017 limit = gfc_create_var (type, "limit");
5018 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
5019 switch (expr->ts.type)
5021 case BT_REAL:
5022 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
5023 expr->ts.kind, 0);
5024 if (HONOR_INFINITIES (DECL_MODE (limit)))
5026 REAL_VALUE_TYPE real;
5027 real_inf (&real);
5028 tmp = build_real (type, real);
5030 else
5031 tmp = huge_cst;
5032 if (HONOR_NANS (DECL_MODE (limit)))
5033 nan_cst = gfc_build_nan (type, "");
5034 break;
5036 case BT_INTEGER:
5037 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
5038 break;
5040 default:
5041 gcc_unreachable ();
5044 /* We start with the most negative possible value for MAXVAL, and the most
5045 positive possible value for MINVAL. The most negative possible value is
5046 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5047 possible value is HUGE in both cases. */
5048 if (op == GT_EXPR)
5050 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
5051 if (huge_cst)
5052 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
5053 TREE_TYPE (huge_cst), huge_cst);
5056 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
5057 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
5058 tmp, build_int_cst (type, 1));
5060 gfc_add_modify (&se->pre, limit, tmp);
5062 /* Walk the arguments. */
5063 actual = expr->value.function.actual;
5064 arrayexpr = actual->expr;
5065 arrayss = gfc_walk_expr (arrayexpr);
5066 gcc_assert (arrayss != gfc_ss_terminator);
5068 actual = actual->next->next;
5069 gcc_assert (actual);
5070 maskexpr = actual->expr;
5071 nonempty = NULL;
5072 if (maskexpr && maskexpr->rank != 0)
5074 maskss = gfc_walk_expr (maskexpr);
5075 gcc_assert (maskss != gfc_ss_terminator);
5077 else
5079 mpz_t asize;
5080 if (gfc_array_size (arrayexpr, &asize))
5082 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
5083 mpz_clear (asize);
5084 nonempty = fold_build2_loc (input_location, GT_EXPR,
5085 logical_type_node, nonempty,
5086 gfc_index_zero_node);
5088 maskss = NULL;
5091 /* Initialize the scalarizer. */
5092 gfc_init_loopinfo (&loop);
5093 gfc_add_ss_to_loop (&loop, arrayss);
5094 if (maskss)
5095 gfc_add_ss_to_loop (&loop, maskss);
5097 /* Initialize the loop. */
5098 gfc_conv_ss_startstride (&loop);
5100 /* The code generated can have more than one loop in sequence (see the
5101 comment at the function header). This doesn't work well with the
5102 scalarizer, which changes arrays' offset when the scalarization loops
5103 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
5104 are currently inlined in the scalar case only. As there is no dependency
5105 to care about in that case, there is no temporary, so that we can use the
5106 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
5107 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
5108 gfc_trans_scalarized_loop_boundary even later to restore offset.
5109 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
5110 should eventually go away. We could either create two loops properly,
5111 or find another way to save/restore the array offsets between the two
5112 loops (without conflicting with temporary management), or use a single
5113 loop minmaxval implementation. See PR 31067. */
5114 loop.temp_dim = loop.dimen;
5115 gfc_conv_loop_setup (&loop, &expr->where);
5117 if (nonempty == NULL && maskss == NULL
5118 && loop.dimen == 1 && loop.from[0] && loop.to[0])
5119 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
5120 loop.from[0], loop.to[0]);
5121 nonempty_var = NULL;
5122 if (nonempty == NULL
5123 && (HONOR_INFINITIES (DECL_MODE (limit))
5124 || HONOR_NANS (DECL_MODE (limit))))
5126 nonempty_var = gfc_create_var (logical_type_node, "nonempty");
5127 gfc_add_modify (&se->pre, nonempty_var, logical_false_node);
5128 nonempty = nonempty_var;
5130 lab = NULL;
5131 fast = NULL;
5132 if (HONOR_NANS (DECL_MODE (limit)))
5134 if (loop.dimen == 1)
5136 lab = gfc_build_label_decl (NULL_TREE);
5137 TREE_USED (lab) = 1;
5139 else
5141 fast = gfc_create_var (logical_type_node, "fast");
5142 gfc_add_modify (&se->pre, fast, logical_false_node);
5146 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
5147 if (maskss)
5148 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
5149 /* Generate the loop body. */
5150 gfc_start_scalarized_body (&loop, &body);
5152 /* If we have a mask, only add this element if the mask is set. */
5153 if (maskss)
5155 gfc_init_se (&maskse, NULL);
5156 gfc_copy_loopinfo_to_se (&maskse, &loop);
5157 maskse.ss = maskss;
5158 gfc_conv_expr_val (&maskse, maskexpr);
5159 gfc_add_block_to_block (&body, &maskse.pre);
5161 gfc_start_block (&block);
5163 else
5164 gfc_init_block (&block);
5166 /* Compare with the current limit. */
5167 gfc_init_se (&arrayse, NULL);
5168 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5169 arrayse.ss = arrayss;
5170 gfc_conv_expr_val (&arrayse, arrayexpr);
5171 gfc_add_block_to_block (&block, &arrayse.pre);
5173 gfc_init_block (&block2);
5175 if (nonempty_var)
5176 gfc_add_modify (&block2, nonempty_var, logical_true_node);
5178 if (HONOR_NANS (DECL_MODE (limit)))
5180 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5181 logical_type_node, arrayse.expr, limit);
5182 if (lab)
5183 ifbody = build1_v (GOTO_EXPR, lab);
5184 else
5186 stmtblock_t ifblock;
5188 gfc_init_block (&ifblock);
5189 gfc_add_modify (&ifblock, limit, arrayse.expr);
5190 gfc_add_modify (&ifblock, fast, logical_true_node);
5191 ifbody = gfc_finish_block (&ifblock);
5193 tmp = build3_v (COND_EXPR, tmp, ifbody,
5194 build_empty_stmt (input_location));
5195 gfc_add_expr_to_block (&block2, tmp);
5197 else
5199 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5200 signed zeros. */
5201 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5203 tmp = fold_build2_loc (input_location, op, logical_type_node,
5204 arrayse.expr, limit);
5205 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5206 tmp = build3_v (COND_EXPR, tmp, ifbody,
5207 build_empty_stmt (input_location));
5208 gfc_add_expr_to_block (&block2, tmp);
5210 else
5212 tmp = fold_build2_loc (input_location,
5213 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5214 type, arrayse.expr, limit);
5215 gfc_add_modify (&block2, limit, tmp);
5219 if (fast)
5221 tree elsebody = gfc_finish_block (&block2);
5223 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5224 signed zeros. */
5225 if (HONOR_NANS (DECL_MODE (limit))
5226 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5228 tmp = fold_build2_loc (input_location, op, logical_type_node,
5229 arrayse.expr, limit);
5230 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5231 ifbody = build3_v (COND_EXPR, tmp, ifbody,
5232 build_empty_stmt (input_location));
5234 else
5236 tmp = fold_build2_loc (input_location,
5237 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5238 type, arrayse.expr, limit);
5239 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5241 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
5242 gfc_add_expr_to_block (&block, tmp);
5244 else
5245 gfc_add_block_to_block (&block, &block2);
5247 gfc_add_block_to_block (&block, &arrayse.post);
5249 tmp = gfc_finish_block (&block);
5250 if (maskss)
5251 /* We enclose the above in if (mask) {...}. */
5252 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5253 build_empty_stmt (input_location));
5254 gfc_add_expr_to_block (&body, tmp);
5256 if (lab)
5258 gfc_trans_scalarized_loop_boundary (&loop, &body);
5260 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5261 nan_cst, huge_cst);
5262 gfc_add_modify (&loop.code[0], limit, tmp);
5263 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
5265 /* If we have a mask, only add this element if the mask is set. */
5266 if (maskss)
5268 gfc_init_se (&maskse, NULL);
5269 gfc_copy_loopinfo_to_se (&maskse, &loop);
5270 maskse.ss = maskss;
5271 gfc_conv_expr_val (&maskse, maskexpr);
5272 gfc_add_block_to_block (&body, &maskse.pre);
5274 gfc_start_block (&block);
5276 else
5277 gfc_init_block (&block);
5279 /* Compare with the current limit. */
5280 gfc_init_se (&arrayse, NULL);
5281 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5282 arrayse.ss = arrayss;
5283 gfc_conv_expr_val (&arrayse, arrayexpr);
5284 gfc_add_block_to_block (&block, &arrayse.pre);
5286 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5287 signed zeros. */
5288 if (HONOR_NANS (DECL_MODE (limit))
5289 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5291 tmp = fold_build2_loc (input_location, op, logical_type_node,
5292 arrayse.expr, limit);
5293 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5294 tmp = build3_v (COND_EXPR, tmp, ifbody,
5295 build_empty_stmt (input_location));
5296 gfc_add_expr_to_block (&block, tmp);
5298 else
5300 tmp = fold_build2_loc (input_location,
5301 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5302 type, arrayse.expr, limit);
5303 gfc_add_modify (&block, limit, tmp);
5306 gfc_add_block_to_block (&block, &arrayse.post);
5308 tmp = gfc_finish_block (&block);
5309 if (maskss)
5310 /* We enclose the above in if (mask) {...}. */
5311 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5312 build_empty_stmt (input_location));
5313 gfc_add_expr_to_block (&body, tmp);
5314 /* Avoid initializing loopvar[0] again, it should be left where
5315 it finished by the first loop. */
5316 loop.from[0] = loop.loopvar[0];
5318 gfc_trans_scalarizing_loops (&loop, &body);
5320 if (fast)
5322 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5323 nan_cst, huge_cst);
5324 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5325 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
5326 ifbody);
5327 gfc_add_expr_to_block (&loop.pre, tmp);
5329 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
5331 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
5332 huge_cst);
5333 gfc_add_modify (&loop.pre, limit, tmp);
5336 /* For a scalar mask, enclose the loop in an if statement. */
5337 if (maskexpr && maskss == NULL)
5339 tree else_stmt;
5341 gfc_init_se (&maskse, NULL);
5342 gfc_conv_expr_val (&maskse, maskexpr);
5343 gfc_init_block (&block);
5344 gfc_add_block_to_block (&block, &loop.pre);
5345 gfc_add_block_to_block (&block, &loop.post);
5346 tmp = gfc_finish_block (&block);
5348 if (HONOR_INFINITIES (DECL_MODE (limit)))
5349 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
5350 else
5351 else_stmt = build_empty_stmt (input_location);
5352 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
5353 gfc_add_expr_to_block (&block, tmp);
5354 gfc_add_block_to_block (&se->pre, &block);
5356 else
5358 gfc_add_block_to_block (&se->pre, &loop.pre);
5359 gfc_add_block_to_block (&se->pre, &loop.post);
5362 gfc_cleanup_loop (&loop);
5364 se->expr = limit;
5367 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
5368 static void
5369 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
5371 tree args[2];
5372 tree type;
5373 tree tmp;
5375 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5376 type = TREE_TYPE (args[0]);
5378 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5379 build_int_cst (type, 1), args[1]);
5380 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
5381 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
5382 build_int_cst (type, 0));
5383 type = gfc_typenode_for_spec (&expr->ts);
5384 se->expr = convert (type, tmp);
5388 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
5389 static void
5390 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
5392 tree args[2];
5394 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5396 /* Convert both arguments to the unsigned type of the same size. */
5397 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
5398 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
5400 /* If they have unequal type size, convert to the larger one. */
5401 if (TYPE_PRECISION (TREE_TYPE (args[0]))
5402 > TYPE_PRECISION (TREE_TYPE (args[1])))
5403 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
5404 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
5405 > TYPE_PRECISION (TREE_TYPE (args[0])))
5406 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
5408 /* Now, we compare them. */
5409 se->expr = fold_build2_loc (input_location, op, logical_type_node,
5410 args[0], args[1]);
5414 /* Generate code to perform the specified operation. */
5415 static void
5416 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
5418 tree args[2];
5420 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5421 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
5422 args[0], args[1]);
5425 /* Bitwise not. */
5426 static void
5427 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
5429 tree arg;
5431 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5432 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
5433 TREE_TYPE (arg), arg);
5436 /* Set or clear a single bit. */
5437 static void
5438 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
5440 tree args[2];
5441 tree type;
5442 tree tmp;
5443 enum tree_code op;
5445 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5446 type = TREE_TYPE (args[0]);
5448 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5449 build_int_cst (type, 1), args[1]);
5450 if (set)
5451 op = BIT_IOR_EXPR;
5452 else
5454 op = BIT_AND_EXPR;
5455 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
5457 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
5460 /* Extract a sequence of bits.
5461 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
5462 static void
5463 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
5465 tree args[3];
5466 tree type;
5467 tree tmp;
5468 tree mask;
5470 gfc_conv_intrinsic_function_args (se, expr, args, 3);
5471 type = TREE_TYPE (args[0]);
5473 mask = build_int_cst (type, -1);
5474 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
5475 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
5477 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
5479 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
5482 static void
5483 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
5484 bool arithmetic)
5486 tree args[2], type, num_bits, cond;
5488 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5490 args[0] = gfc_evaluate_now (args[0], &se->pre);
5491 args[1] = gfc_evaluate_now (args[1], &se->pre);
5492 type = TREE_TYPE (args[0]);
5494 if (!arithmetic)
5495 args[0] = fold_convert (unsigned_type_for (type), args[0]);
5496 else
5497 gcc_assert (right_shift);
5499 se->expr = fold_build2_loc (input_location,
5500 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
5501 TREE_TYPE (args[0]), args[0], args[1]);
5503 if (!arithmetic)
5504 se->expr = fold_convert (type, se->expr);
5506 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5507 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5508 special case. */
5509 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
5510 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
5511 args[1], num_bits);
5513 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5514 build_int_cst (type, 0), se->expr);
5517 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
5519 : ((shift >= 0) ? i << shift : i >> -shift)
5520 where all shifts are logical shifts. */
5521 static void
5522 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
5524 tree args[2];
5525 tree type;
5526 tree utype;
5527 tree tmp;
5528 tree width;
5529 tree num_bits;
5530 tree cond;
5531 tree lshift;
5532 tree rshift;
5534 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5536 args[0] = gfc_evaluate_now (args[0], &se->pre);
5537 args[1] = gfc_evaluate_now (args[1], &se->pre);
5539 type = TREE_TYPE (args[0]);
5540 utype = unsigned_type_for (type);
5542 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
5543 args[1]);
5545 /* Left shift if positive. */
5546 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
5548 /* Right shift if negative.
5549 We convert to an unsigned type because we want a logical shift.
5550 The standard doesn't define the case of shifting negative
5551 numbers, and we try to be compatible with other compilers, most
5552 notably g77, here. */
5553 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
5554 utype, convert (utype, args[0]), width));
5556 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[1],
5557 build_int_cst (TREE_TYPE (args[1]), 0));
5558 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
5560 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5561 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5562 special case. */
5563 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
5564 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, width,
5565 num_bits);
5566 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5567 build_int_cst (type, 0), tmp);
5571 /* Circular shift. AKA rotate or barrel shift. */
5573 static void
5574 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
5576 tree *args;
5577 tree type;
5578 tree tmp;
5579 tree lrot;
5580 tree rrot;
5581 tree zero;
5582 unsigned int num_args;
5584 num_args = gfc_intrinsic_argument_list_length (expr);
5585 args = XALLOCAVEC (tree, num_args);
5587 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
5589 if (num_args == 3)
5591 /* Use a library function for the 3 parameter version. */
5592 tree int4type = gfc_get_int_type (4);
5594 type = TREE_TYPE (args[0]);
5595 /* We convert the first argument to at least 4 bytes, and
5596 convert back afterwards. This removes the need for library
5597 functions for all argument sizes, and function will be
5598 aligned to at least 32 bits, so there's no loss. */
5599 if (expr->ts.kind < 4)
5600 args[0] = convert (int4type, args[0]);
5602 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
5603 need loads of library functions. They cannot have values >
5604 BIT_SIZE (I) so the conversion is safe. */
5605 args[1] = convert (int4type, args[1]);
5606 args[2] = convert (int4type, args[2]);
5608 switch (expr->ts.kind)
5610 case 1:
5611 case 2:
5612 case 4:
5613 tmp = gfor_fndecl_math_ishftc4;
5614 break;
5615 case 8:
5616 tmp = gfor_fndecl_math_ishftc8;
5617 break;
5618 case 16:
5619 tmp = gfor_fndecl_math_ishftc16;
5620 break;
5621 default:
5622 gcc_unreachable ();
5624 se->expr = build_call_expr_loc (input_location,
5625 tmp, 3, args[0], args[1], args[2]);
5626 /* Convert the result back to the original type, if we extended
5627 the first argument's width above. */
5628 if (expr->ts.kind < 4)
5629 se->expr = convert (type, se->expr);
5631 return;
5633 type = TREE_TYPE (args[0]);
5635 /* Evaluate arguments only once. */
5636 args[0] = gfc_evaluate_now (args[0], &se->pre);
5637 args[1] = gfc_evaluate_now (args[1], &se->pre);
5639 /* Rotate left if positive. */
5640 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
5642 /* Rotate right if negative. */
5643 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
5644 args[1]);
5645 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
5647 zero = build_int_cst (TREE_TYPE (args[1]), 0);
5648 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, args[1],
5649 zero);
5650 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
5652 /* Do nothing if shift == 0. */
5653 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, args[1],
5654 zero);
5655 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
5656 rrot);
5660 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
5661 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
5663 The conditional expression is necessary because the result of LEADZ(0)
5664 is defined, but the result of __builtin_clz(0) is undefined for most
5665 targets.
5667 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
5668 difference in bit size between the argument of LEADZ and the C int. */
5670 static void
5671 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
5673 tree arg;
5674 tree arg_type;
5675 tree cond;
5676 tree result_type;
5677 tree leadz;
5678 tree bit_size;
5679 tree tmp;
5680 tree func;
5681 int s, argsize;
5683 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5684 argsize = TYPE_PRECISION (TREE_TYPE (arg));
5686 /* Which variant of __builtin_clz* should we call? */
5687 if (argsize <= INT_TYPE_SIZE)
5689 arg_type = unsigned_type_node;
5690 func = builtin_decl_explicit (BUILT_IN_CLZ);
5692 else if (argsize <= LONG_TYPE_SIZE)
5694 arg_type = long_unsigned_type_node;
5695 func = builtin_decl_explicit (BUILT_IN_CLZL);
5697 else if (argsize <= LONG_LONG_TYPE_SIZE)
5699 arg_type = long_long_unsigned_type_node;
5700 func = builtin_decl_explicit (BUILT_IN_CLZLL);
5702 else
5704 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
5705 arg_type = gfc_build_uint_type (argsize);
5706 func = NULL_TREE;
5709 /* Convert the actual argument twice: first, to the unsigned type of the
5710 same size; then, to the proper argument type for the built-in
5711 function. But the return type is of the default INTEGER kind. */
5712 arg = fold_convert (gfc_build_uint_type (argsize), arg);
5713 arg = fold_convert (arg_type, arg);
5714 arg = gfc_evaluate_now (arg, &se->pre);
5715 result_type = gfc_get_int_type (gfc_default_integer_kind);
5717 /* Compute LEADZ for the case i .ne. 0. */
5718 if (func)
5720 s = TYPE_PRECISION (arg_type) - argsize;
5721 tmp = fold_convert (result_type,
5722 build_call_expr_loc (input_location, func,
5723 1, arg));
5724 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
5725 tmp, build_int_cst (result_type, s));
5727 else
5729 /* We end up here if the argument type is larger than 'long long'.
5730 We generate this code:
5732 if (x & (ULL_MAX << ULL_SIZE) != 0)
5733 return clzll ((unsigned long long) (x >> ULLSIZE));
5734 else
5735 return ULL_SIZE + clzll ((unsigned long long) x);
5736 where ULL_MAX is the largest value that a ULL_MAX can hold
5737 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
5738 is the bit-size of the long long type (64 in this example). */
5739 tree ullsize, ullmax, tmp1, tmp2, btmp;
5741 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
5742 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
5743 long_long_unsigned_type_node,
5744 build_int_cst (long_long_unsigned_type_node,
5745 0));
5747 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
5748 fold_convert (arg_type, ullmax), ullsize);
5749 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
5750 arg, cond);
5751 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
5752 cond, build_int_cst (arg_type, 0));
5754 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
5755 arg, ullsize);
5756 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
5757 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
5758 tmp1 = fold_convert (result_type,
5759 build_call_expr_loc (input_location, btmp, 1, tmp1));
5761 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
5762 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
5763 tmp2 = fold_convert (result_type,
5764 build_call_expr_loc (input_location, btmp, 1, tmp2));
5765 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
5766 tmp2, ullsize);
5768 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
5769 cond, tmp1, tmp2);
5772 /* Build BIT_SIZE. */
5773 bit_size = build_int_cst (result_type, argsize);
5775 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
5776 arg, build_int_cst (arg_type, 0));
5777 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
5778 bit_size, leadz);
5782 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
5784 The conditional expression is necessary because the result of TRAILZ(0)
5785 is defined, but the result of __builtin_ctz(0) is undefined for most
5786 targets. */
5788 static void
5789 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
5791 tree arg;
5792 tree arg_type;
5793 tree cond;
5794 tree result_type;
5795 tree trailz;
5796 tree bit_size;
5797 tree func;
5798 int argsize;
5800 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5801 argsize = TYPE_PRECISION (TREE_TYPE (arg));
5803 /* Which variant of __builtin_ctz* should we call? */
5804 if (argsize <= INT_TYPE_SIZE)
5806 arg_type = unsigned_type_node;
5807 func = builtin_decl_explicit (BUILT_IN_CTZ);
5809 else if (argsize <= LONG_TYPE_SIZE)
5811 arg_type = long_unsigned_type_node;
5812 func = builtin_decl_explicit (BUILT_IN_CTZL);
5814 else if (argsize <= LONG_LONG_TYPE_SIZE)
5816 arg_type = long_long_unsigned_type_node;
5817 func = builtin_decl_explicit (BUILT_IN_CTZLL);
5819 else
5821 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
5822 arg_type = gfc_build_uint_type (argsize);
5823 func = NULL_TREE;
5826 /* Convert the actual argument twice: first, to the unsigned type of the
5827 same size; then, to the proper argument type for the built-in
5828 function. But the return type is of the default INTEGER kind. */
5829 arg = fold_convert (gfc_build_uint_type (argsize), arg);
5830 arg = fold_convert (arg_type, arg);
5831 arg = gfc_evaluate_now (arg, &se->pre);
5832 result_type = gfc_get_int_type (gfc_default_integer_kind);
5834 /* Compute TRAILZ for the case i .ne. 0. */
5835 if (func)
5836 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
5837 func, 1, arg));
5838 else
5840 /* We end up here if the argument type is larger than 'long long'.
5841 We generate this code:
5843 if ((x & ULL_MAX) == 0)
5844 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
5845 else
5846 return ctzll ((unsigned long long) x);
5848 where ULL_MAX is the largest value that a ULL_MAX can hold
5849 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
5850 is the bit-size of the long long type (64 in this example). */
5851 tree ullsize, ullmax, tmp1, tmp2, btmp;
5853 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
5854 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
5855 long_long_unsigned_type_node,
5856 build_int_cst (long_long_unsigned_type_node, 0));
5858 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
5859 fold_convert (arg_type, ullmax));
5860 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, cond,
5861 build_int_cst (arg_type, 0));
5863 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
5864 arg, ullsize);
5865 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
5866 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
5867 tmp1 = fold_convert (result_type,
5868 build_call_expr_loc (input_location, btmp, 1, tmp1));
5869 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
5870 tmp1, ullsize);
5872 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
5873 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
5874 tmp2 = fold_convert (result_type,
5875 build_call_expr_loc (input_location, btmp, 1, tmp2));
5877 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
5878 cond, tmp1, tmp2);
5881 /* Build BIT_SIZE. */
5882 bit_size = build_int_cst (result_type, argsize);
5884 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
5885 arg, build_int_cst (arg_type, 0));
5886 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
5887 bit_size, trailz);
5890 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
5891 for types larger than "long long", we call the long long built-in for
5892 the lower and higher bits and combine the result. */
5894 static void
5895 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
5897 tree arg;
5898 tree arg_type;
5899 tree result_type;
5900 tree func;
5901 int argsize;
5903 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5904 argsize = TYPE_PRECISION (TREE_TYPE (arg));
5905 result_type = gfc_get_int_type (gfc_default_integer_kind);
5907 /* Which variant of the builtin should we call? */
5908 if (argsize <= INT_TYPE_SIZE)
5910 arg_type = unsigned_type_node;
5911 func = builtin_decl_explicit (parity
5912 ? BUILT_IN_PARITY
5913 : BUILT_IN_POPCOUNT);
5915 else if (argsize <= LONG_TYPE_SIZE)
5917 arg_type = long_unsigned_type_node;
5918 func = builtin_decl_explicit (parity
5919 ? BUILT_IN_PARITYL
5920 : BUILT_IN_POPCOUNTL);
5922 else if (argsize <= LONG_LONG_TYPE_SIZE)
5924 arg_type = long_long_unsigned_type_node;
5925 func = builtin_decl_explicit (parity
5926 ? BUILT_IN_PARITYLL
5927 : BUILT_IN_POPCOUNTLL);
5929 else
5931 /* Our argument type is larger than 'long long', which mean none
5932 of the POPCOUNT builtins covers it. We thus call the 'long long'
5933 variant multiple times, and add the results. */
5934 tree utype, arg2, call1, call2;
5936 /* For now, we only cover the case where argsize is twice as large
5937 as 'long long'. */
5938 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
5940 func = builtin_decl_explicit (parity
5941 ? BUILT_IN_PARITYLL
5942 : BUILT_IN_POPCOUNTLL);
5944 /* Convert it to an integer, and store into a variable. */
5945 utype = gfc_build_uint_type (argsize);
5946 arg = fold_convert (utype, arg);
5947 arg = gfc_evaluate_now (arg, &se->pre);
5949 /* Call the builtin twice. */
5950 call1 = build_call_expr_loc (input_location, func, 1,
5951 fold_convert (long_long_unsigned_type_node,
5952 arg));
5954 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
5955 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
5956 call2 = build_call_expr_loc (input_location, func, 1,
5957 fold_convert (long_long_unsigned_type_node,
5958 arg2));
5960 /* Combine the results. */
5961 if (parity)
5962 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
5963 call1, call2);
5964 else
5965 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
5966 call1, call2);
5968 return;
5971 /* Convert the actual argument twice: first, to the unsigned type of the
5972 same size; then, to the proper argument type for the built-in
5973 function. */
5974 arg = fold_convert (gfc_build_uint_type (argsize), arg);
5975 arg = fold_convert (arg_type, arg);
5977 se->expr = fold_convert (result_type,
5978 build_call_expr_loc (input_location, func, 1, arg));
5982 /* Process an intrinsic with unspecified argument-types that has an optional
5983 argument (which could be of type character), e.g. EOSHIFT. For those, we
5984 need to append the string length of the optional argument if it is not
5985 present and the type is really character.
5986 primary specifies the position (starting at 1) of the non-optional argument
5987 specifying the type and optional gives the position of the optional
5988 argument in the arglist. */
5990 static void
5991 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
5992 unsigned primary, unsigned optional)
5994 gfc_actual_arglist* prim_arg;
5995 gfc_actual_arglist* opt_arg;
5996 unsigned cur_pos;
5997 gfc_actual_arglist* arg;
5998 gfc_symbol* sym;
5999 vec<tree, va_gc> *append_args;
6001 /* Find the two arguments given as position. */
6002 cur_pos = 0;
6003 prim_arg = NULL;
6004 opt_arg = NULL;
6005 for (arg = expr->value.function.actual; arg; arg = arg->next)
6007 ++cur_pos;
6009 if (cur_pos == primary)
6010 prim_arg = arg;
6011 if (cur_pos == optional)
6012 opt_arg = arg;
6014 if (cur_pos >= primary && cur_pos >= optional)
6015 break;
6017 gcc_assert (prim_arg);
6018 gcc_assert (prim_arg->expr);
6019 gcc_assert (opt_arg);
6021 /* If we do have type CHARACTER and the optional argument is really absent,
6022 append a dummy 0 as string length. */
6023 append_args = NULL;
6024 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
6026 tree dummy;
6028 dummy = build_int_cst (gfc_charlen_type_node, 0);
6029 vec_alloc (append_args, 1);
6030 append_args->quick_push (dummy);
6033 /* Build the call itself. */
6034 gcc_assert (!se->ignore_optional);
6035 sym = gfc_get_symbol_for_expr (expr, false);
6036 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
6037 append_args);
6038 gfc_free_symbol (sym);
6042 /* The length of a character string. */
6043 static void
6044 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
6046 tree len;
6047 tree type;
6048 tree decl;
6049 gfc_symbol *sym;
6050 gfc_se argse;
6051 gfc_expr *arg;
6053 gcc_assert (!se->ss);
6055 arg = expr->value.function.actual->expr;
6057 type = gfc_typenode_for_spec (&expr->ts);
6058 switch (arg->expr_type)
6060 case EXPR_CONSTANT:
6061 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
6062 break;
6064 case EXPR_ARRAY:
6065 /* Obtain the string length from the function used by
6066 trans-array.c(gfc_trans_array_constructor). */
6067 len = NULL_TREE;
6068 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
6069 break;
6071 case EXPR_VARIABLE:
6072 if (arg->ref == NULL
6073 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
6075 /* This doesn't catch all cases.
6076 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
6077 and the surrounding thread. */
6078 sym = arg->symtree->n.sym;
6079 decl = gfc_get_symbol_decl (sym);
6080 if (decl == current_function_decl && sym->attr.function
6081 && (sym->result == sym))
6082 decl = gfc_get_fake_result_decl (sym, 0);
6084 len = sym->ts.u.cl->backend_decl;
6085 gcc_assert (len);
6086 break;
6089 /* Fall through. */
6091 default:
6092 /* Anybody stupid enough to do this deserves inefficient code. */
6093 gfc_init_se (&argse, se);
6094 if (arg->rank == 0)
6095 gfc_conv_expr (&argse, arg);
6096 else
6097 gfc_conv_expr_descriptor (&argse, arg);
6098 gfc_add_block_to_block (&se->pre, &argse.pre);
6099 gfc_add_block_to_block (&se->post, &argse.post);
6100 len = argse.string_length;
6101 break;
6103 se->expr = convert (type, len);
6106 /* The length of a character string not including trailing blanks. */
6107 static void
6108 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
6110 int kind = expr->value.function.actual->expr->ts.kind;
6111 tree args[2], type, fndecl;
6113 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6114 type = gfc_typenode_for_spec (&expr->ts);
6116 if (kind == 1)
6117 fndecl = gfor_fndecl_string_len_trim;
6118 else if (kind == 4)
6119 fndecl = gfor_fndecl_string_len_trim_char4;
6120 else
6121 gcc_unreachable ();
6123 se->expr = build_call_expr_loc (input_location,
6124 fndecl, 2, args[0], args[1]);
6125 se->expr = convert (type, se->expr);
6129 /* Returns the starting position of a substring within a string. */
6131 static void
6132 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
6133 tree function)
6135 tree logical4_type_node = gfc_get_logical_type (4);
6136 tree type;
6137 tree fndecl;
6138 tree *args;
6139 unsigned int num_args;
6141 args = XALLOCAVEC (tree, 5);
6143 /* Get number of arguments; characters count double due to the
6144 string length argument. Kind= is not passed to the library
6145 and thus ignored. */
6146 if (expr->value.function.actual->next->next->expr == NULL)
6147 num_args = 4;
6148 else
6149 num_args = 5;
6151 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6152 type = gfc_typenode_for_spec (&expr->ts);
6154 if (num_args == 4)
6155 args[4] = build_int_cst (logical4_type_node, 0);
6156 else
6157 args[4] = convert (logical4_type_node, args[4]);
6159 fndecl = build_addr (function);
6160 se->expr = build_call_array_loc (input_location,
6161 TREE_TYPE (TREE_TYPE (function)), fndecl,
6162 5, args);
6163 se->expr = convert (type, se->expr);
6167 /* The ascii value for a single character. */
6168 static void
6169 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
6171 tree args[3], type, pchartype;
6172 int nargs;
6174 nargs = gfc_intrinsic_argument_list_length (expr);
6175 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6176 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
6177 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
6178 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
6179 type = gfc_typenode_for_spec (&expr->ts);
6181 se->expr = build_fold_indirect_ref_loc (input_location,
6182 args[1]);
6183 se->expr = convert (type, se->expr);
6187 /* Intrinsic ISNAN calls __builtin_isnan. */
6189 static void
6190 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
6192 tree arg;
6194 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6195 se->expr = build_call_expr_loc (input_location,
6196 builtin_decl_explicit (BUILT_IN_ISNAN),
6197 1, arg);
6198 STRIP_TYPE_NOPS (se->expr);
6199 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6203 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
6204 their argument against a constant integer value. */
6206 static void
6207 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
6209 tree arg;
6211 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6212 se->expr = fold_build2_loc (input_location, EQ_EXPR,
6213 gfc_typenode_for_spec (&expr->ts),
6214 arg, build_int_cst (TREE_TYPE (arg), value));
6219 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
6221 static void
6222 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
6224 tree tsource;
6225 tree fsource;
6226 tree mask;
6227 tree type;
6228 tree len, len2;
6229 tree *args;
6230 unsigned int num_args;
6232 num_args = gfc_intrinsic_argument_list_length (expr);
6233 args = XALLOCAVEC (tree, num_args);
6235 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6236 if (expr->ts.type != BT_CHARACTER)
6238 tsource = args[0];
6239 fsource = args[1];
6240 mask = args[2];
6242 else
6244 /* We do the same as in the non-character case, but the argument
6245 list is different because of the string length arguments. We
6246 also have to set the string length for the result. */
6247 len = args[0];
6248 tsource = args[1];
6249 len2 = args[2];
6250 fsource = args[3];
6251 mask = args[4];
6253 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
6254 &se->pre);
6255 se->string_length = len;
6257 type = TREE_TYPE (tsource);
6258 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
6259 fold_convert (type, fsource));
6263 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
6265 static void
6266 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
6268 tree args[3], mask, type;
6270 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6271 mask = gfc_evaluate_now (args[2], &se->pre);
6273 type = TREE_TYPE (args[0]);
6274 gcc_assert (TREE_TYPE (args[1]) == type);
6275 gcc_assert (TREE_TYPE (mask) == type);
6277 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
6278 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
6279 fold_build1_loc (input_location, BIT_NOT_EXPR,
6280 type, mask));
6281 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
6282 args[0], args[1]);
6286 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
6287 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
6289 static void
6290 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
6292 tree arg, allones, type, utype, res, cond, bitsize;
6293 int i;
6295 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6296 arg = gfc_evaluate_now (arg, &se->pre);
6298 type = gfc_get_int_type (expr->ts.kind);
6299 utype = unsigned_type_for (type);
6301 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
6302 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
6304 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
6305 build_int_cst (utype, 0));
6307 if (left)
6309 /* Left-justified mask. */
6310 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
6311 bitsize, arg);
6312 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6313 fold_convert (utype, res));
6315 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
6316 smaller than type width. */
6317 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
6318 build_int_cst (TREE_TYPE (arg), 0));
6319 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
6320 build_int_cst (utype, 0), res);
6322 else
6324 /* Right-justified mask. */
6325 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6326 fold_convert (utype, arg));
6327 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
6329 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
6330 strictly smaller than type width. */
6331 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6332 arg, bitsize);
6333 res = fold_build3_loc (input_location, COND_EXPR, utype,
6334 cond, allones, res);
6337 se->expr = fold_convert (type, res);
6341 /* FRACTION (s) is translated into:
6342 isfinite (s) ? frexp (s, &dummy_int) : NaN */
6343 static void
6344 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
6346 tree arg, type, tmp, res, frexp, cond;
6348 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6350 type = gfc_typenode_for_spec (&expr->ts);
6351 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6352 arg = gfc_evaluate_now (arg, &se->pre);
6354 cond = build_call_expr_loc (input_location,
6355 builtin_decl_explicit (BUILT_IN_ISFINITE),
6356 1, arg);
6358 tmp = gfc_create_var (integer_type_node, NULL);
6359 res = build_call_expr_loc (input_location, frexp, 2,
6360 fold_convert (type, arg),
6361 gfc_build_addr_expr (NULL_TREE, tmp));
6362 res = fold_convert (type, res);
6364 se->expr = fold_build3_loc (input_location, COND_EXPR, type,
6365 cond, res, gfc_build_nan (type, ""));
6369 /* NEAREST (s, dir) is translated into
6370 tmp = copysign (HUGE_VAL, dir);
6371 return nextafter (s, tmp);
6373 static void
6374 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
6376 tree args[2], type, tmp, nextafter, copysign, huge_val;
6378 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
6379 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
6381 type = gfc_typenode_for_spec (&expr->ts);
6382 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6384 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
6385 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
6386 fold_convert (type, args[1]));
6387 se->expr = build_call_expr_loc (input_location, nextafter, 2,
6388 fold_convert (type, args[0]), tmp);
6389 se->expr = fold_convert (type, se->expr);
6393 /* SPACING (s) is translated into
6394 int e;
6395 if (!isfinite (s))
6396 res = NaN;
6397 else if (s == 0)
6398 res = tiny;
6399 else
6401 frexp (s, &e);
6402 e = e - prec;
6403 e = MAX_EXPR (e, emin);
6404 res = scalbn (1., e);
6406 return res;
6408 where prec is the precision of s, gfc_real_kinds[k].digits,
6409 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
6410 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
6412 static void
6413 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
6415 tree arg, type, prec, emin, tiny, res, e;
6416 tree cond, nan, tmp, frexp, scalbn;
6417 int k;
6418 stmtblock_t block;
6420 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
6421 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
6422 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
6423 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
6425 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6426 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6428 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6429 arg = gfc_evaluate_now (arg, &se->pre);
6431 type = gfc_typenode_for_spec (&expr->ts);
6432 e = gfc_create_var (integer_type_node, NULL);
6433 res = gfc_create_var (type, NULL);
6436 /* Build the block for s /= 0. */
6437 gfc_start_block (&block);
6438 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
6439 gfc_build_addr_expr (NULL_TREE, e));
6440 gfc_add_expr_to_block (&block, tmp);
6442 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
6443 prec);
6444 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
6445 integer_type_node, tmp, emin));
6447 tmp = build_call_expr_loc (input_location, scalbn, 2,
6448 build_real_from_int_cst (type, integer_one_node), e);
6449 gfc_add_modify (&block, res, tmp);
6451 /* Finish by building the IF statement for value zero. */
6452 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
6453 build_real_from_int_cst (type, integer_zero_node));
6454 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
6455 gfc_finish_block (&block));
6457 /* And deal with infinities and NaNs. */
6458 cond = build_call_expr_loc (input_location,
6459 builtin_decl_explicit (BUILT_IN_ISFINITE),
6460 1, arg);
6461 nan = gfc_build_nan (type, "");
6462 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
6464 gfc_add_expr_to_block (&se->pre, tmp);
6465 se->expr = res;
6469 /* RRSPACING (s) is translated into
6470 int e;
6471 real x;
6472 x = fabs (s);
6473 if (isfinite (x))
6475 if (x != 0)
6477 frexp (s, &e);
6478 x = scalbn (x, precision - e);
6481 else
6482 x = NaN;
6483 return x;
6485 where precision is gfc_real_kinds[k].digits. */
6487 static void
6488 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
6490 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
6491 int prec, k;
6492 stmtblock_t block;
6494 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
6495 prec = gfc_real_kinds[k].digits;
6497 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6498 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6499 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
6501 type = gfc_typenode_for_spec (&expr->ts);
6502 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6503 arg = gfc_evaluate_now (arg, &se->pre);
6505 e = gfc_create_var (integer_type_node, NULL);
6506 x = gfc_create_var (type, NULL);
6507 gfc_add_modify (&se->pre, x,
6508 build_call_expr_loc (input_location, fabs, 1, arg));
6511 gfc_start_block (&block);
6512 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
6513 gfc_build_addr_expr (NULL_TREE, e));
6514 gfc_add_expr_to_block (&block, tmp);
6516 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
6517 build_int_cst (integer_type_node, prec), e);
6518 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
6519 gfc_add_modify (&block, x, tmp);
6520 stmt = gfc_finish_block (&block);
6522 /* if (x != 0) */
6523 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, x,
6524 build_real_from_int_cst (type, integer_zero_node));
6525 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
6527 /* And deal with infinities and NaNs. */
6528 cond = build_call_expr_loc (input_location,
6529 builtin_decl_explicit (BUILT_IN_ISFINITE),
6530 1, x);
6531 nan = gfc_build_nan (type, "");
6532 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
6534 gfc_add_expr_to_block (&se->pre, tmp);
6535 se->expr = fold_convert (type, x);
6539 /* SCALE (s, i) is translated into scalbn (s, i). */
6540 static void
6541 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
6543 tree args[2], type, scalbn;
6545 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6547 type = gfc_typenode_for_spec (&expr->ts);
6548 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6549 se->expr = build_call_expr_loc (input_location, scalbn, 2,
6550 fold_convert (type, args[0]),
6551 fold_convert (integer_type_node, args[1]));
6552 se->expr = fold_convert (type, se->expr);
6556 /* SET_EXPONENT (s, i) is translated into
6557 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
6558 static void
6559 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
6561 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
6563 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6564 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6566 type = gfc_typenode_for_spec (&expr->ts);
6567 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6568 args[0] = gfc_evaluate_now (args[0], &se->pre);
6570 tmp = gfc_create_var (integer_type_node, NULL);
6571 tmp = build_call_expr_loc (input_location, frexp, 2,
6572 fold_convert (type, args[0]),
6573 gfc_build_addr_expr (NULL_TREE, tmp));
6574 res = build_call_expr_loc (input_location, scalbn, 2, tmp,
6575 fold_convert (integer_type_node, args[1]));
6576 res = fold_convert (type, res);
6578 /* Call to isfinite */
6579 cond = build_call_expr_loc (input_location,
6580 builtin_decl_explicit (BUILT_IN_ISFINITE),
6581 1, args[0]);
6582 nan = gfc_build_nan (type, "");
6584 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
6585 res, nan);
6589 static void
6590 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
6592 gfc_actual_arglist *actual;
6593 tree arg1;
6594 tree type;
6595 tree fncall0;
6596 tree fncall1;
6597 gfc_se argse;
6599 gfc_init_se (&argse, NULL);
6600 actual = expr->value.function.actual;
6602 if (actual->expr->ts.type == BT_CLASS)
6603 gfc_add_class_array_ref (actual->expr);
6605 argse.data_not_needed = 1;
6606 if (gfc_is_alloc_class_array_function (actual->expr))
6608 /* For functions that return a class array conv_expr_descriptor is not
6609 able to get the descriptor right. Therefore this special case. */
6610 gfc_conv_expr_reference (&argse, actual->expr);
6611 argse.expr = gfc_build_addr_expr (NULL_TREE,
6612 gfc_class_data_get (argse.expr));
6614 else
6616 argse.want_pointer = 1;
6617 gfc_conv_expr_descriptor (&argse, actual->expr);
6619 gfc_add_block_to_block (&se->pre, &argse.pre);
6620 gfc_add_block_to_block (&se->post, &argse.post);
6621 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
6623 /* Build the call to size0. */
6624 fncall0 = build_call_expr_loc (input_location,
6625 gfor_fndecl_size0, 1, arg1);
6627 actual = actual->next;
6629 if (actual->expr)
6631 gfc_init_se (&argse, NULL);
6632 gfc_conv_expr_type (&argse, actual->expr,
6633 gfc_array_index_type);
6634 gfc_add_block_to_block (&se->pre, &argse.pre);
6636 /* Unusually, for an intrinsic, size does not exclude
6637 an optional arg2, so we must test for it. */
6638 if (actual->expr->expr_type == EXPR_VARIABLE
6639 && actual->expr->symtree->n.sym->attr.dummy
6640 && actual->expr->symtree->n.sym->attr.optional)
6642 tree tmp;
6643 /* Build the call to size1. */
6644 fncall1 = build_call_expr_loc (input_location,
6645 gfor_fndecl_size1, 2,
6646 arg1, argse.expr);
6648 gfc_init_se (&argse, NULL);
6649 argse.want_pointer = 1;
6650 argse.data_not_needed = 1;
6651 gfc_conv_expr (&argse, actual->expr);
6652 gfc_add_block_to_block (&se->pre, &argse.pre);
6653 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6654 argse.expr, null_pointer_node);
6655 tmp = gfc_evaluate_now (tmp, &se->pre);
6656 se->expr = fold_build3_loc (input_location, COND_EXPR,
6657 pvoid_type_node, tmp, fncall1, fncall0);
6659 else
6661 se->expr = NULL_TREE;
6662 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
6663 gfc_array_index_type,
6664 argse.expr, gfc_index_one_node);
6667 else if (expr->value.function.actual->expr->rank == 1)
6669 argse.expr = gfc_index_zero_node;
6670 se->expr = NULL_TREE;
6672 else
6673 se->expr = fncall0;
6675 if (se->expr == NULL_TREE)
6677 tree ubound, lbound;
6679 arg1 = build_fold_indirect_ref_loc (input_location,
6680 arg1);
6681 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
6682 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
6683 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
6684 gfc_array_index_type, ubound, lbound);
6685 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
6686 gfc_array_index_type,
6687 se->expr, gfc_index_one_node);
6688 se->expr = fold_build2_loc (input_location, MAX_EXPR,
6689 gfc_array_index_type, se->expr,
6690 gfc_index_zero_node);
6693 type = gfc_typenode_for_spec (&expr->ts);
6694 se->expr = convert (type, se->expr);
6698 /* Helper function to compute the size of a character variable,
6699 excluding the terminating null characters. The result has
6700 gfc_array_index_type type. */
6702 tree
6703 size_of_string_in_bytes (int kind, tree string_length)
6705 tree bytesize;
6706 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
6708 bytesize = build_int_cst (gfc_array_index_type,
6709 gfc_character_kinds[i].bit_size / 8);
6711 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6712 bytesize,
6713 fold_convert (gfc_array_index_type, string_length));
6717 static void
6718 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
6720 gfc_expr *arg;
6721 gfc_se argse;
6722 tree source_bytes;
6723 tree tmp;
6724 tree lower;
6725 tree upper;
6726 tree byte_size;
6727 int n;
6729 gfc_init_se (&argse, NULL);
6730 arg = expr->value.function.actual->expr;
6732 if (arg->rank || arg->ts.type == BT_ASSUMED)
6733 gfc_conv_expr_descriptor (&argse, arg);
6734 else
6735 gfc_conv_expr_reference (&argse, arg);
6737 if (arg->ts.type == BT_ASSUMED)
6739 /* This only works if an array descriptor has been passed; thus, extract
6740 the size from the descriptor. */
6741 gcc_assert (TYPE_PRECISION (gfc_array_index_type)
6742 == TYPE_PRECISION (size_type_node));
6743 tmp = arg->symtree->n.sym->backend_decl;
6744 tmp = DECL_LANG_SPECIFIC (tmp)
6745 && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
6746 ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
6747 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
6748 tmp = build_fold_indirect_ref_loc (input_location, tmp);
6749 tmp = fold_convert (size_type_node, gfc_conv_descriptor_dtype (tmp));
6750 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, TREE_TYPE (tmp), tmp,
6751 build_int_cst (TREE_TYPE (tmp),
6752 GFC_DTYPE_SIZE_SHIFT));
6753 byte_size = fold_convert (gfc_array_index_type, tmp);
6755 else if (arg->ts.type == BT_CLASS)
6757 /* Conv_expr_descriptor returns a component_ref to _data component of the
6758 class object. The class object may be a non-pointer object, e.g.
6759 located on the stack, or a memory location pointed to, e.g. a
6760 parameter, i.e., an indirect_ref. */
6761 if (arg->rank < 0
6762 || (arg->rank > 0 && !VAR_P (argse.expr)
6763 && ((INDIRECT_REF_P (TREE_OPERAND (argse.expr, 0))
6764 && GFC_DECL_CLASS (TREE_OPERAND (
6765 TREE_OPERAND (argse.expr, 0), 0)))
6766 || GFC_DECL_CLASS (TREE_OPERAND (argse.expr, 0)))))
6767 byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
6768 else if (arg->rank > 0
6769 || (arg->rank == 0
6770 && arg->ref && arg->ref->type == REF_COMPONENT))
6771 /* The scalarizer added an additional temp. To get the class' vptr
6772 one has to look at the original backend_decl. */
6773 byte_size = gfc_class_vtab_size_get (
6774 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
6775 else
6776 byte_size = gfc_class_vtab_size_get (argse.expr);
6778 else
6780 if (arg->ts.type == BT_CHARACTER)
6781 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
6782 else
6784 if (arg->rank == 0)
6785 byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
6786 argse.expr));
6787 else
6788 byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
6789 byte_size = fold_convert (gfc_array_index_type,
6790 size_in_bytes (byte_size));
6794 if (arg->rank == 0)
6795 se->expr = byte_size;
6796 else
6798 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
6799 gfc_add_modify (&argse.pre, source_bytes, byte_size);
6801 if (arg->rank == -1)
6803 tree cond, loop_var, exit_label;
6804 stmtblock_t body;
6806 tmp = fold_convert (gfc_array_index_type,
6807 gfc_conv_descriptor_rank (argse.expr));
6808 loop_var = gfc_create_var (gfc_array_index_type, "i");
6809 gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
6810 exit_label = gfc_build_label_decl (NULL_TREE);
6812 /* Create loop:
6813 for (;;)
6815 if (i >= rank)
6816 goto exit;
6817 source_bytes = source_bytes * array.dim[i].extent;
6818 i = i + 1;
6820 exit: */
6821 gfc_start_block (&body);
6822 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
6823 loop_var, tmp);
6824 tmp = build1_v (GOTO_EXPR, exit_label);
6825 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
6826 cond, tmp, build_empty_stmt (input_location));
6827 gfc_add_expr_to_block (&body, tmp);
6829 lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
6830 upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
6831 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
6832 tmp = fold_build2_loc (input_location, MULT_EXPR,
6833 gfc_array_index_type, tmp, source_bytes);
6834 gfc_add_modify (&body, source_bytes, tmp);
6836 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6837 gfc_array_index_type, loop_var,
6838 gfc_index_one_node);
6839 gfc_add_modify_loc (input_location, &body, loop_var, tmp);
6841 tmp = gfc_finish_block (&body);
6843 tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
6844 tmp);
6845 gfc_add_expr_to_block (&argse.pre, tmp);
6847 tmp = build1_v (LABEL_EXPR, exit_label);
6848 gfc_add_expr_to_block (&argse.pre, tmp);
6850 else
6852 /* Obtain the size of the array in bytes. */
6853 for (n = 0; n < arg->rank; n++)
6855 tree idx;
6856 idx = gfc_rank_cst[n];
6857 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
6858 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
6859 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
6860 tmp = fold_build2_loc (input_location, MULT_EXPR,
6861 gfc_array_index_type, tmp, source_bytes);
6862 gfc_add_modify (&argse.pre, source_bytes, tmp);
6865 se->expr = source_bytes;
6868 gfc_add_block_to_block (&se->pre, &argse.pre);
6872 static void
6873 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
6875 gfc_expr *arg;
6876 gfc_se argse;
6877 tree type, result_type, tmp;
6879 arg = expr->value.function.actual->expr;
6881 gfc_init_se (&argse, NULL);
6882 result_type = gfc_get_int_type (expr->ts.kind);
6884 if (arg->rank == 0)
6886 if (arg->ts.type == BT_CLASS)
6888 gfc_add_vptr_component (arg);
6889 gfc_add_size_component (arg);
6890 gfc_conv_expr (&argse, arg);
6891 tmp = fold_convert (result_type, argse.expr);
6892 goto done;
6895 gfc_conv_expr_reference (&argse, arg);
6896 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
6897 argse.expr));
6899 else
6901 argse.want_pointer = 0;
6902 gfc_conv_expr_descriptor (&argse, arg);
6903 if (arg->ts.type == BT_CLASS)
6905 if (arg->rank > 0)
6906 tmp = gfc_class_vtab_size_get (
6907 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
6908 else
6909 tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
6910 tmp = fold_convert (result_type, tmp);
6911 goto done;
6913 type = gfc_get_element_type (TREE_TYPE (argse.expr));
6916 /* Obtain the argument's word length. */
6917 if (arg->ts.type == BT_CHARACTER)
6918 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
6919 else
6920 tmp = size_in_bytes (type);
6921 tmp = fold_convert (result_type, tmp);
6923 done:
6924 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
6925 build_int_cst (result_type, BITS_PER_UNIT));
6926 gfc_add_block_to_block (&se->pre, &argse.pre);
6930 /* Intrinsic string comparison functions. */
6932 static void
6933 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
6935 tree args[4];
6937 gfc_conv_intrinsic_function_args (se, expr, args, 4);
6939 se->expr
6940 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
6941 expr->value.function.actual->expr->ts.kind,
6942 op);
6943 se->expr = fold_build2_loc (input_location, op,
6944 gfc_typenode_for_spec (&expr->ts), se->expr,
6945 build_int_cst (TREE_TYPE (se->expr), 0));
6948 /* Generate a call to the adjustl/adjustr library function. */
6949 static void
6950 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
6952 tree args[3];
6953 tree len;
6954 tree type;
6955 tree var;
6956 tree tmp;
6958 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
6959 len = args[1];
6961 type = TREE_TYPE (args[2]);
6962 var = gfc_conv_string_tmp (se, type, len);
6963 args[0] = var;
6965 tmp = build_call_expr_loc (input_location,
6966 fndecl, 3, args[0], args[1], args[2]);
6967 gfc_add_expr_to_block (&se->pre, tmp);
6968 se->expr = var;
6969 se->string_length = len;
6973 /* Generate code for the TRANSFER intrinsic:
6974 For scalar results:
6975 DEST = TRANSFER (SOURCE, MOLD)
6976 where:
6977 typeof<DEST> = typeof<MOLD>
6978 and:
6979 MOLD is scalar.
6981 For array results:
6982 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
6983 where:
6984 typeof<DEST> = typeof<MOLD>
6985 and:
6986 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
6987 sizeof (DEST(0) * SIZE). */
6988 static void
6989 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
6991 tree tmp;
6992 tree tmpdecl;
6993 tree ptr;
6994 tree extent;
6995 tree source;
6996 tree source_type;
6997 tree source_bytes;
6998 tree mold_type;
6999 tree dest_word_len;
7000 tree size_words;
7001 tree size_bytes;
7002 tree upper;
7003 tree lower;
7004 tree stmt;
7005 gfc_actual_arglist *arg;
7006 gfc_se argse;
7007 gfc_array_info *info;
7008 stmtblock_t block;
7009 int n;
7010 bool scalar_mold;
7011 gfc_expr *source_expr, *mold_expr;
7013 info = NULL;
7014 if (se->loop)
7015 info = &se->ss->info->data.array;
7017 /* Convert SOURCE. The output from this stage is:-
7018 source_bytes = length of the source in bytes
7019 source = pointer to the source data. */
7020 arg = expr->value.function.actual;
7021 source_expr = arg->expr;
7023 /* Ensure double transfer through LOGICAL preserves all
7024 the needed bits. */
7025 if (arg->expr->expr_type == EXPR_FUNCTION
7026 && arg->expr->value.function.esym == NULL
7027 && arg->expr->value.function.isym != NULL
7028 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
7029 && arg->expr->ts.type == BT_LOGICAL
7030 && expr->ts.type != arg->expr->ts.type)
7031 arg->expr->value.function.name = "__transfer_in_transfer";
7033 gfc_init_se (&argse, NULL);
7035 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
7037 /* Obtain the pointer to source and the length of source in bytes. */
7038 if (arg->expr->rank == 0)
7040 gfc_conv_expr_reference (&argse, arg->expr);
7041 if (arg->expr->ts.type == BT_CLASS)
7042 source = gfc_class_data_get (argse.expr);
7043 else
7044 source = argse.expr;
7046 /* Obtain the source word length. */
7047 switch (arg->expr->ts.type)
7049 case BT_CHARACTER:
7050 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7051 argse.string_length);
7052 break;
7053 case BT_CLASS:
7054 tmp = gfc_class_vtab_size_get (argse.expr);
7055 break;
7056 default:
7057 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7058 source));
7059 tmp = fold_convert (gfc_array_index_type,
7060 size_in_bytes (source_type));
7061 break;
7064 else
7066 argse.want_pointer = 0;
7067 gfc_conv_expr_descriptor (&argse, arg->expr);
7068 source = gfc_conv_descriptor_data_get (argse.expr);
7069 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7071 /* Repack the source if not simply contiguous. */
7072 if (!gfc_is_simply_contiguous (arg->expr, false, true))
7074 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
7076 if (warn_array_temporaries)
7077 gfc_warning (OPT_Warray_temporaries,
7078 "Creating array temporary at %L", &expr->where);
7080 source = build_call_expr_loc (input_location,
7081 gfor_fndecl_in_pack, 1, tmp);
7082 source = gfc_evaluate_now (source, &argse.pre);
7084 /* Free the temporary. */
7085 gfc_start_block (&block);
7086 tmp = gfc_call_free (source);
7087 gfc_add_expr_to_block (&block, tmp);
7088 stmt = gfc_finish_block (&block);
7090 /* Clean up if it was repacked. */
7091 gfc_init_block (&block);
7092 tmp = gfc_conv_array_data (argse.expr);
7093 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7094 source, tmp);
7095 tmp = build3_v (COND_EXPR, tmp, stmt,
7096 build_empty_stmt (input_location));
7097 gfc_add_expr_to_block (&block, tmp);
7098 gfc_add_block_to_block (&block, &se->post);
7099 gfc_init_block (&se->post);
7100 gfc_add_block_to_block (&se->post, &block);
7103 /* Obtain the source word length. */
7104 if (arg->expr->ts.type == BT_CHARACTER)
7105 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7106 argse.string_length);
7107 else
7108 tmp = fold_convert (gfc_array_index_type,
7109 size_in_bytes (source_type));
7111 /* Obtain the size of the array in bytes. */
7112 extent = gfc_create_var (gfc_array_index_type, NULL);
7113 for (n = 0; n < arg->expr->rank; n++)
7115 tree idx;
7116 idx = gfc_rank_cst[n];
7117 gfc_add_modify (&argse.pre, source_bytes, tmp);
7118 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
7119 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
7120 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7121 gfc_array_index_type, upper, lower);
7122 gfc_add_modify (&argse.pre, extent, tmp);
7123 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7124 gfc_array_index_type, extent,
7125 gfc_index_one_node);
7126 tmp = fold_build2_loc (input_location, MULT_EXPR,
7127 gfc_array_index_type, tmp, source_bytes);
7131 gfc_add_modify (&argse.pre, source_bytes, tmp);
7132 gfc_add_block_to_block (&se->pre, &argse.pre);
7133 gfc_add_block_to_block (&se->post, &argse.post);
7135 /* Now convert MOLD. The outputs are:
7136 mold_type = the TREE type of MOLD
7137 dest_word_len = destination word length in bytes. */
7138 arg = arg->next;
7139 mold_expr = arg->expr;
7141 gfc_init_se (&argse, NULL);
7143 scalar_mold = arg->expr->rank == 0;
7145 if (arg->expr->rank == 0)
7147 gfc_conv_expr_reference (&argse, arg->expr);
7148 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7149 argse.expr));
7151 else
7153 gfc_init_se (&argse, NULL);
7154 argse.want_pointer = 0;
7155 gfc_conv_expr_descriptor (&argse, arg->expr);
7156 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7159 gfc_add_block_to_block (&se->pre, &argse.pre);
7160 gfc_add_block_to_block (&se->post, &argse.post);
7162 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
7164 /* If this TRANSFER is nested in another TRANSFER, use a type
7165 that preserves all bits. */
7166 if (arg->expr->ts.type == BT_LOGICAL)
7167 mold_type = gfc_get_int_type (arg->expr->ts.kind);
7170 /* Obtain the destination word length. */
7171 switch (arg->expr->ts.type)
7173 case BT_CHARACTER:
7174 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
7175 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
7176 break;
7177 case BT_CLASS:
7178 tmp = gfc_class_vtab_size_get (argse.expr);
7179 break;
7180 default:
7181 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
7182 break;
7184 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
7185 gfc_add_modify (&se->pre, dest_word_len, tmp);
7187 /* Finally convert SIZE, if it is present. */
7188 arg = arg->next;
7189 size_words = gfc_create_var (gfc_array_index_type, NULL);
7191 if (arg->expr)
7193 gfc_init_se (&argse, NULL);
7194 gfc_conv_expr_reference (&argse, arg->expr);
7195 tmp = convert (gfc_array_index_type,
7196 build_fold_indirect_ref_loc (input_location,
7197 argse.expr));
7198 gfc_add_block_to_block (&se->pre, &argse.pre);
7199 gfc_add_block_to_block (&se->post, &argse.post);
7201 else
7202 tmp = NULL_TREE;
7204 /* Separate array and scalar results. */
7205 if (scalar_mold && tmp == NULL_TREE)
7206 goto scalar_transfer;
7208 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
7209 if (tmp != NULL_TREE)
7210 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7211 tmp, dest_word_len);
7212 else
7213 tmp = source_bytes;
7215 gfc_add_modify (&se->pre, size_bytes, tmp);
7216 gfc_add_modify (&se->pre, size_words,
7217 fold_build2_loc (input_location, CEIL_DIV_EXPR,
7218 gfc_array_index_type,
7219 size_bytes, dest_word_len));
7221 /* Evaluate the bounds of the result. If the loop range exists, we have
7222 to check if it is too large. If so, we modify loop->to be consistent
7223 with min(size, size(source)). Otherwise, size is made consistent with
7224 the loop range, so that the right number of bytes is transferred.*/
7225 n = se->loop->order[0];
7226 if (se->loop->to[n] != NULL_TREE)
7228 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7229 se->loop->to[n], se->loop->from[n]);
7230 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7231 tmp, gfc_index_one_node);
7232 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7233 tmp, size_words);
7234 gfc_add_modify (&se->pre, size_words, tmp);
7235 gfc_add_modify (&se->pre, size_bytes,
7236 fold_build2_loc (input_location, MULT_EXPR,
7237 gfc_array_index_type,
7238 size_words, dest_word_len));
7239 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7240 size_words, se->loop->from[n]);
7241 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7242 upper, gfc_index_one_node);
7244 else
7246 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7247 size_words, gfc_index_one_node);
7248 se->loop->from[n] = gfc_index_zero_node;
7251 se->loop->to[n] = upper;
7253 /* Build a destination descriptor, using the pointer, source, as the
7254 data field. */
7255 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
7256 NULL_TREE, false, true, false, &expr->where);
7258 /* Cast the pointer to the result. */
7259 tmp = gfc_conv_descriptor_data_get (info->descriptor);
7260 tmp = fold_convert (pvoid_type_node, tmp);
7262 /* Use memcpy to do the transfer. */
7264 = build_call_expr_loc (input_location,
7265 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
7266 fold_convert (pvoid_type_node, source),
7267 fold_convert (size_type_node,
7268 fold_build2_loc (input_location,
7269 MIN_EXPR,
7270 gfc_array_index_type,
7271 size_bytes,
7272 source_bytes)));
7273 gfc_add_expr_to_block (&se->pre, tmp);
7275 se->expr = info->descriptor;
7276 if (expr->ts.type == BT_CHARACTER)
7277 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7279 return;
7281 /* Deal with scalar results. */
7282 scalar_transfer:
7283 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7284 dest_word_len, source_bytes);
7285 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
7286 extent, gfc_index_zero_node);
7288 if (expr->ts.type == BT_CHARACTER)
7290 tree direct, indirect, free;
7292 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
7293 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
7294 "transfer");
7296 /* If source is longer than the destination, use a pointer to
7297 the source directly. */
7298 gfc_init_block (&block);
7299 gfc_add_modify (&block, tmpdecl, ptr);
7300 direct = gfc_finish_block (&block);
7302 /* Otherwise, allocate a string with the length of the destination
7303 and copy the source into it. */
7304 gfc_init_block (&block);
7305 tmp = gfc_get_pchar_type (expr->ts.kind);
7306 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
7307 gfc_add_modify (&block, tmpdecl,
7308 fold_convert (TREE_TYPE (ptr), tmp));
7309 tmp = build_call_expr_loc (input_location,
7310 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7311 fold_convert (pvoid_type_node, tmpdecl),
7312 fold_convert (pvoid_type_node, ptr),
7313 fold_convert (size_type_node, extent));
7314 gfc_add_expr_to_block (&block, tmp);
7315 indirect = gfc_finish_block (&block);
7317 /* Wrap it up with the condition. */
7318 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
7319 dest_word_len, source_bytes);
7320 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
7321 gfc_add_expr_to_block (&se->pre, tmp);
7323 /* Free the temporary string, if necessary. */
7324 free = gfc_call_free (tmpdecl);
7325 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
7326 dest_word_len, source_bytes);
7327 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
7328 gfc_add_expr_to_block (&se->post, tmp);
7330 se->expr = tmpdecl;
7331 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7333 else
7335 tmpdecl = gfc_create_var (mold_type, "transfer");
7337 ptr = convert (build_pointer_type (mold_type), source);
7339 /* For CLASS results, allocate the needed memory first. */
7340 if (mold_expr->ts.type == BT_CLASS)
7342 tree cdata;
7343 cdata = gfc_class_data_get (tmpdecl);
7344 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
7345 gfc_add_modify (&se->pre, cdata, tmp);
7348 /* Use memcpy to do the transfer. */
7349 if (mold_expr->ts.type == BT_CLASS)
7350 tmp = gfc_class_data_get (tmpdecl);
7351 else
7352 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
7354 tmp = build_call_expr_loc (input_location,
7355 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7356 fold_convert (pvoid_type_node, tmp),
7357 fold_convert (pvoid_type_node, ptr),
7358 fold_convert (size_type_node, extent));
7359 gfc_add_expr_to_block (&se->pre, tmp);
7361 /* For CLASS results, set the _vptr. */
7362 if (mold_expr->ts.type == BT_CLASS)
7364 tree vptr;
7365 gfc_symbol *vtab;
7366 vptr = gfc_class_vptr_get (tmpdecl);
7367 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
7368 gcc_assert (vtab);
7369 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7370 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
7373 se->expr = tmpdecl;
7378 /* Generate a call to caf_is_present. */
7380 static tree
7381 trans_caf_is_present (gfc_se *se, gfc_expr *expr)
7383 tree caf_reference, caf_decl, token, image_index;
7385 /* Compile the reference chain. */
7386 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
7387 gcc_assert (caf_reference != NULL_TREE);
7389 caf_decl = gfc_get_tree_for_caf_expr (expr);
7390 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
7391 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
7392 image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
7393 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
7394 expr);
7396 return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
7397 3, token, image_index, caf_reference);
7401 /* Test whether this ref-chain refs this image only. */
7403 static bool
7404 caf_this_image_ref (gfc_ref *ref)
7406 for ( ; ref; ref = ref->next)
7407 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
7408 return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
7410 return false;
7414 /* Generate code for the ALLOCATED intrinsic.
7415 Generate inline code that directly check the address of the argument. */
7417 static void
7418 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
7420 gfc_actual_arglist *arg1;
7421 gfc_se arg1se;
7422 tree tmp;
7423 symbol_attribute caf_attr;
7425 gfc_init_se (&arg1se, NULL);
7426 arg1 = expr->value.function.actual;
7428 if (arg1->expr->ts.type == BT_CLASS)
7430 /* Make sure that class array expressions have both a _data
7431 component reference and an array reference.... */
7432 if (CLASS_DATA (arg1->expr)->attr.dimension)
7433 gfc_add_class_array_ref (arg1->expr);
7434 /* .... whilst scalars only need the _data component. */
7435 else
7436 gfc_add_data_component (arg1->expr);
7439 /* When arg1 references an allocatable component in a coarray, then call
7440 the caf-library function caf_is_present (). */
7441 if (flag_coarray == GFC_FCOARRAY_LIB && arg1->expr->expr_type == EXPR_FUNCTION
7442 && arg1->expr->value.function.isym
7443 && arg1->expr->value.function.isym->id == GFC_ISYM_CAF_GET)
7444 caf_attr = gfc_caf_attr (arg1->expr->value.function.actual->expr);
7445 else
7446 gfc_clear_attr (&caf_attr);
7447 if (flag_coarray == GFC_FCOARRAY_LIB && caf_attr.codimension
7448 && !caf_this_image_ref (arg1->expr->value.function.actual->expr->ref))
7449 tmp = trans_caf_is_present (se, arg1->expr->value.function.actual->expr);
7450 else
7452 if (arg1->expr->rank == 0)
7454 /* Allocatable scalar. */
7455 arg1se.want_pointer = 1;
7456 gfc_conv_expr (&arg1se, arg1->expr);
7457 tmp = arg1se.expr;
7459 else
7461 /* Allocatable array. */
7462 arg1se.descriptor_only = 1;
7463 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7464 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
7467 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
7468 fold_convert (TREE_TYPE (tmp), null_pointer_node));
7470 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
7474 /* Generate code for the ASSOCIATED intrinsic.
7475 If both POINTER and TARGET are arrays, generate a call to library function
7476 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
7477 In other cases, generate inline code that directly compare the address of
7478 POINTER with the address of TARGET. */
7480 static void
7481 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
7483 gfc_actual_arglist *arg1;
7484 gfc_actual_arglist *arg2;
7485 gfc_se arg1se;
7486 gfc_se arg2se;
7487 tree tmp2;
7488 tree tmp;
7489 tree nonzero_charlen;
7490 tree nonzero_arraylen;
7491 gfc_ss *ss;
7492 bool scalar;
7494 gfc_init_se (&arg1se, NULL);
7495 gfc_init_se (&arg2se, NULL);
7496 arg1 = expr->value.function.actual;
7497 arg2 = arg1->next;
7499 /* Check whether the expression is a scalar or not; we cannot use
7500 arg1->expr->rank as it can be nonzero for proc pointers. */
7501 ss = gfc_walk_expr (arg1->expr);
7502 scalar = ss == gfc_ss_terminator;
7503 if (!scalar)
7504 gfc_free_ss_chain (ss);
7506 if (!arg2->expr)
7508 /* No optional target. */
7509 if (scalar)
7511 /* A pointer to a scalar. */
7512 arg1se.want_pointer = 1;
7513 gfc_conv_expr (&arg1se, arg1->expr);
7514 if (arg1->expr->symtree->n.sym->attr.proc_pointer
7515 && arg1->expr->symtree->n.sym->attr.dummy)
7516 arg1se.expr = build_fold_indirect_ref_loc (input_location,
7517 arg1se.expr);
7518 if (arg1->expr->ts.type == BT_CLASS)
7520 tmp2 = gfc_class_data_get (arg1se.expr);
7521 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
7522 tmp2 = gfc_conv_descriptor_data_get (tmp2);
7524 else
7525 tmp2 = arg1se.expr;
7527 else
7529 /* A pointer to an array. */
7530 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7531 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
7533 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7534 gfc_add_block_to_block (&se->post, &arg1se.post);
7535 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp2,
7536 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
7537 se->expr = tmp;
7539 else
7541 /* An optional target. */
7542 if (arg2->expr->ts.type == BT_CLASS)
7543 gfc_add_data_component (arg2->expr);
7545 nonzero_charlen = NULL_TREE;
7546 if (arg1->expr->ts.type == BT_CHARACTER)
7547 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
7548 logical_type_node,
7549 arg1->expr->ts.u.cl->backend_decl,
7550 integer_zero_node);
7551 if (scalar)
7553 /* A pointer to a scalar. */
7554 arg1se.want_pointer = 1;
7555 gfc_conv_expr (&arg1se, arg1->expr);
7556 if (arg1->expr->symtree->n.sym->attr.proc_pointer
7557 && arg1->expr->symtree->n.sym->attr.dummy)
7558 arg1se.expr = build_fold_indirect_ref_loc (input_location,
7559 arg1se.expr);
7560 if (arg1->expr->ts.type == BT_CLASS)
7561 arg1se.expr = gfc_class_data_get (arg1se.expr);
7563 arg2se.want_pointer = 1;
7564 gfc_conv_expr (&arg2se, arg2->expr);
7565 if (arg2->expr->symtree->n.sym->attr.proc_pointer
7566 && arg2->expr->symtree->n.sym->attr.dummy)
7567 arg2se.expr = build_fold_indirect_ref_loc (input_location,
7568 arg2se.expr);
7569 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7570 gfc_add_block_to_block (&se->post, &arg1se.post);
7571 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7572 gfc_add_block_to_block (&se->post, &arg2se.post);
7573 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7574 arg1se.expr, arg2se.expr);
7575 tmp2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7576 arg1se.expr, null_pointer_node);
7577 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7578 logical_type_node, tmp, tmp2);
7580 else
7582 /* An array pointer of zero length is not associated if target is
7583 present. */
7584 arg1se.descriptor_only = 1;
7585 gfc_conv_expr_lhs (&arg1se, arg1->expr);
7586 if (arg1->expr->rank == -1)
7588 tmp = gfc_conv_descriptor_rank (arg1se.expr);
7589 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7590 TREE_TYPE (tmp), tmp, gfc_index_one_node);
7592 else
7593 tmp = gfc_rank_cst[arg1->expr->rank - 1];
7594 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
7595 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
7596 logical_type_node, tmp,
7597 build_int_cst (TREE_TYPE (tmp), 0));
7599 /* A pointer to an array, call library function _gfor_associated. */
7600 arg1se.want_pointer = 1;
7601 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7603 arg2se.want_pointer = 1;
7604 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
7605 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7606 gfc_add_block_to_block (&se->post, &arg2se.post);
7607 se->expr = build_call_expr_loc (input_location,
7608 gfor_fndecl_associated, 2,
7609 arg1se.expr, arg2se.expr);
7610 se->expr = convert (logical_type_node, se->expr);
7611 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7612 logical_type_node, se->expr,
7613 nonzero_arraylen);
7616 /* If target is present zero character length pointers cannot
7617 be associated. */
7618 if (nonzero_charlen != NULL_TREE)
7619 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7620 logical_type_node,
7621 se->expr, nonzero_charlen);
7624 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7628 /* Generate code for the SAME_TYPE_AS intrinsic.
7629 Generate inline code that directly checks the vindices. */
7631 static void
7632 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
7634 gfc_expr *a, *b;
7635 gfc_se se1, se2;
7636 tree tmp;
7637 tree conda = NULL_TREE, condb = NULL_TREE;
7639 gfc_init_se (&se1, NULL);
7640 gfc_init_se (&se2, NULL);
7642 a = expr->value.function.actual->expr;
7643 b = expr->value.function.actual->next->expr;
7645 if (UNLIMITED_POLY (a))
7647 tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
7648 conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7649 tmp, build_int_cst (TREE_TYPE (tmp), 0));
7652 if (UNLIMITED_POLY (b))
7654 tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
7655 condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7656 tmp, build_int_cst (TREE_TYPE (tmp), 0));
7659 if (a->ts.type == BT_CLASS)
7661 gfc_add_vptr_component (a);
7662 gfc_add_hash_component (a);
7664 else if (a->ts.type == BT_DERIVED)
7665 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
7666 a->ts.u.derived->hash_value);
7668 if (b->ts.type == BT_CLASS)
7670 gfc_add_vptr_component (b);
7671 gfc_add_hash_component (b);
7673 else if (b->ts.type == BT_DERIVED)
7674 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
7675 b->ts.u.derived->hash_value);
7677 gfc_conv_expr (&se1, a);
7678 gfc_conv_expr (&se2, b);
7680 tmp = fold_build2_loc (input_location, EQ_EXPR,
7681 logical_type_node, se1.expr,
7682 fold_convert (TREE_TYPE (se1.expr), se2.expr));
7684 if (conda)
7685 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
7686 logical_type_node, conda, tmp);
7688 if (condb)
7689 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
7690 logical_type_node, condb, tmp);
7692 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
7696 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
7698 static void
7699 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
7701 tree args[2];
7703 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7704 se->expr = build_call_expr_loc (input_location,
7705 gfor_fndecl_sc_kind, 2, args[0], args[1]);
7706 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7710 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
7712 static void
7713 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
7715 tree arg, type;
7717 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7719 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
7720 type = gfc_get_int_type (4);
7721 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
7723 /* Convert it to the required type. */
7724 type = gfc_typenode_for_spec (&expr->ts);
7725 se->expr = build_call_expr_loc (input_location,
7726 gfor_fndecl_si_kind, 1, arg);
7727 se->expr = fold_convert (type, se->expr);
7731 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
7733 static void
7734 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
7736 gfc_actual_arglist *actual;
7737 tree type;
7738 gfc_se argse;
7739 vec<tree, va_gc> *args = NULL;
7741 for (actual = expr->value.function.actual; actual; actual = actual->next)
7743 gfc_init_se (&argse, se);
7745 /* Pass a NULL pointer for an absent arg. */
7746 if (actual->expr == NULL)
7747 argse.expr = null_pointer_node;
7748 else
7750 gfc_typespec ts;
7751 gfc_clear_ts (&ts);
7753 if (actual->expr->ts.kind != gfc_c_int_kind)
7755 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
7756 ts.type = BT_INTEGER;
7757 ts.kind = gfc_c_int_kind;
7758 gfc_convert_type (actual->expr, &ts, 2);
7760 gfc_conv_expr_reference (&argse, actual->expr);
7763 gfc_add_block_to_block (&se->pre, &argse.pre);
7764 gfc_add_block_to_block (&se->post, &argse.post);
7765 vec_safe_push (args, argse.expr);
7768 /* Convert it to the required type. */
7769 type = gfc_typenode_for_spec (&expr->ts);
7770 se->expr = build_call_expr_loc_vec (input_location,
7771 gfor_fndecl_sr_kind, args);
7772 se->expr = fold_convert (type, se->expr);
7776 /* Generate code for TRIM (A) intrinsic function. */
7778 static void
7779 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
7781 tree var;
7782 tree len;
7783 tree addr;
7784 tree tmp;
7785 tree cond;
7786 tree fndecl;
7787 tree function;
7788 tree *args;
7789 unsigned int num_args;
7791 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
7792 args = XALLOCAVEC (tree, num_args);
7794 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
7795 addr = gfc_build_addr_expr (ppvoid_type_node, var);
7796 len = gfc_create_var (gfc_charlen_type_node, "len");
7798 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
7799 args[0] = gfc_build_addr_expr (NULL_TREE, len);
7800 args[1] = addr;
7802 if (expr->ts.kind == 1)
7803 function = gfor_fndecl_string_trim;
7804 else if (expr->ts.kind == 4)
7805 function = gfor_fndecl_string_trim_char4;
7806 else
7807 gcc_unreachable ();
7809 fndecl = build_addr (function);
7810 tmp = build_call_array_loc (input_location,
7811 TREE_TYPE (TREE_TYPE (function)), fndecl,
7812 num_args, args);
7813 gfc_add_expr_to_block (&se->pre, tmp);
7815 /* Free the temporary afterwards, if necessary. */
7816 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
7817 len, build_int_cst (TREE_TYPE (len), 0));
7818 tmp = gfc_call_free (var);
7819 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
7820 gfc_add_expr_to_block (&se->post, tmp);
7822 se->expr = var;
7823 se->string_length = len;
7827 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
7829 static void
7830 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
7832 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
7833 tree type, cond, tmp, count, exit_label, n, max, largest;
7834 tree size;
7835 stmtblock_t block, body;
7836 int i;
7838 /* We store in charsize the size of a character. */
7839 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
7840 size = build_int_cst (size_type_node, gfc_character_kinds[i].bit_size / 8);
7842 /* Get the arguments. */
7843 gfc_conv_intrinsic_function_args (se, expr, args, 3);
7844 slen = fold_convert (size_type_node, gfc_evaluate_now (args[0], &se->pre));
7845 src = args[1];
7846 ncopies = gfc_evaluate_now (args[2], &se->pre);
7847 ncopies_type = TREE_TYPE (ncopies);
7849 /* Check that NCOPIES is not negative. */
7850 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, ncopies,
7851 build_int_cst (ncopies_type, 0));
7852 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
7853 "Argument NCOPIES of REPEAT intrinsic is negative "
7854 "(its value is %ld)",
7855 fold_convert (long_integer_type_node, ncopies));
7857 /* If the source length is zero, any non negative value of NCOPIES
7858 is valid, and nothing happens. */
7859 n = gfc_create_var (ncopies_type, "ncopies");
7860 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
7861 build_int_cst (size_type_node, 0));
7862 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
7863 build_int_cst (ncopies_type, 0), ncopies);
7864 gfc_add_modify (&se->pre, n, tmp);
7865 ncopies = n;
7867 /* Check that ncopies is not too large: ncopies should be less than
7868 (or equal to) MAX / slen, where MAX is the maximal integer of
7869 the gfc_charlen_type_node type. If slen == 0, we need a special
7870 case to avoid the division by zero. */
7871 i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
7872 max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_charlen_int_kind);
7873 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node,
7874 fold_convert (size_type_node, max), slen);
7875 largest = TYPE_PRECISION (size_type_node) > TYPE_PRECISION (ncopies_type)
7876 ? size_type_node : ncopies_type;
7877 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
7878 fold_convert (largest, ncopies),
7879 fold_convert (largest, max));
7880 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
7881 build_int_cst (size_type_node, 0));
7882 cond = fold_build3_loc (input_location, COND_EXPR, logical_type_node, tmp,
7883 logical_false_node, cond);
7884 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
7885 "Argument NCOPIES of REPEAT intrinsic is too large");
7887 /* Compute the destination length. */
7888 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
7889 fold_convert (gfc_charlen_type_node, slen),
7890 fold_convert (gfc_charlen_type_node, ncopies));
7891 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
7892 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
7894 /* Generate the code to do the repeat operation:
7895 for (i = 0; i < ncopies; i++)
7896 memmove (dest + (i * slen * size), src, slen*size); */
7897 gfc_start_block (&block);
7898 count = gfc_create_var (ncopies_type, "count");
7899 gfc_add_modify (&block, count, build_int_cst (ncopies_type, 0));
7900 exit_label = gfc_build_label_decl (NULL_TREE);
7902 /* Start the loop body. */
7903 gfc_start_block (&body);
7905 /* Exit the loop if count >= ncopies. */
7906 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, count,
7907 ncopies);
7908 tmp = build1_v (GOTO_EXPR, exit_label);
7909 TREE_USED (exit_label) = 1;
7910 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
7911 build_empty_stmt (input_location));
7912 gfc_add_expr_to_block (&body, tmp);
7914 /* Call memmove (dest + (i*slen*size), src, slen*size). */
7915 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
7916 fold_convert (gfc_charlen_type_node, slen),
7917 fold_convert (gfc_charlen_type_node, count));
7918 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
7919 tmp, fold_convert (gfc_charlen_type_node, size));
7920 tmp = fold_build_pointer_plus_loc (input_location,
7921 fold_convert (pvoid_type_node, dest), tmp);
7922 tmp = build_call_expr_loc (input_location,
7923 builtin_decl_explicit (BUILT_IN_MEMMOVE),
7924 3, tmp, src,
7925 fold_build2_loc (input_location, MULT_EXPR,
7926 size_type_node, slen,
7927 fold_convert (size_type_node,
7928 size)));
7929 gfc_add_expr_to_block (&body, tmp);
7931 /* Increment count. */
7932 tmp = fold_build2_loc (input_location, PLUS_EXPR, ncopies_type,
7933 count, build_int_cst (TREE_TYPE (count), 1));
7934 gfc_add_modify (&body, count, tmp);
7936 /* Build the loop. */
7937 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
7938 gfc_add_expr_to_block (&block, tmp);
7940 /* Add the exit label. */
7941 tmp = build1_v (LABEL_EXPR, exit_label);
7942 gfc_add_expr_to_block (&block, tmp);
7944 /* Finish the block. */
7945 tmp = gfc_finish_block (&block);
7946 gfc_add_expr_to_block (&se->pre, tmp);
7948 /* Set the result value. */
7949 se->expr = dest;
7950 se->string_length = dlen;
7954 /* Generate code for the IARGC intrinsic. */
7956 static void
7957 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
7959 tree tmp;
7960 tree fndecl;
7961 tree type;
7963 /* Call the library function. This always returns an INTEGER(4). */
7964 fndecl = gfor_fndecl_iargc;
7965 tmp = build_call_expr_loc (input_location,
7966 fndecl, 0);
7968 /* Convert it to the required type. */
7969 type = gfc_typenode_for_spec (&expr->ts);
7970 tmp = fold_convert (type, tmp);
7972 se->expr = tmp;
7976 /* The loc intrinsic returns the address of its argument as
7977 gfc_index_integer_kind integer. */
7979 static void
7980 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
7982 tree temp_var;
7983 gfc_expr *arg_expr;
7985 gcc_assert (!se->ss);
7987 arg_expr = expr->value.function.actual->expr;
7988 if (arg_expr->rank == 0)
7990 if (arg_expr->ts.type == BT_CLASS)
7991 gfc_add_data_component (arg_expr);
7992 gfc_conv_expr_reference (se, arg_expr);
7994 else
7995 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
7996 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
7998 /* Create a temporary variable for loc return value. Without this,
7999 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
8000 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
8001 gfc_add_modify (&se->pre, temp_var, se->expr);
8002 se->expr = temp_var;
8006 /* The following routine generates code for the intrinsic
8007 functions from the ISO_C_BINDING module:
8008 * C_LOC
8009 * C_FUNLOC
8010 * C_ASSOCIATED */
8012 static void
8013 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
8015 gfc_actual_arglist *arg = expr->value.function.actual;
8017 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
8019 if (arg->expr->rank == 0)
8020 gfc_conv_expr_reference (se, arg->expr);
8021 else if (gfc_is_simply_contiguous (arg->expr, false, false))
8022 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
8023 else
8025 gfc_conv_expr_descriptor (se, arg->expr);
8026 se->expr = gfc_conv_descriptor_data_get (se->expr);
8029 /* TODO -- the following two lines shouldn't be necessary, but if
8030 they're removed, a bug is exposed later in the code path.
8031 This workaround was thus introduced, but will have to be
8032 removed; please see PR 35150 for details about the issue. */
8033 se->expr = convert (pvoid_type_node, se->expr);
8034 se->expr = gfc_evaluate_now (se->expr, &se->pre);
8036 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
8037 gfc_conv_expr_reference (se, arg->expr);
8038 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
8040 gfc_se arg1se;
8041 gfc_se arg2se;
8043 /* Build the addr_expr for the first argument. The argument is
8044 already an *address* so we don't need to set want_pointer in
8045 the gfc_se. */
8046 gfc_init_se (&arg1se, NULL);
8047 gfc_conv_expr (&arg1se, arg->expr);
8048 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8049 gfc_add_block_to_block (&se->post, &arg1se.post);
8051 /* See if we were given two arguments. */
8052 if (arg->next->expr == NULL)
8053 /* Only given one arg so generate a null and do a
8054 not-equal comparison against the first arg. */
8055 se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8056 arg1se.expr,
8057 fold_convert (TREE_TYPE (arg1se.expr),
8058 null_pointer_node));
8059 else
8061 tree eq_expr;
8062 tree not_null_expr;
8064 /* Given two arguments so build the arg2se from second arg. */
8065 gfc_init_se (&arg2se, NULL);
8066 gfc_conv_expr (&arg2se, arg->next->expr);
8067 gfc_add_block_to_block (&se->pre, &arg2se.pre);
8068 gfc_add_block_to_block (&se->post, &arg2se.post);
8070 /* Generate test to compare that the two args are equal. */
8071 eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
8072 arg1se.expr, arg2se.expr);
8073 /* Generate test to ensure that the first arg is not null. */
8074 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
8075 logical_type_node,
8076 arg1se.expr, null_pointer_node);
8078 /* Finally, the generated test must check that both arg1 is not
8079 NULL and that it is equal to the second arg. */
8080 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8081 logical_type_node,
8082 not_null_expr, eq_expr);
8085 else
8086 gcc_unreachable ();
8090 /* The following routine generates code for the intrinsic
8091 subroutines from the ISO_C_BINDING module:
8092 * C_F_POINTER
8093 * C_F_PROCPOINTER. */
8095 static tree
8096 conv_isocbinding_subroutine (gfc_code *code)
8098 gfc_se se;
8099 gfc_se cptrse;
8100 gfc_se fptrse;
8101 gfc_se shapese;
8102 gfc_ss *shape_ss;
8103 tree desc, dim, tmp, stride, offset;
8104 stmtblock_t body, block;
8105 gfc_loopinfo loop;
8106 gfc_actual_arglist *arg = code->ext.actual;
8108 gfc_init_se (&se, NULL);
8109 gfc_init_se (&cptrse, NULL);
8110 gfc_conv_expr (&cptrse, arg->expr);
8111 gfc_add_block_to_block (&se.pre, &cptrse.pre);
8112 gfc_add_block_to_block (&se.post, &cptrse.post);
8114 gfc_init_se (&fptrse, NULL);
8115 if (arg->next->expr->rank == 0)
8117 fptrse.want_pointer = 1;
8118 gfc_conv_expr (&fptrse, arg->next->expr);
8119 gfc_add_block_to_block (&se.pre, &fptrse.pre);
8120 gfc_add_block_to_block (&se.post, &fptrse.post);
8121 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
8122 && arg->next->expr->symtree->n.sym->attr.dummy)
8123 fptrse.expr = build_fold_indirect_ref_loc (input_location,
8124 fptrse.expr);
8125 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
8126 TREE_TYPE (fptrse.expr),
8127 fptrse.expr,
8128 fold_convert (TREE_TYPE (fptrse.expr),
8129 cptrse.expr));
8130 gfc_add_expr_to_block (&se.pre, se.expr);
8131 gfc_add_block_to_block (&se.pre, &se.post);
8132 return gfc_finish_block (&se.pre);
8135 gfc_start_block (&block);
8137 /* Get the descriptor of the Fortran pointer. */
8138 fptrse.descriptor_only = 1;
8139 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
8140 gfc_add_block_to_block (&block, &fptrse.pre);
8141 desc = fptrse.expr;
8143 /* Set the span field. */
8144 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
8145 tmp = fold_convert (gfc_array_index_type, tmp);
8146 gfc_conv_descriptor_span_set (&block, desc, tmp);
8148 /* Set data value, dtype, and offset. */
8149 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
8150 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
8151 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
8152 gfc_get_dtype (TREE_TYPE (desc)));
8154 /* Start scalarization of the bounds, using the shape argument. */
8156 shape_ss = gfc_walk_expr (arg->next->next->expr);
8157 gcc_assert (shape_ss != gfc_ss_terminator);
8158 gfc_init_se (&shapese, NULL);
8160 gfc_init_loopinfo (&loop);
8161 gfc_add_ss_to_loop (&loop, shape_ss);
8162 gfc_conv_ss_startstride (&loop);
8163 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
8164 gfc_mark_ss_chain_used (shape_ss, 1);
8166 gfc_copy_loopinfo_to_se (&shapese, &loop);
8167 shapese.ss = shape_ss;
8169 stride = gfc_create_var (gfc_array_index_type, "stride");
8170 offset = gfc_create_var (gfc_array_index_type, "offset");
8171 gfc_add_modify (&block, stride, gfc_index_one_node);
8172 gfc_add_modify (&block, offset, gfc_index_zero_node);
8174 /* Loop body. */
8175 gfc_start_scalarized_body (&loop, &body);
8177 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8178 loop.loopvar[0], loop.from[0]);
8180 /* Set bounds and stride. */
8181 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
8182 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
8184 gfc_conv_expr (&shapese, arg->next->next->expr);
8185 gfc_add_block_to_block (&body, &shapese.pre);
8186 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
8187 gfc_add_block_to_block (&body, &shapese.post);
8189 /* Calculate offset. */
8190 gfc_add_modify (&body, offset,
8191 fold_build2_loc (input_location, PLUS_EXPR,
8192 gfc_array_index_type, offset, stride));
8193 /* Update stride. */
8194 gfc_add_modify (&body, stride,
8195 fold_build2_loc (input_location, MULT_EXPR,
8196 gfc_array_index_type, stride,
8197 fold_convert (gfc_array_index_type,
8198 shapese.expr)));
8199 /* Finish scalarization loop. */
8200 gfc_trans_scalarizing_loops (&loop, &body);
8201 gfc_add_block_to_block (&block, &loop.pre);
8202 gfc_add_block_to_block (&block, &loop.post);
8203 gfc_add_block_to_block (&block, &fptrse.post);
8204 gfc_cleanup_loop (&loop);
8206 gfc_add_modify (&block, offset,
8207 fold_build1_loc (input_location, NEGATE_EXPR,
8208 gfc_array_index_type, offset));
8209 gfc_conv_descriptor_offset_set (&block, desc, offset);
8211 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
8212 gfc_add_block_to_block (&se.pre, &se.post);
8213 return gfc_finish_block (&se.pre);
8217 /* Save and restore floating-point state. */
8219 tree
8220 gfc_save_fp_state (stmtblock_t *block)
8222 tree type, fpstate, tmp;
8224 type = build_array_type (char_type_node,
8225 build_range_type (size_type_node, size_zero_node,
8226 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
8227 fpstate = gfc_create_var (type, "fpstate");
8228 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
8230 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
8231 1, fpstate);
8232 gfc_add_expr_to_block (block, tmp);
8234 return fpstate;
8238 void
8239 gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
8241 tree tmp;
8243 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
8244 1, fpstate);
8245 gfc_add_expr_to_block (block, tmp);
8249 /* Generate code for arguments of IEEE functions. */
8251 static void
8252 conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
8253 int nargs)
8255 gfc_actual_arglist *actual;
8256 gfc_expr *e;
8257 gfc_se argse;
8258 int arg;
8260 actual = expr->value.function.actual;
8261 for (arg = 0; arg < nargs; arg++, actual = actual->next)
8263 gcc_assert (actual);
8264 e = actual->expr;
8266 gfc_init_se (&argse, se);
8267 gfc_conv_expr_val (&argse, e);
8269 gfc_add_block_to_block (&se->pre, &argse.pre);
8270 gfc_add_block_to_block (&se->post, &argse.post);
8271 argarray[arg] = argse.expr;
8276 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
8277 and IEEE_UNORDERED, which translate directly to GCC type-generic
8278 built-ins. */
8280 static void
8281 conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
8282 enum built_in_function code, int nargs)
8284 tree args[2];
8285 gcc_assert ((unsigned) nargs <= sizeof(args)/sizeof(args[0]));
8287 conv_ieee_function_args (se, expr, args, nargs);
8288 se->expr = build_call_expr_loc_array (input_location,
8289 builtin_decl_explicit (code),
8290 nargs, args);
8291 STRIP_TYPE_NOPS (se->expr);
8292 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8296 /* Generate code for IEEE_IS_NORMAL intrinsic:
8297 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
8299 static void
8300 conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
8302 tree arg, isnormal, iszero;
8304 /* Convert arg, evaluate it only once. */
8305 conv_ieee_function_args (se, expr, &arg, 1);
8306 arg = gfc_evaluate_now (arg, &se->pre);
8308 isnormal = build_call_expr_loc (input_location,
8309 builtin_decl_explicit (BUILT_IN_ISNORMAL),
8310 1, arg);
8311 iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
8312 build_real_from_int_cst (TREE_TYPE (arg),
8313 integer_zero_node));
8314 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
8315 logical_type_node, isnormal, iszero);
8316 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8320 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
8321 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
8323 static void
8324 conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
8326 tree arg, signbit, isnan;
8328 /* Convert arg, evaluate it only once. */
8329 conv_ieee_function_args (se, expr, &arg, 1);
8330 arg = gfc_evaluate_now (arg, &se->pre);
8332 isnan = build_call_expr_loc (input_location,
8333 builtin_decl_explicit (BUILT_IN_ISNAN),
8334 1, arg);
8335 STRIP_TYPE_NOPS (isnan);
8337 signbit = build_call_expr_loc (input_location,
8338 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8339 1, arg);
8340 signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8341 signbit, integer_zero_node);
8343 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8344 logical_type_node, signbit,
8345 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
8346 TREE_TYPE(isnan), isnan));
8348 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8352 /* Generate code for IEEE_LOGB and IEEE_RINT. */
8354 static void
8355 conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
8356 enum built_in_function code)
8358 tree arg, decl, call, fpstate;
8359 int argprec;
8361 conv_ieee_function_args (se, expr, &arg, 1);
8362 argprec = TYPE_PRECISION (TREE_TYPE (arg));
8363 decl = builtin_decl_for_precision (code, argprec);
8365 /* Save floating-point state. */
8366 fpstate = gfc_save_fp_state (&se->pre);
8368 /* Make the function call. */
8369 call = build_call_expr_loc (input_location, decl, 1, arg);
8370 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
8372 /* Restore floating-point state. */
8373 gfc_restore_fp_state (&se->post, fpstate);
8377 /* Generate code for IEEE_REM. */
8379 static void
8380 conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
8382 tree args[2], decl, call, fpstate;
8383 int argprec;
8385 conv_ieee_function_args (se, expr, args, 2);
8387 /* If arguments have unequal size, convert them to the larger. */
8388 if (TYPE_PRECISION (TREE_TYPE (args[0]))
8389 > TYPE_PRECISION (TREE_TYPE (args[1])))
8390 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8391 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
8392 > TYPE_PRECISION (TREE_TYPE (args[0])))
8393 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
8395 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8396 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
8398 /* Save floating-point state. */
8399 fpstate = gfc_save_fp_state (&se->pre);
8401 /* Make the function call. */
8402 call = build_call_expr_loc_array (input_location, decl, 2, args);
8403 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8405 /* Restore floating-point state. */
8406 gfc_restore_fp_state (&se->post, fpstate);
8410 /* Generate code for IEEE_NEXT_AFTER. */
8412 static void
8413 conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
8415 tree args[2], decl, call, fpstate;
8416 int argprec;
8418 conv_ieee_function_args (se, expr, args, 2);
8420 /* Result has the characteristics of first argument. */
8421 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8422 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8423 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
8425 /* Save floating-point state. */
8426 fpstate = gfc_save_fp_state (&se->pre);
8428 /* Make the function call. */
8429 call = build_call_expr_loc_array (input_location, decl, 2, args);
8430 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8432 /* Restore floating-point state. */
8433 gfc_restore_fp_state (&se->post, fpstate);
8437 /* Generate code for IEEE_SCALB. */
8439 static void
8440 conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
8442 tree args[2], decl, call, huge, type;
8443 int argprec, n;
8445 conv_ieee_function_args (se, expr, args, 2);
8447 /* Result has the characteristics of first argument. */
8448 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8449 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
8451 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
8453 /* We need to fold the integer into the range of a C int. */
8454 args[1] = gfc_evaluate_now (args[1], &se->pre);
8455 type = TREE_TYPE (args[1]);
8457 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
8458 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
8459 gfc_c_int_kind);
8460 huge = fold_convert (type, huge);
8461 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
8462 huge);
8463 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
8464 fold_build1_loc (input_location, NEGATE_EXPR,
8465 type, huge));
8468 args[1] = fold_convert (integer_type_node, args[1]);
8470 /* Make the function call. */
8471 call = build_call_expr_loc_array (input_location, decl, 2, args);
8472 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8476 /* Generate code for IEEE_COPY_SIGN. */
8478 static void
8479 conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
8481 tree args[2], decl, sign;
8482 int argprec;
8484 conv_ieee_function_args (se, expr, args, 2);
8486 /* Get the sign of the second argument. */
8487 sign = build_call_expr_loc (input_location,
8488 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8489 1, args[1]);
8490 sign = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8491 sign, integer_zero_node);
8493 /* Create a value of one, with the right sign. */
8494 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
8495 sign,
8496 fold_build1_loc (input_location, NEGATE_EXPR,
8497 integer_type_node,
8498 integer_one_node),
8499 integer_one_node);
8500 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
8502 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8503 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
8505 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
8509 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
8510 module. */
8512 bool
8513 gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
8515 const char *name = expr->value.function.name;
8517 #define STARTS_WITH(A,B) (strncmp((A), (B), strlen(B)) == 0)
8519 if (STARTS_WITH (name, "_gfortran_ieee_is_nan"))
8520 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
8521 else if (STARTS_WITH (name, "_gfortran_ieee_is_finite"))
8522 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
8523 else if (STARTS_WITH (name, "_gfortran_ieee_unordered"))
8524 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
8525 else if (STARTS_WITH (name, "_gfortran_ieee_is_normal"))
8526 conv_intrinsic_ieee_is_normal (se, expr);
8527 else if (STARTS_WITH (name, "_gfortran_ieee_is_negative"))
8528 conv_intrinsic_ieee_is_negative (se, expr);
8529 else if (STARTS_WITH (name, "_gfortran_ieee_copy_sign"))
8530 conv_intrinsic_ieee_copy_sign (se, expr);
8531 else if (STARTS_WITH (name, "_gfortran_ieee_scalb"))
8532 conv_intrinsic_ieee_scalb (se, expr);
8533 else if (STARTS_WITH (name, "_gfortran_ieee_next_after"))
8534 conv_intrinsic_ieee_next_after (se, expr);
8535 else if (STARTS_WITH (name, "_gfortran_ieee_rem"))
8536 conv_intrinsic_ieee_rem (se, expr);
8537 else if (STARTS_WITH (name, "_gfortran_ieee_logb"))
8538 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
8539 else if (STARTS_WITH (name, "_gfortran_ieee_rint"))
8540 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
8541 else
8542 /* It is not among the functions we translate directly. We return
8543 false, so a library function call is emitted. */
8544 return false;
8546 #undef STARTS_WITH
8548 return true;
8552 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
8554 static void
8555 gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
8557 tree arg, res, restype;
8559 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8560 arg = fold_convert (size_type_node, arg);
8561 res = build_call_expr_loc (input_location,
8562 builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
8563 restype = gfc_typenode_for_spec (&expr->ts);
8564 se->expr = fold_convert (restype, res);
8568 /* Generate code for an intrinsic function. Some map directly to library
8569 calls, others get special handling. In some cases the name of the function
8570 used depends on the type specifiers. */
8572 void
8573 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
8575 const char *name;
8576 int lib, kind;
8577 tree fndecl;
8579 name = &expr->value.function.name[2];
8581 if (expr->rank > 0)
8583 lib = gfc_is_intrinsic_libcall (expr);
8584 if (lib != 0)
8586 if (lib == 1)
8587 se->ignore_optional = 1;
8589 switch (expr->value.function.isym->id)
8591 case GFC_ISYM_EOSHIFT:
8592 case GFC_ISYM_PACK:
8593 case GFC_ISYM_RESHAPE:
8594 /* For all of those the first argument specifies the type and the
8595 third is optional. */
8596 conv_generic_with_optional_char_arg (se, expr, 1, 3);
8597 break;
8599 default:
8600 gfc_conv_intrinsic_funcall (se, expr);
8601 break;
8604 return;
8608 switch (expr->value.function.isym->id)
8610 case GFC_ISYM_NONE:
8611 gcc_unreachable ();
8613 case GFC_ISYM_REPEAT:
8614 gfc_conv_intrinsic_repeat (se, expr);
8615 break;
8617 case GFC_ISYM_TRIM:
8618 gfc_conv_intrinsic_trim (se, expr);
8619 break;
8621 case GFC_ISYM_SC_KIND:
8622 gfc_conv_intrinsic_sc_kind (se, expr);
8623 break;
8625 case GFC_ISYM_SI_KIND:
8626 gfc_conv_intrinsic_si_kind (se, expr);
8627 break;
8629 case GFC_ISYM_SR_KIND:
8630 gfc_conv_intrinsic_sr_kind (se, expr);
8631 break;
8633 case GFC_ISYM_EXPONENT:
8634 gfc_conv_intrinsic_exponent (se, expr);
8635 break;
8637 case GFC_ISYM_SCAN:
8638 kind = expr->value.function.actual->expr->ts.kind;
8639 if (kind == 1)
8640 fndecl = gfor_fndecl_string_scan;
8641 else if (kind == 4)
8642 fndecl = gfor_fndecl_string_scan_char4;
8643 else
8644 gcc_unreachable ();
8646 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
8647 break;
8649 case GFC_ISYM_VERIFY:
8650 kind = expr->value.function.actual->expr->ts.kind;
8651 if (kind == 1)
8652 fndecl = gfor_fndecl_string_verify;
8653 else if (kind == 4)
8654 fndecl = gfor_fndecl_string_verify_char4;
8655 else
8656 gcc_unreachable ();
8658 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
8659 break;
8661 case GFC_ISYM_ALLOCATED:
8662 gfc_conv_allocated (se, expr);
8663 break;
8665 case GFC_ISYM_ASSOCIATED:
8666 gfc_conv_associated(se, expr);
8667 break;
8669 case GFC_ISYM_SAME_TYPE_AS:
8670 gfc_conv_same_type_as (se, expr);
8671 break;
8673 case GFC_ISYM_ABS:
8674 gfc_conv_intrinsic_abs (se, expr);
8675 break;
8677 case GFC_ISYM_ADJUSTL:
8678 if (expr->ts.kind == 1)
8679 fndecl = gfor_fndecl_adjustl;
8680 else if (expr->ts.kind == 4)
8681 fndecl = gfor_fndecl_adjustl_char4;
8682 else
8683 gcc_unreachable ();
8685 gfc_conv_intrinsic_adjust (se, expr, fndecl);
8686 break;
8688 case GFC_ISYM_ADJUSTR:
8689 if (expr->ts.kind == 1)
8690 fndecl = gfor_fndecl_adjustr;
8691 else if (expr->ts.kind == 4)
8692 fndecl = gfor_fndecl_adjustr_char4;
8693 else
8694 gcc_unreachable ();
8696 gfc_conv_intrinsic_adjust (se, expr, fndecl);
8697 break;
8699 case GFC_ISYM_AIMAG:
8700 gfc_conv_intrinsic_imagpart (se, expr);
8701 break;
8703 case GFC_ISYM_AINT:
8704 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
8705 break;
8707 case GFC_ISYM_ALL:
8708 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
8709 break;
8711 case GFC_ISYM_ANINT:
8712 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
8713 break;
8715 case GFC_ISYM_AND:
8716 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
8717 break;
8719 case GFC_ISYM_ANY:
8720 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
8721 break;
8723 case GFC_ISYM_BTEST:
8724 gfc_conv_intrinsic_btest (se, expr);
8725 break;
8727 case GFC_ISYM_BGE:
8728 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
8729 break;
8731 case GFC_ISYM_BGT:
8732 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
8733 break;
8735 case GFC_ISYM_BLE:
8736 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
8737 break;
8739 case GFC_ISYM_BLT:
8740 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
8741 break;
8743 case GFC_ISYM_C_ASSOCIATED:
8744 case GFC_ISYM_C_FUNLOC:
8745 case GFC_ISYM_C_LOC:
8746 conv_isocbinding_function (se, expr);
8747 break;
8749 case GFC_ISYM_ACHAR:
8750 case GFC_ISYM_CHAR:
8751 gfc_conv_intrinsic_char (se, expr);
8752 break;
8754 case GFC_ISYM_CONVERSION:
8755 case GFC_ISYM_REAL:
8756 case GFC_ISYM_LOGICAL:
8757 case GFC_ISYM_DBLE:
8758 gfc_conv_intrinsic_conversion (se, expr);
8759 break;
8761 /* Integer conversions are handled separately to make sure we get the
8762 correct rounding mode. */
8763 case GFC_ISYM_INT:
8764 case GFC_ISYM_INT2:
8765 case GFC_ISYM_INT8:
8766 case GFC_ISYM_LONG:
8767 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
8768 break;
8770 case GFC_ISYM_NINT:
8771 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
8772 break;
8774 case GFC_ISYM_CEILING:
8775 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
8776 break;
8778 case GFC_ISYM_FLOOR:
8779 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
8780 break;
8782 case GFC_ISYM_MOD:
8783 gfc_conv_intrinsic_mod (se, expr, 0);
8784 break;
8786 case GFC_ISYM_MODULO:
8787 gfc_conv_intrinsic_mod (se, expr, 1);
8788 break;
8790 case GFC_ISYM_CAF_GET:
8791 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
8792 false, NULL);
8793 break;
8795 case GFC_ISYM_CMPLX:
8796 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
8797 break;
8799 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
8800 gfc_conv_intrinsic_iargc (se, expr);
8801 break;
8803 case GFC_ISYM_COMPLEX:
8804 gfc_conv_intrinsic_cmplx (se, expr, 1);
8805 break;
8807 case GFC_ISYM_CONJG:
8808 gfc_conv_intrinsic_conjg (se, expr);
8809 break;
8811 case GFC_ISYM_COUNT:
8812 gfc_conv_intrinsic_count (se, expr);
8813 break;
8815 case GFC_ISYM_CTIME:
8816 gfc_conv_intrinsic_ctime (se, expr);
8817 break;
8819 case GFC_ISYM_DIM:
8820 gfc_conv_intrinsic_dim (se, expr);
8821 break;
8823 case GFC_ISYM_DOT_PRODUCT:
8824 gfc_conv_intrinsic_dot_product (se, expr);
8825 break;
8827 case GFC_ISYM_DPROD:
8828 gfc_conv_intrinsic_dprod (se, expr);
8829 break;
8831 case GFC_ISYM_DSHIFTL:
8832 gfc_conv_intrinsic_dshift (se, expr, true);
8833 break;
8835 case GFC_ISYM_DSHIFTR:
8836 gfc_conv_intrinsic_dshift (se, expr, false);
8837 break;
8839 case GFC_ISYM_FDATE:
8840 gfc_conv_intrinsic_fdate (se, expr);
8841 break;
8843 case GFC_ISYM_FRACTION:
8844 gfc_conv_intrinsic_fraction (se, expr);
8845 break;
8847 case GFC_ISYM_IALL:
8848 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
8849 break;
8851 case GFC_ISYM_IAND:
8852 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
8853 break;
8855 case GFC_ISYM_IANY:
8856 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
8857 break;
8859 case GFC_ISYM_IBCLR:
8860 gfc_conv_intrinsic_singlebitop (se, expr, 0);
8861 break;
8863 case GFC_ISYM_IBITS:
8864 gfc_conv_intrinsic_ibits (se, expr);
8865 break;
8867 case GFC_ISYM_IBSET:
8868 gfc_conv_intrinsic_singlebitop (se, expr, 1);
8869 break;
8871 case GFC_ISYM_IACHAR:
8872 case GFC_ISYM_ICHAR:
8873 /* We assume ASCII character sequence. */
8874 gfc_conv_intrinsic_ichar (se, expr);
8875 break;
8877 case GFC_ISYM_IARGC:
8878 gfc_conv_intrinsic_iargc (se, expr);
8879 break;
8881 case GFC_ISYM_IEOR:
8882 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
8883 break;
8885 case GFC_ISYM_INDEX:
8886 kind = expr->value.function.actual->expr->ts.kind;
8887 if (kind == 1)
8888 fndecl = gfor_fndecl_string_index;
8889 else if (kind == 4)
8890 fndecl = gfor_fndecl_string_index_char4;
8891 else
8892 gcc_unreachable ();
8894 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
8895 break;
8897 case GFC_ISYM_IOR:
8898 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
8899 break;
8901 case GFC_ISYM_IPARITY:
8902 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
8903 break;
8905 case GFC_ISYM_IS_IOSTAT_END:
8906 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
8907 break;
8909 case GFC_ISYM_IS_IOSTAT_EOR:
8910 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
8911 break;
8913 case GFC_ISYM_ISNAN:
8914 gfc_conv_intrinsic_isnan (se, expr);
8915 break;
8917 case GFC_ISYM_LSHIFT:
8918 gfc_conv_intrinsic_shift (se, expr, false, false);
8919 break;
8921 case GFC_ISYM_RSHIFT:
8922 gfc_conv_intrinsic_shift (se, expr, true, true);
8923 break;
8925 case GFC_ISYM_SHIFTA:
8926 gfc_conv_intrinsic_shift (se, expr, true, true);
8927 break;
8929 case GFC_ISYM_SHIFTL:
8930 gfc_conv_intrinsic_shift (se, expr, false, false);
8931 break;
8933 case GFC_ISYM_SHIFTR:
8934 gfc_conv_intrinsic_shift (se, expr, true, false);
8935 break;
8937 case GFC_ISYM_ISHFT:
8938 gfc_conv_intrinsic_ishft (se, expr);
8939 break;
8941 case GFC_ISYM_ISHFTC:
8942 gfc_conv_intrinsic_ishftc (se, expr);
8943 break;
8945 case GFC_ISYM_LEADZ:
8946 gfc_conv_intrinsic_leadz (se, expr);
8947 break;
8949 case GFC_ISYM_TRAILZ:
8950 gfc_conv_intrinsic_trailz (se, expr);
8951 break;
8953 case GFC_ISYM_POPCNT:
8954 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
8955 break;
8957 case GFC_ISYM_POPPAR:
8958 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
8959 break;
8961 case GFC_ISYM_LBOUND:
8962 gfc_conv_intrinsic_bound (se, expr, 0);
8963 break;
8965 case GFC_ISYM_LCOBOUND:
8966 conv_intrinsic_cobound (se, expr);
8967 break;
8969 case GFC_ISYM_TRANSPOSE:
8970 /* The scalarizer has already been set up for reversed dimension access
8971 order ; now we just get the argument value normally. */
8972 gfc_conv_expr (se, expr->value.function.actual->expr);
8973 break;
8975 case GFC_ISYM_LEN:
8976 gfc_conv_intrinsic_len (se, expr);
8977 break;
8979 case GFC_ISYM_LEN_TRIM:
8980 gfc_conv_intrinsic_len_trim (se, expr);
8981 break;
8983 case GFC_ISYM_LGE:
8984 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
8985 break;
8987 case GFC_ISYM_LGT:
8988 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
8989 break;
8991 case GFC_ISYM_LLE:
8992 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
8993 break;
8995 case GFC_ISYM_LLT:
8996 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
8997 break;
8999 case GFC_ISYM_MALLOC:
9000 gfc_conv_intrinsic_malloc (se, expr);
9001 break;
9003 case GFC_ISYM_MASKL:
9004 gfc_conv_intrinsic_mask (se, expr, 1);
9005 break;
9007 case GFC_ISYM_MASKR:
9008 gfc_conv_intrinsic_mask (se, expr, 0);
9009 break;
9011 case GFC_ISYM_MAX:
9012 if (expr->ts.type == BT_CHARACTER)
9013 gfc_conv_intrinsic_minmax_char (se, expr, 1);
9014 else
9015 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
9016 break;
9018 case GFC_ISYM_MAXLOC:
9019 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
9020 break;
9022 case GFC_ISYM_MAXVAL:
9023 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
9024 break;
9026 case GFC_ISYM_MERGE:
9027 gfc_conv_intrinsic_merge (se, expr);
9028 break;
9030 case GFC_ISYM_MERGE_BITS:
9031 gfc_conv_intrinsic_merge_bits (se, expr);
9032 break;
9034 case GFC_ISYM_MIN:
9035 if (expr->ts.type == BT_CHARACTER)
9036 gfc_conv_intrinsic_minmax_char (se, expr, -1);
9037 else
9038 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
9039 break;
9041 case GFC_ISYM_MINLOC:
9042 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
9043 break;
9045 case GFC_ISYM_MINVAL:
9046 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
9047 break;
9049 case GFC_ISYM_NEAREST:
9050 gfc_conv_intrinsic_nearest (se, expr);
9051 break;
9053 case GFC_ISYM_NORM2:
9054 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
9055 break;
9057 case GFC_ISYM_NOT:
9058 gfc_conv_intrinsic_not (se, expr);
9059 break;
9061 case GFC_ISYM_OR:
9062 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9063 break;
9065 case GFC_ISYM_PARITY:
9066 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
9067 break;
9069 case GFC_ISYM_PRESENT:
9070 gfc_conv_intrinsic_present (se, expr);
9071 break;
9073 case GFC_ISYM_PRODUCT:
9074 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
9075 break;
9077 case GFC_ISYM_RANK:
9078 gfc_conv_intrinsic_rank (se, expr);
9079 break;
9081 case GFC_ISYM_RRSPACING:
9082 gfc_conv_intrinsic_rrspacing (se, expr);
9083 break;
9085 case GFC_ISYM_SET_EXPONENT:
9086 gfc_conv_intrinsic_set_exponent (se, expr);
9087 break;
9089 case GFC_ISYM_SCALE:
9090 gfc_conv_intrinsic_scale (se, expr);
9091 break;
9093 case GFC_ISYM_SIGN:
9094 gfc_conv_intrinsic_sign (se, expr);
9095 break;
9097 case GFC_ISYM_SIZE:
9098 gfc_conv_intrinsic_size (se, expr);
9099 break;
9101 case GFC_ISYM_SIZEOF:
9102 case GFC_ISYM_C_SIZEOF:
9103 gfc_conv_intrinsic_sizeof (se, expr);
9104 break;
9106 case GFC_ISYM_STORAGE_SIZE:
9107 gfc_conv_intrinsic_storage_size (se, expr);
9108 break;
9110 case GFC_ISYM_SPACING:
9111 gfc_conv_intrinsic_spacing (se, expr);
9112 break;
9114 case GFC_ISYM_STRIDE:
9115 conv_intrinsic_stride (se, expr);
9116 break;
9118 case GFC_ISYM_SUM:
9119 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
9120 break;
9122 case GFC_ISYM_TRANSFER:
9123 if (se->ss && se->ss->info->useflags)
9124 /* Access the previously obtained result. */
9125 gfc_conv_tmp_array_ref (se);
9126 else
9127 gfc_conv_intrinsic_transfer (se, expr);
9128 break;
9130 case GFC_ISYM_TTYNAM:
9131 gfc_conv_intrinsic_ttynam (se, expr);
9132 break;
9134 case GFC_ISYM_UBOUND:
9135 gfc_conv_intrinsic_bound (se, expr, 1);
9136 break;
9138 case GFC_ISYM_UCOBOUND:
9139 conv_intrinsic_cobound (se, expr);
9140 break;
9142 case GFC_ISYM_XOR:
9143 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9144 break;
9146 case GFC_ISYM_LOC:
9147 gfc_conv_intrinsic_loc (se, expr);
9148 break;
9150 case GFC_ISYM_THIS_IMAGE:
9151 /* For num_images() == 1, handle as LCOBOUND. */
9152 if (expr->value.function.actual->expr
9153 && flag_coarray == GFC_FCOARRAY_SINGLE)
9154 conv_intrinsic_cobound (se, expr);
9155 else
9156 trans_this_image (se, expr);
9157 break;
9159 case GFC_ISYM_IMAGE_INDEX:
9160 trans_image_index (se, expr);
9161 break;
9163 case GFC_ISYM_IMAGE_STATUS:
9164 conv_intrinsic_image_status (se, expr);
9165 break;
9167 case GFC_ISYM_NUM_IMAGES:
9168 trans_num_images (se, expr);
9169 break;
9171 case GFC_ISYM_ACCESS:
9172 case GFC_ISYM_CHDIR:
9173 case GFC_ISYM_CHMOD:
9174 case GFC_ISYM_DTIME:
9175 case GFC_ISYM_ETIME:
9176 case GFC_ISYM_EXTENDS_TYPE_OF:
9177 case GFC_ISYM_FGET:
9178 case GFC_ISYM_FGETC:
9179 case GFC_ISYM_FNUM:
9180 case GFC_ISYM_FPUT:
9181 case GFC_ISYM_FPUTC:
9182 case GFC_ISYM_FSTAT:
9183 case GFC_ISYM_FTELL:
9184 case GFC_ISYM_GETCWD:
9185 case GFC_ISYM_GETGID:
9186 case GFC_ISYM_GETPID:
9187 case GFC_ISYM_GETUID:
9188 case GFC_ISYM_HOSTNM:
9189 case GFC_ISYM_KILL:
9190 case GFC_ISYM_IERRNO:
9191 case GFC_ISYM_IRAND:
9192 case GFC_ISYM_ISATTY:
9193 case GFC_ISYM_JN2:
9194 case GFC_ISYM_LINK:
9195 case GFC_ISYM_LSTAT:
9196 case GFC_ISYM_MATMUL:
9197 case GFC_ISYM_MCLOCK:
9198 case GFC_ISYM_MCLOCK8:
9199 case GFC_ISYM_RAND:
9200 case GFC_ISYM_RENAME:
9201 case GFC_ISYM_SECOND:
9202 case GFC_ISYM_SECNDS:
9203 case GFC_ISYM_SIGNAL:
9204 case GFC_ISYM_STAT:
9205 case GFC_ISYM_SYMLNK:
9206 case GFC_ISYM_SYSTEM:
9207 case GFC_ISYM_TIME:
9208 case GFC_ISYM_TIME8:
9209 case GFC_ISYM_UMASK:
9210 case GFC_ISYM_UNLINK:
9211 case GFC_ISYM_YN2:
9212 gfc_conv_intrinsic_funcall (se, expr);
9213 break;
9215 case GFC_ISYM_EOSHIFT:
9216 case GFC_ISYM_PACK:
9217 case GFC_ISYM_RESHAPE:
9218 /* For those, expr->rank should always be >0 and thus the if above the
9219 switch should have matched. */
9220 gcc_unreachable ();
9221 break;
9223 default:
9224 gfc_conv_intrinsic_lib_function (se, expr);
9225 break;
9230 static gfc_ss *
9231 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
9233 gfc_ss *arg_ss, *tmp_ss;
9234 gfc_actual_arglist *arg;
9236 arg = expr->value.function.actual;
9238 gcc_assert (arg->expr);
9240 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
9241 gcc_assert (arg_ss != gfc_ss_terminator);
9243 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
9245 if (tmp_ss->info->type != GFC_SS_SCALAR
9246 && tmp_ss->info->type != GFC_SS_REFERENCE)
9248 gcc_assert (tmp_ss->dimen == 2);
9250 /* We just invert dimensions. */
9251 std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
9254 /* Stop when tmp_ss points to the last valid element of the chain... */
9255 if (tmp_ss->next == gfc_ss_terminator)
9256 break;
9259 /* ... so that we can attach the rest of the chain to it. */
9260 tmp_ss->next = ss;
9262 return arg_ss;
9266 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
9267 This has the side effect of reversing the nested list, so there is no
9268 need to call gfc_reverse_ss on it (the given list is assumed not to be
9269 reversed yet). */
9271 static gfc_ss *
9272 nest_loop_dimension (gfc_ss *ss, int dim)
9274 int ss_dim, i;
9275 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
9276 gfc_loopinfo *new_loop;
9278 gcc_assert (ss != gfc_ss_terminator);
9280 for (; ss != gfc_ss_terminator; ss = ss->next)
9282 new_ss = gfc_get_ss ();
9283 new_ss->next = prev_ss;
9284 new_ss->parent = ss;
9285 new_ss->info = ss->info;
9286 new_ss->info->refcount++;
9287 if (ss->dimen != 0)
9289 gcc_assert (ss->info->type != GFC_SS_SCALAR
9290 && ss->info->type != GFC_SS_REFERENCE);
9292 new_ss->dimen = 1;
9293 new_ss->dim[0] = ss->dim[dim];
9295 gcc_assert (dim < ss->dimen);
9297 ss_dim = --ss->dimen;
9298 for (i = dim; i < ss_dim; i++)
9299 ss->dim[i] = ss->dim[i + 1];
9301 ss->dim[ss_dim] = 0;
9303 prev_ss = new_ss;
9305 if (ss->nested_ss)
9307 ss->nested_ss->parent = new_ss;
9308 new_ss->nested_ss = ss->nested_ss;
9310 ss->nested_ss = new_ss;
9313 new_loop = gfc_get_loopinfo ();
9314 gfc_init_loopinfo (new_loop);
9316 gcc_assert (prev_ss != NULL);
9317 gcc_assert (prev_ss != gfc_ss_terminator);
9318 gfc_add_ss_to_loop (new_loop, prev_ss);
9319 return new_ss->parent;
9323 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
9324 is to be inlined. */
9326 static gfc_ss *
9327 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
9329 gfc_ss *tmp_ss, *tail, *array_ss;
9330 gfc_actual_arglist *arg1, *arg2, *arg3;
9331 int sum_dim;
9332 bool scalar_mask = false;
9334 /* The rank of the result will be determined later. */
9335 arg1 = expr->value.function.actual;
9336 arg2 = arg1->next;
9337 arg3 = arg2->next;
9338 gcc_assert (arg3 != NULL);
9340 if (expr->rank == 0)
9341 return ss;
9343 tmp_ss = gfc_ss_terminator;
9345 if (arg3->expr)
9347 gfc_ss *mask_ss;
9349 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
9350 if (mask_ss == tmp_ss)
9351 scalar_mask = 1;
9353 tmp_ss = mask_ss;
9356 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
9357 gcc_assert (array_ss != tmp_ss);
9359 /* Odd thing: If the mask is scalar, it is used by the frontend after
9360 the array (to make an if around the nested loop). Thus it shall
9361 be after array_ss once the gfc_ss list is reversed. */
9362 if (scalar_mask)
9363 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
9364 else
9365 tmp_ss = array_ss;
9367 /* "Hide" the dimension on which we will sum in the first arg's scalarization
9368 chain. */
9369 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
9370 tail = nest_loop_dimension (tmp_ss, sum_dim);
9371 tail->next = ss;
9373 return tmp_ss;
9377 static gfc_ss *
9378 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
9381 switch (expr->value.function.isym->id)
9383 case GFC_ISYM_PRODUCT:
9384 case GFC_ISYM_SUM:
9385 return walk_inline_intrinsic_arith (ss, expr);
9387 case GFC_ISYM_TRANSPOSE:
9388 return walk_inline_intrinsic_transpose (ss, expr);
9390 default:
9391 gcc_unreachable ();
9393 gcc_unreachable ();
9397 /* This generates code to execute before entering the scalarization loop.
9398 Currently does nothing. */
9400 void
9401 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
9403 switch (ss->info->expr->value.function.isym->id)
9405 case GFC_ISYM_UBOUND:
9406 case GFC_ISYM_LBOUND:
9407 case GFC_ISYM_UCOBOUND:
9408 case GFC_ISYM_LCOBOUND:
9409 case GFC_ISYM_THIS_IMAGE:
9410 break;
9412 default:
9413 gcc_unreachable ();
9418 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
9419 are expanded into code inside the scalarization loop. */
9421 static gfc_ss *
9422 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
9424 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
9425 gfc_add_class_array_ref (expr->value.function.actual->expr);
9427 /* The two argument version returns a scalar. */
9428 if (expr->value.function.actual->next->expr)
9429 return ss;
9431 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
9435 /* Walk an intrinsic array libcall. */
9437 static gfc_ss *
9438 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
9440 gcc_assert (expr->rank > 0);
9441 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
9445 /* Return whether the function call expression EXPR will be expanded
9446 inline by gfc_conv_intrinsic_function. */
9448 bool
9449 gfc_inline_intrinsic_function_p (gfc_expr *expr)
9451 gfc_actual_arglist *args;
9453 if (!expr->value.function.isym)
9454 return false;
9456 switch (expr->value.function.isym->id)
9458 case GFC_ISYM_PRODUCT:
9459 case GFC_ISYM_SUM:
9460 /* Disable inline expansion if code size matters. */
9461 if (optimize_size)
9462 return false;
9464 args = expr->value.function.actual;
9465 /* We need to be able to subset the SUM argument at compile-time. */
9466 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
9467 return false;
9469 return true;
9471 case GFC_ISYM_TRANSPOSE:
9472 return true;
9474 default:
9475 return false;
9480 /* Returns nonzero if the specified intrinsic function call maps directly to
9481 an external library call. Should only be used for functions that return
9482 arrays. */
9485 gfc_is_intrinsic_libcall (gfc_expr * expr)
9487 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
9488 gcc_assert (expr->rank > 0);
9490 if (gfc_inline_intrinsic_function_p (expr))
9491 return 0;
9493 switch (expr->value.function.isym->id)
9495 case GFC_ISYM_ALL:
9496 case GFC_ISYM_ANY:
9497 case GFC_ISYM_COUNT:
9498 case GFC_ISYM_JN2:
9499 case GFC_ISYM_IANY:
9500 case GFC_ISYM_IALL:
9501 case GFC_ISYM_IPARITY:
9502 case GFC_ISYM_MATMUL:
9503 case GFC_ISYM_MAXLOC:
9504 case GFC_ISYM_MAXVAL:
9505 case GFC_ISYM_MINLOC:
9506 case GFC_ISYM_MINVAL:
9507 case GFC_ISYM_NORM2:
9508 case GFC_ISYM_PARITY:
9509 case GFC_ISYM_PRODUCT:
9510 case GFC_ISYM_SUM:
9511 case GFC_ISYM_SHAPE:
9512 case GFC_ISYM_SPREAD:
9513 case GFC_ISYM_YN2:
9514 /* Ignore absent optional parameters. */
9515 return 1;
9517 case GFC_ISYM_CSHIFT:
9518 case GFC_ISYM_EOSHIFT:
9519 case GFC_ISYM_FAILED_IMAGES:
9520 case GFC_ISYM_STOPPED_IMAGES:
9521 case GFC_ISYM_PACK:
9522 case GFC_ISYM_RESHAPE:
9523 case GFC_ISYM_UNPACK:
9524 /* Pass absent optional parameters. */
9525 return 2;
9527 default:
9528 return 0;
9532 /* Walk an intrinsic function. */
9533 gfc_ss *
9534 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
9535 gfc_intrinsic_sym * isym)
9537 gcc_assert (isym);
9539 if (isym->elemental)
9540 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
9541 NULL, GFC_SS_SCALAR);
9543 if (expr->rank == 0)
9544 return ss;
9546 if (gfc_inline_intrinsic_function_p (expr))
9547 return walk_inline_intrinsic_function (ss, expr);
9549 if (gfc_is_intrinsic_libcall (expr))
9550 return gfc_walk_intrinsic_libfunc (ss, expr);
9552 /* Special cases. */
9553 switch (isym->id)
9555 case GFC_ISYM_LBOUND:
9556 case GFC_ISYM_LCOBOUND:
9557 case GFC_ISYM_UBOUND:
9558 case GFC_ISYM_UCOBOUND:
9559 case GFC_ISYM_THIS_IMAGE:
9560 return gfc_walk_intrinsic_bound (ss, expr);
9562 case GFC_ISYM_TRANSFER:
9563 case GFC_ISYM_CAF_GET:
9564 return gfc_walk_intrinsic_libfunc (ss, expr);
9566 default:
9567 /* This probably meant someone forgot to add an intrinsic to the above
9568 list(s) when they implemented it, or something's gone horribly
9569 wrong. */
9570 gcc_unreachable ();
9575 static tree
9576 conv_co_collective (gfc_code *code)
9578 gfc_se argse;
9579 stmtblock_t block, post_block;
9580 tree fndecl, array, strlen, image_index, stat, errmsg, errmsg_len;
9581 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
9583 gfc_start_block (&block);
9584 gfc_init_block (&post_block);
9586 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
9588 opr_expr = code->ext.actual->next->expr;
9589 image_idx_expr = code->ext.actual->next->next->expr;
9590 stat_expr = code->ext.actual->next->next->next->expr;
9591 errmsg_expr = code->ext.actual->next->next->next->next->expr;
9593 else
9595 opr_expr = NULL;
9596 image_idx_expr = code->ext.actual->next->expr;
9597 stat_expr = code->ext.actual->next->next->expr;
9598 errmsg_expr = code->ext.actual->next->next->next->expr;
9601 /* stat. */
9602 if (stat_expr)
9604 gfc_init_se (&argse, NULL);
9605 gfc_conv_expr (&argse, stat_expr);
9606 gfc_add_block_to_block (&block, &argse.pre);
9607 gfc_add_block_to_block (&post_block, &argse.post);
9608 stat = argse.expr;
9609 if (flag_coarray != GFC_FCOARRAY_SINGLE)
9610 stat = gfc_build_addr_expr (NULL_TREE, stat);
9612 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
9613 stat = NULL_TREE;
9614 else
9615 stat = null_pointer_node;
9617 /* Early exit for GFC_FCOARRAY_SINGLE. */
9618 if (flag_coarray == GFC_FCOARRAY_SINGLE)
9620 if (stat != NULL_TREE)
9621 gfc_add_modify (&block, stat,
9622 fold_convert (TREE_TYPE (stat), integer_zero_node));
9623 return gfc_finish_block (&block);
9626 /* Handle the array. */
9627 gfc_init_se (&argse, NULL);
9628 if (code->ext.actual->expr->rank == 0)
9630 symbol_attribute attr;
9631 gfc_clear_attr (&attr);
9632 gfc_init_se (&argse, NULL);
9633 gfc_conv_expr (&argse, code->ext.actual->expr);
9634 gfc_add_block_to_block (&block, &argse.pre);
9635 gfc_add_block_to_block (&post_block, &argse.post);
9636 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
9637 array = gfc_build_addr_expr (NULL_TREE, array);
9639 else
9641 argse.want_pointer = 1;
9642 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
9643 array = argse.expr;
9645 gfc_add_block_to_block (&block, &argse.pre);
9646 gfc_add_block_to_block (&post_block, &argse.post);
9648 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
9649 strlen = argse.string_length;
9650 else
9651 strlen = integer_zero_node;
9653 /* image_index. */
9654 if (image_idx_expr)
9656 gfc_init_se (&argse, NULL);
9657 gfc_conv_expr (&argse, image_idx_expr);
9658 gfc_add_block_to_block (&block, &argse.pre);
9659 gfc_add_block_to_block (&post_block, &argse.post);
9660 image_index = fold_convert (integer_type_node, argse.expr);
9662 else
9663 image_index = integer_zero_node;
9665 /* errmsg. */
9666 if (errmsg_expr)
9668 gfc_init_se (&argse, NULL);
9669 gfc_conv_expr (&argse, errmsg_expr);
9670 gfc_add_block_to_block (&block, &argse.pre);
9671 gfc_add_block_to_block (&post_block, &argse.post);
9672 errmsg = argse.expr;
9673 errmsg_len = fold_convert (integer_type_node, argse.string_length);
9675 else
9677 errmsg = null_pointer_node;
9678 errmsg_len = integer_zero_node;
9681 /* Generate the function call. */
9682 switch (code->resolved_isym->id)
9684 case GFC_ISYM_CO_BROADCAST:
9685 fndecl = gfor_fndecl_co_broadcast;
9686 break;
9687 case GFC_ISYM_CO_MAX:
9688 fndecl = gfor_fndecl_co_max;
9689 break;
9690 case GFC_ISYM_CO_MIN:
9691 fndecl = gfor_fndecl_co_min;
9692 break;
9693 case GFC_ISYM_CO_REDUCE:
9694 fndecl = gfor_fndecl_co_reduce;
9695 break;
9696 case GFC_ISYM_CO_SUM:
9697 fndecl = gfor_fndecl_co_sum;
9698 break;
9699 default:
9700 gcc_unreachable ();
9703 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
9704 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
9705 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
9706 image_index, stat, errmsg, errmsg_len);
9707 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
9708 fndecl = build_call_expr_loc (input_location, fndecl, 6, array, image_index,
9709 stat, errmsg, strlen, errmsg_len);
9710 else
9712 tree opr, opr_flags;
9714 // FIXME: Handle TS29113's bind(C) strings with descriptor.
9715 int opr_flag_int;
9716 if (gfc_is_proc_ptr_comp (opr_expr))
9718 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
9719 opr_flag_int = sym->attr.dimension
9720 || (sym->ts.type == BT_CHARACTER
9721 && !sym->attr.is_bind_c)
9722 ? GFC_CAF_BYREF : 0;
9723 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
9724 && !sym->attr.is_bind_c
9725 ? GFC_CAF_HIDDENLEN : 0;
9726 opr_flag_int |= sym->formal->sym->attr.value ? GFC_CAF_ARG_VALUE : 0;
9728 else
9730 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
9731 ? GFC_CAF_BYREF : 0;
9732 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
9733 && !opr_expr->symtree->n.sym->attr.is_bind_c
9734 ? GFC_CAF_HIDDENLEN : 0;
9735 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
9736 ? GFC_CAF_ARG_VALUE : 0;
9738 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
9739 gfc_conv_expr (&argse, opr_expr);
9740 opr = argse.expr;
9741 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr, opr_flags,
9742 image_index, stat, errmsg, strlen, errmsg_len);
9745 gfc_add_expr_to_block (&block, fndecl);
9746 gfc_add_block_to_block (&block, &post_block);
9748 return gfc_finish_block (&block);
9752 static tree
9753 conv_intrinsic_atomic_op (gfc_code *code)
9755 gfc_se argse;
9756 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
9757 stmtblock_t block, post_block;
9758 gfc_expr *atom_expr = code->ext.actual->expr;
9759 gfc_expr *stat_expr;
9760 built_in_function fn;
9762 if (atom_expr->expr_type == EXPR_FUNCTION
9763 && atom_expr->value.function.isym
9764 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
9765 atom_expr = atom_expr->value.function.actual->expr;
9767 gfc_start_block (&block);
9768 gfc_init_block (&post_block);
9770 gfc_init_se (&argse, NULL);
9771 argse.want_pointer = 1;
9772 gfc_conv_expr (&argse, atom_expr);
9773 gfc_add_block_to_block (&block, &argse.pre);
9774 gfc_add_block_to_block (&post_block, &argse.post);
9775 atom = argse.expr;
9777 gfc_init_se (&argse, NULL);
9778 if (flag_coarray == GFC_FCOARRAY_LIB
9779 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
9780 argse.want_pointer = 1;
9781 gfc_conv_expr (&argse, code->ext.actual->next->expr);
9782 gfc_add_block_to_block (&block, &argse.pre);
9783 gfc_add_block_to_block (&post_block, &argse.post);
9784 value = argse.expr;
9786 switch (code->resolved_isym->id)
9788 case GFC_ISYM_ATOMIC_ADD:
9789 case GFC_ISYM_ATOMIC_AND:
9790 case GFC_ISYM_ATOMIC_DEF:
9791 case GFC_ISYM_ATOMIC_OR:
9792 case GFC_ISYM_ATOMIC_XOR:
9793 stat_expr = code->ext.actual->next->next->expr;
9794 if (flag_coarray == GFC_FCOARRAY_LIB)
9795 old = null_pointer_node;
9796 break;
9797 default:
9798 gfc_init_se (&argse, NULL);
9799 if (flag_coarray == GFC_FCOARRAY_LIB)
9800 argse.want_pointer = 1;
9801 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
9802 gfc_add_block_to_block (&block, &argse.pre);
9803 gfc_add_block_to_block (&post_block, &argse.post);
9804 old = argse.expr;
9805 stat_expr = code->ext.actual->next->next->next->expr;
9808 /* STAT= */
9809 if (stat_expr != NULL)
9811 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
9812 gfc_init_se (&argse, NULL);
9813 if (flag_coarray == GFC_FCOARRAY_LIB)
9814 argse.want_pointer = 1;
9815 gfc_conv_expr_val (&argse, stat_expr);
9816 gfc_add_block_to_block (&block, &argse.pre);
9817 gfc_add_block_to_block (&post_block, &argse.post);
9818 stat = argse.expr;
9820 else if (flag_coarray == GFC_FCOARRAY_LIB)
9821 stat = null_pointer_node;
9823 if (flag_coarray == GFC_FCOARRAY_LIB)
9825 tree image_index, caf_decl, offset, token;
9826 int op;
9828 switch (code->resolved_isym->id)
9830 case GFC_ISYM_ATOMIC_ADD:
9831 case GFC_ISYM_ATOMIC_FETCH_ADD:
9832 op = (int) GFC_CAF_ATOMIC_ADD;
9833 break;
9834 case GFC_ISYM_ATOMIC_AND:
9835 case GFC_ISYM_ATOMIC_FETCH_AND:
9836 op = (int) GFC_CAF_ATOMIC_AND;
9837 break;
9838 case GFC_ISYM_ATOMIC_OR:
9839 case GFC_ISYM_ATOMIC_FETCH_OR:
9840 op = (int) GFC_CAF_ATOMIC_OR;
9841 break;
9842 case GFC_ISYM_ATOMIC_XOR:
9843 case GFC_ISYM_ATOMIC_FETCH_XOR:
9844 op = (int) GFC_CAF_ATOMIC_XOR;
9845 break;
9846 case GFC_ISYM_ATOMIC_DEF:
9847 op = 0; /* Unused. */
9848 break;
9849 default:
9850 gcc_unreachable ();
9853 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
9854 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
9855 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
9857 if (gfc_is_coindexed (atom_expr))
9858 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
9859 else
9860 image_index = integer_zero_node;
9862 if (!POINTER_TYPE_P (TREE_TYPE (value)))
9864 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
9865 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
9866 value = gfc_build_addr_expr (NULL_TREE, tmp);
9869 gfc_init_se (&argse, NULL);
9870 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
9871 atom_expr);
9873 gfc_add_block_to_block (&block, &argse.pre);
9874 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
9875 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
9876 token, offset, image_index, value, stat,
9877 build_int_cst (integer_type_node,
9878 (int) atom_expr->ts.type),
9879 build_int_cst (integer_type_node,
9880 (int) atom_expr->ts.kind));
9881 else
9882 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
9883 build_int_cst (integer_type_node, op),
9884 token, offset, image_index, value, old, stat,
9885 build_int_cst (integer_type_node,
9886 (int) atom_expr->ts.type),
9887 build_int_cst (integer_type_node,
9888 (int) atom_expr->ts.kind));
9890 gfc_add_expr_to_block (&block, tmp);
9891 gfc_add_block_to_block (&block, &argse.post);
9892 gfc_add_block_to_block (&block, &post_block);
9893 return gfc_finish_block (&block);
9897 switch (code->resolved_isym->id)
9899 case GFC_ISYM_ATOMIC_ADD:
9900 case GFC_ISYM_ATOMIC_FETCH_ADD:
9901 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
9902 break;
9903 case GFC_ISYM_ATOMIC_AND:
9904 case GFC_ISYM_ATOMIC_FETCH_AND:
9905 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
9906 break;
9907 case GFC_ISYM_ATOMIC_DEF:
9908 fn = BUILT_IN_ATOMIC_STORE_N;
9909 break;
9910 case GFC_ISYM_ATOMIC_OR:
9911 case GFC_ISYM_ATOMIC_FETCH_OR:
9912 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
9913 break;
9914 case GFC_ISYM_ATOMIC_XOR:
9915 case GFC_ISYM_ATOMIC_FETCH_XOR:
9916 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
9917 break;
9918 default:
9919 gcc_unreachable ();
9922 tmp = TREE_TYPE (TREE_TYPE (atom));
9923 fn = (built_in_function) ((int) fn
9924 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
9925 + 1);
9926 tmp = builtin_decl_explicit (fn);
9927 tree itype = TREE_TYPE (TREE_TYPE (atom));
9928 tmp = builtin_decl_explicit (fn);
9930 switch (code->resolved_isym->id)
9932 case GFC_ISYM_ATOMIC_ADD:
9933 case GFC_ISYM_ATOMIC_AND:
9934 case GFC_ISYM_ATOMIC_DEF:
9935 case GFC_ISYM_ATOMIC_OR:
9936 case GFC_ISYM_ATOMIC_XOR:
9937 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
9938 fold_convert (itype, value),
9939 build_int_cst (NULL, MEMMODEL_RELAXED));
9940 gfc_add_expr_to_block (&block, tmp);
9941 break;
9942 default:
9943 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
9944 fold_convert (itype, value),
9945 build_int_cst (NULL, MEMMODEL_RELAXED));
9946 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
9947 break;
9950 if (stat != NULL_TREE)
9951 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
9952 gfc_add_block_to_block (&block, &post_block);
9953 return gfc_finish_block (&block);
9957 static tree
9958 conv_intrinsic_atomic_ref (gfc_code *code)
9960 gfc_se argse;
9961 tree tmp, atom, value, stat = NULL_TREE;
9962 stmtblock_t block, post_block;
9963 built_in_function fn;
9964 gfc_expr *atom_expr = code->ext.actual->next->expr;
9966 if (atom_expr->expr_type == EXPR_FUNCTION
9967 && atom_expr->value.function.isym
9968 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
9969 atom_expr = atom_expr->value.function.actual->expr;
9971 gfc_start_block (&block);
9972 gfc_init_block (&post_block);
9973 gfc_init_se (&argse, NULL);
9974 argse.want_pointer = 1;
9975 gfc_conv_expr (&argse, atom_expr);
9976 gfc_add_block_to_block (&block, &argse.pre);
9977 gfc_add_block_to_block (&post_block, &argse.post);
9978 atom = argse.expr;
9980 gfc_init_se (&argse, NULL);
9981 if (flag_coarray == GFC_FCOARRAY_LIB
9982 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
9983 argse.want_pointer = 1;
9984 gfc_conv_expr (&argse, code->ext.actual->expr);
9985 gfc_add_block_to_block (&block, &argse.pre);
9986 gfc_add_block_to_block (&post_block, &argse.post);
9987 value = argse.expr;
9989 /* STAT= */
9990 if (code->ext.actual->next->next->expr != NULL)
9992 gcc_assert (code->ext.actual->next->next->expr->expr_type
9993 == EXPR_VARIABLE);
9994 gfc_init_se (&argse, NULL);
9995 if (flag_coarray == GFC_FCOARRAY_LIB)
9996 argse.want_pointer = 1;
9997 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
9998 gfc_add_block_to_block (&block, &argse.pre);
9999 gfc_add_block_to_block (&post_block, &argse.post);
10000 stat = argse.expr;
10002 else if (flag_coarray == GFC_FCOARRAY_LIB)
10003 stat = null_pointer_node;
10005 if (flag_coarray == GFC_FCOARRAY_LIB)
10007 tree image_index, caf_decl, offset, token;
10008 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
10010 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10011 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10012 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10014 if (gfc_is_coindexed (atom_expr))
10015 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10016 else
10017 image_index = integer_zero_node;
10019 gfc_init_se (&argse, NULL);
10020 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10021 atom_expr);
10022 gfc_add_block_to_block (&block, &argse.pre);
10024 /* Different type, need type conversion. */
10025 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10027 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10028 orig_value = value;
10029 value = gfc_build_addr_expr (NULL_TREE, vardecl);
10032 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
10033 token, offset, image_index, value, stat,
10034 build_int_cst (integer_type_node,
10035 (int) atom_expr->ts.type),
10036 build_int_cst (integer_type_node,
10037 (int) atom_expr->ts.kind));
10038 gfc_add_expr_to_block (&block, tmp);
10039 if (vardecl != NULL_TREE)
10040 gfc_add_modify (&block, orig_value,
10041 fold_convert (TREE_TYPE (orig_value), vardecl));
10042 gfc_add_block_to_block (&block, &argse.post);
10043 gfc_add_block_to_block (&block, &post_block);
10044 return gfc_finish_block (&block);
10047 tmp = TREE_TYPE (TREE_TYPE (atom));
10048 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
10049 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10050 + 1);
10051 tmp = builtin_decl_explicit (fn);
10052 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
10053 build_int_cst (integer_type_node,
10054 MEMMODEL_RELAXED));
10055 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
10057 if (stat != NULL_TREE)
10058 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10059 gfc_add_block_to_block (&block, &post_block);
10060 return gfc_finish_block (&block);
10064 static tree
10065 conv_intrinsic_atomic_cas (gfc_code *code)
10067 gfc_se argse;
10068 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
10069 stmtblock_t block, post_block;
10070 built_in_function fn;
10071 gfc_expr *atom_expr = code->ext.actual->expr;
10073 if (atom_expr->expr_type == EXPR_FUNCTION
10074 && atom_expr->value.function.isym
10075 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10076 atom_expr = atom_expr->value.function.actual->expr;
10078 gfc_init_block (&block);
10079 gfc_init_block (&post_block);
10080 gfc_init_se (&argse, NULL);
10081 argse.want_pointer = 1;
10082 gfc_conv_expr (&argse, atom_expr);
10083 atom = argse.expr;
10085 gfc_init_se (&argse, NULL);
10086 if (flag_coarray == GFC_FCOARRAY_LIB)
10087 argse.want_pointer = 1;
10088 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10089 gfc_add_block_to_block (&block, &argse.pre);
10090 gfc_add_block_to_block (&post_block, &argse.post);
10091 old = argse.expr;
10093 gfc_init_se (&argse, NULL);
10094 if (flag_coarray == GFC_FCOARRAY_LIB)
10095 argse.want_pointer = 1;
10096 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10097 gfc_add_block_to_block (&block, &argse.pre);
10098 gfc_add_block_to_block (&post_block, &argse.post);
10099 comp = argse.expr;
10101 gfc_init_se (&argse, NULL);
10102 if (flag_coarray == GFC_FCOARRAY_LIB
10103 && code->ext.actual->next->next->next->expr->ts.kind
10104 == atom_expr->ts.kind)
10105 argse.want_pointer = 1;
10106 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
10107 gfc_add_block_to_block (&block, &argse.pre);
10108 gfc_add_block_to_block (&post_block, &argse.post);
10109 new_val = argse.expr;
10111 /* STAT= */
10112 if (code->ext.actual->next->next->next->next->expr != NULL)
10114 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
10115 == EXPR_VARIABLE);
10116 gfc_init_se (&argse, NULL);
10117 if (flag_coarray == GFC_FCOARRAY_LIB)
10118 argse.want_pointer = 1;
10119 gfc_conv_expr_val (&argse,
10120 code->ext.actual->next->next->next->next->expr);
10121 gfc_add_block_to_block (&block, &argse.pre);
10122 gfc_add_block_to_block (&post_block, &argse.post);
10123 stat = argse.expr;
10125 else if (flag_coarray == GFC_FCOARRAY_LIB)
10126 stat = null_pointer_node;
10128 if (flag_coarray == GFC_FCOARRAY_LIB)
10130 tree image_index, caf_decl, offset, token;
10132 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10133 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10134 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10136 if (gfc_is_coindexed (atom_expr))
10137 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10138 else
10139 image_index = integer_zero_node;
10141 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
10143 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
10144 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
10145 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
10148 /* Convert a constant to a pointer. */
10149 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
10151 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
10152 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
10153 comp = gfc_build_addr_expr (NULL_TREE, tmp);
10156 gfc_init_se (&argse, NULL);
10157 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10158 atom_expr);
10159 gfc_add_block_to_block (&block, &argse.pre);
10161 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
10162 token, offset, image_index, old, comp, new_val,
10163 stat, build_int_cst (integer_type_node,
10164 (int) atom_expr->ts.type),
10165 build_int_cst (integer_type_node,
10166 (int) atom_expr->ts.kind));
10167 gfc_add_expr_to_block (&block, tmp);
10168 gfc_add_block_to_block (&block, &argse.post);
10169 gfc_add_block_to_block (&block, &post_block);
10170 return gfc_finish_block (&block);
10173 tmp = TREE_TYPE (TREE_TYPE (atom));
10174 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
10175 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10176 + 1);
10177 tmp = builtin_decl_explicit (fn);
10179 gfc_add_modify (&block, old, comp);
10180 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
10181 gfc_build_addr_expr (NULL, old),
10182 fold_convert (TREE_TYPE (old), new_val),
10183 boolean_false_node,
10184 build_int_cst (NULL, MEMMODEL_RELAXED),
10185 build_int_cst (NULL, MEMMODEL_RELAXED));
10186 gfc_add_expr_to_block (&block, tmp);
10188 if (stat != NULL_TREE)
10189 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10190 gfc_add_block_to_block (&block, &post_block);
10191 return gfc_finish_block (&block);
10194 static tree
10195 conv_intrinsic_event_query (gfc_code *code)
10197 gfc_se se, argse;
10198 tree stat = NULL_TREE, stat2 = NULL_TREE;
10199 tree count = NULL_TREE, count2 = NULL_TREE;
10201 gfc_expr *event_expr = code->ext.actual->expr;
10203 if (code->ext.actual->next->next->expr)
10205 gcc_assert (code->ext.actual->next->next->expr->expr_type
10206 == EXPR_VARIABLE);
10207 gfc_init_se (&argse, NULL);
10208 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10209 stat = argse.expr;
10211 else if (flag_coarray == GFC_FCOARRAY_LIB)
10212 stat = null_pointer_node;
10214 if (code->ext.actual->next->expr)
10216 gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
10217 gfc_init_se (&argse, NULL);
10218 gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
10219 count = argse.expr;
10222 gfc_start_block (&se.pre);
10223 if (flag_coarray == GFC_FCOARRAY_LIB)
10225 tree tmp, token, image_index;
10226 tree index = size_zero_node;
10228 if (event_expr->expr_type == EXPR_FUNCTION
10229 && event_expr->value.function.isym
10230 && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10231 event_expr = event_expr->value.function.actual->expr;
10233 tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
10235 if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
10236 || event_expr->symtree->n.sym->ts.u.derived->from_intmod
10237 != INTMOD_ISO_FORTRAN_ENV
10238 || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
10239 != ISOFORTRAN_EVENT_TYPE)
10241 gfc_error ("Sorry, the event component of derived type at %L is not "
10242 "yet supported", &event_expr->where);
10243 return NULL_TREE;
10246 if (gfc_is_coindexed (event_expr))
10248 gfc_error ("The event variable at %L shall not be coindexed",
10249 &event_expr->where);
10250 return NULL_TREE;
10253 image_index = integer_zero_node;
10255 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
10256 event_expr);
10258 /* For arrays, obtain the array index. */
10259 if (gfc_expr_attr (event_expr).dimension)
10261 tree desc, tmp, extent, lbound, ubound;
10262 gfc_array_ref *ar, ar2;
10263 int i;
10265 /* TODO: Extend this, once DT components are supported. */
10266 ar = &event_expr->ref->u.ar;
10267 ar2 = *ar;
10268 memset (ar, '\0', sizeof (*ar));
10269 ar->as = ar2.as;
10270 ar->type = AR_FULL;
10272 gfc_init_se (&argse, NULL);
10273 argse.descriptor_only = 1;
10274 gfc_conv_expr_descriptor (&argse, event_expr);
10275 gfc_add_block_to_block (&se.pre, &argse.pre);
10276 desc = argse.expr;
10277 *ar = ar2;
10279 extent = integer_one_node;
10280 for (i = 0; i < ar->dimen; i++)
10282 gfc_init_se (&argse, NULL);
10283 gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
10284 gfc_add_block_to_block (&argse.pre, &argse.pre);
10285 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
10286 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10287 integer_type_node, argse.expr,
10288 fold_convert(integer_type_node, lbound));
10289 tmp = fold_build2_loc (input_location, MULT_EXPR,
10290 integer_type_node, extent, tmp);
10291 index = fold_build2_loc (input_location, PLUS_EXPR,
10292 integer_type_node, index, tmp);
10293 if (i < ar->dimen - 1)
10295 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
10296 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
10297 tmp = fold_convert (integer_type_node, tmp);
10298 extent = fold_build2_loc (input_location, MULT_EXPR,
10299 integer_type_node, extent, tmp);
10304 if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
10306 count2 = count;
10307 count = gfc_create_var (integer_type_node, "count");
10310 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
10312 stat2 = stat;
10313 stat = gfc_create_var (integer_type_node, "stat");
10316 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
10317 token, index, image_index, count
10318 ? gfc_build_addr_expr (NULL, count) : count,
10319 stat != null_pointer_node
10320 ? gfc_build_addr_expr (NULL, stat) : stat);
10321 gfc_add_expr_to_block (&se.pre, tmp);
10323 if (count2 != NULL_TREE)
10324 gfc_add_modify (&se.pre, count2,
10325 fold_convert (TREE_TYPE (count2), count));
10327 if (stat2 != NULL_TREE)
10328 gfc_add_modify (&se.pre, stat2,
10329 fold_convert (TREE_TYPE (stat2), stat));
10331 return gfc_finish_block (&se.pre);
10334 gfc_init_se (&argse, NULL);
10335 gfc_conv_expr_val (&argse, code->ext.actual->expr);
10336 gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
10338 if (stat != NULL_TREE)
10339 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
10341 return gfc_finish_block (&se.pre);
10344 static tree
10345 conv_intrinsic_move_alloc (gfc_code *code)
10347 stmtblock_t block;
10348 gfc_expr *from_expr, *to_expr;
10349 gfc_expr *to_expr2, *from_expr2 = NULL;
10350 gfc_se from_se, to_se;
10351 tree tmp;
10352 bool coarray;
10354 gfc_start_block (&block);
10356 from_expr = code->ext.actual->expr;
10357 to_expr = code->ext.actual->next->expr;
10359 gfc_init_se (&from_se, NULL);
10360 gfc_init_se (&to_se, NULL);
10362 gcc_assert (from_expr->ts.type != BT_CLASS
10363 || to_expr->ts.type == BT_CLASS);
10364 coarray = gfc_get_corank (from_expr) != 0;
10366 if (from_expr->rank == 0 && !coarray)
10368 if (from_expr->ts.type != BT_CLASS)
10369 from_expr2 = from_expr;
10370 else
10372 from_expr2 = gfc_copy_expr (from_expr);
10373 gfc_add_data_component (from_expr2);
10376 if (to_expr->ts.type != BT_CLASS)
10377 to_expr2 = to_expr;
10378 else
10380 to_expr2 = gfc_copy_expr (to_expr);
10381 gfc_add_data_component (to_expr2);
10384 from_se.want_pointer = 1;
10385 to_se.want_pointer = 1;
10386 gfc_conv_expr (&from_se, from_expr2);
10387 gfc_conv_expr (&to_se, to_expr2);
10388 gfc_add_block_to_block (&block, &from_se.pre);
10389 gfc_add_block_to_block (&block, &to_se.pre);
10391 /* Deallocate "to". */
10392 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10393 true, to_expr, to_expr->ts);
10394 gfc_add_expr_to_block (&block, tmp);
10396 /* Assign (_data) pointers. */
10397 gfc_add_modify_loc (input_location, &block, to_se.expr,
10398 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
10400 /* Set "from" to NULL. */
10401 gfc_add_modify_loc (input_location, &block, from_se.expr,
10402 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
10404 gfc_add_block_to_block (&block, &from_se.post);
10405 gfc_add_block_to_block (&block, &to_se.post);
10407 /* Set _vptr. */
10408 if (to_expr->ts.type == BT_CLASS)
10410 gfc_symbol *vtab;
10412 gfc_free_expr (to_expr2);
10413 gfc_init_se (&to_se, NULL);
10414 to_se.want_pointer = 1;
10415 gfc_add_vptr_component (to_expr);
10416 gfc_conv_expr (&to_se, to_expr);
10418 if (from_expr->ts.type == BT_CLASS)
10420 if (UNLIMITED_POLY (from_expr))
10421 vtab = NULL;
10422 else
10424 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10425 gcc_assert (vtab);
10428 gfc_free_expr (from_expr2);
10429 gfc_init_se (&from_se, NULL);
10430 from_se.want_pointer = 1;
10431 gfc_add_vptr_component (from_expr);
10432 gfc_conv_expr (&from_se, from_expr);
10433 gfc_add_modify_loc (input_location, &block, to_se.expr,
10434 fold_convert (TREE_TYPE (to_se.expr),
10435 from_se.expr));
10437 /* Reset _vptr component to declared type. */
10438 if (vtab == NULL)
10439 /* Unlimited polymorphic. */
10440 gfc_add_modify_loc (input_location, &block, from_se.expr,
10441 fold_convert (TREE_TYPE (from_se.expr),
10442 null_pointer_node));
10443 else
10445 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10446 gfc_add_modify_loc (input_location, &block, from_se.expr,
10447 fold_convert (TREE_TYPE (from_se.expr), tmp));
10450 else
10452 vtab = gfc_find_vtab (&from_expr->ts);
10453 gcc_assert (vtab);
10454 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10455 gfc_add_modify_loc (input_location, &block, to_se.expr,
10456 fold_convert (TREE_TYPE (to_se.expr), tmp));
10460 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
10462 gfc_add_modify_loc (input_location, &block, to_se.string_length,
10463 fold_convert (TREE_TYPE (to_se.string_length),
10464 from_se.string_length));
10465 if (from_expr->ts.deferred)
10466 gfc_add_modify_loc (input_location, &block, from_se.string_length,
10467 build_int_cst (TREE_TYPE (from_se.string_length), 0));
10470 return gfc_finish_block (&block);
10473 /* Update _vptr component. */
10474 if (to_expr->ts.type == BT_CLASS)
10476 gfc_symbol *vtab;
10478 to_se.want_pointer = 1;
10479 to_expr2 = gfc_copy_expr (to_expr);
10480 gfc_add_vptr_component (to_expr2);
10481 gfc_conv_expr (&to_se, to_expr2);
10483 if (from_expr->ts.type == BT_CLASS)
10485 if (UNLIMITED_POLY (from_expr))
10486 vtab = NULL;
10487 else
10489 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10490 gcc_assert (vtab);
10493 from_se.want_pointer = 1;
10494 from_expr2 = gfc_copy_expr (from_expr);
10495 gfc_add_vptr_component (from_expr2);
10496 gfc_conv_expr (&from_se, from_expr2);
10497 gfc_add_modify_loc (input_location, &block, to_se.expr,
10498 fold_convert (TREE_TYPE (to_se.expr),
10499 from_se.expr));
10501 /* Reset _vptr component to declared type. */
10502 if (vtab == NULL)
10503 /* Unlimited polymorphic. */
10504 gfc_add_modify_loc (input_location, &block, from_se.expr,
10505 fold_convert (TREE_TYPE (from_se.expr),
10506 null_pointer_node));
10507 else
10509 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10510 gfc_add_modify_loc (input_location, &block, from_se.expr,
10511 fold_convert (TREE_TYPE (from_se.expr), tmp));
10514 else
10516 vtab = gfc_find_vtab (&from_expr->ts);
10517 gcc_assert (vtab);
10518 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10519 gfc_add_modify_loc (input_location, &block, to_se.expr,
10520 fold_convert (TREE_TYPE (to_se.expr), tmp));
10523 gfc_free_expr (to_expr2);
10524 gfc_init_se (&to_se, NULL);
10526 if (from_expr->ts.type == BT_CLASS)
10528 gfc_free_expr (from_expr2);
10529 gfc_init_se (&from_se, NULL);
10534 /* Deallocate "to". */
10535 if (from_expr->rank == 0)
10537 to_se.want_coarray = 1;
10538 from_se.want_coarray = 1;
10540 gfc_conv_expr_descriptor (&to_se, to_expr);
10541 gfc_conv_expr_descriptor (&from_se, from_expr);
10543 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
10544 is an image control "statement", cf. IR F08/0040 in 12-006A. */
10545 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
10547 tree cond;
10549 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10550 NULL_TREE, NULL_TREE, true, to_expr,
10551 GFC_CAF_COARRAY_DEALLOCATE_ONLY);
10552 gfc_add_expr_to_block (&block, tmp);
10554 tmp = gfc_conv_descriptor_data_get (to_se.expr);
10555 cond = fold_build2_loc (input_location, EQ_EXPR,
10556 logical_type_node, tmp,
10557 fold_convert (TREE_TYPE (tmp),
10558 null_pointer_node));
10559 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
10560 3, null_pointer_node, null_pointer_node,
10561 build_int_cst (integer_type_node, 0));
10563 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
10564 tmp, build_empty_stmt (input_location));
10565 gfc_add_expr_to_block (&block, tmp);
10567 else
10569 if (to_expr->ts.type == BT_DERIVED
10570 && to_expr->ts.u.derived->attr.alloc_comp)
10572 tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
10573 to_se.expr, to_expr->rank);
10574 gfc_add_expr_to_block (&block, tmp);
10577 tmp = gfc_conv_descriptor_data_get (to_se.expr);
10578 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
10579 NULL_TREE, true, to_expr,
10580 GFC_CAF_COARRAY_NOCOARRAY);
10581 gfc_add_expr_to_block (&block, tmp);
10584 /* Move the pointer and update the array descriptor data. */
10585 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
10587 /* Set "from" to NULL. */
10588 tmp = gfc_conv_descriptor_data_get (from_se.expr);
10589 gfc_add_modify_loc (input_location, &block, tmp,
10590 fold_convert (TREE_TYPE (tmp), null_pointer_node));
10593 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
10595 gfc_add_modify_loc (input_location, &block, to_se.string_length,
10596 fold_convert (TREE_TYPE (to_se.string_length),
10597 from_se.string_length));
10598 if (from_expr->ts.deferred)
10599 gfc_add_modify_loc (input_location, &block, from_se.string_length,
10600 build_int_cst (TREE_TYPE (from_se.string_length), 0));
10603 return gfc_finish_block (&block);
10607 tree
10608 gfc_conv_intrinsic_subroutine (gfc_code *code)
10610 tree res;
10612 gcc_assert (code->resolved_isym);
10614 switch (code->resolved_isym->id)
10616 case GFC_ISYM_MOVE_ALLOC:
10617 res = conv_intrinsic_move_alloc (code);
10618 break;
10620 case GFC_ISYM_ATOMIC_CAS:
10621 res = conv_intrinsic_atomic_cas (code);
10622 break;
10624 case GFC_ISYM_ATOMIC_ADD:
10625 case GFC_ISYM_ATOMIC_AND:
10626 case GFC_ISYM_ATOMIC_DEF:
10627 case GFC_ISYM_ATOMIC_OR:
10628 case GFC_ISYM_ATOMIC_XOR:
10629 case GFC_ISYM_ATOMIC_FETCH_ADD:
10630 case GFC_ISYM_ATOMIC_FETCH_AND:
10631 case GFC_ISYM_ATOMIC_FETCH_OR:
10632 case GFC_ISYM_ATOMIC_FETCH_XOR:
10633 res = conv_intrinsic_atomic_op (code);
10634 break;
10636 case GFC_ISYM_ATOMIC_REF:
10637 res = conv_intrinsic_atomic_ref (code);
10638 break;
10640 case GFC_ISYM_EVENT_QUERY:
10641 res = conv_intrinsic_event_query (code);
10642 break;
10644 case GFC_ISYM_C_F_POINTER:
10645 case GFC_ISYM_C_F_PROCPOINTER:
10646 res = conv_isocbinding_subroutine (code);
10647 break;
10649 case GFC_ISYM_CAF_SEND:
10650 res = conv_caf_send (code);
10651 break;
10653 case GFC_ISYM_CO_BROADCAST:
10654 case GFC_ISYM_CO_MIN:
10655 case GFC_ISYM_CO_MAX:
10656 case GFC_ISYM_CO_REDUCE:
10657 case GFC_ISYM_CO_SUM:
10658 res = conv_co_collective (code);
10659 break;
10661 case GFC_ISYM_FREE:
10662 res = conv_intrinsic_free (code);
10663 break;
10665 case GFC_ISYM_SYSTEM_CLOCK:
10666 res = conv_intrinsic_system_clock (code);
10667 break;
10669 default:
10670 res = NULL_TREE;
10671 break;
10674 return res;
10677 #include "gt-fortran-trans-intrinsic.h"