PR c++/82357 - bit-field in template
[official-gcc.git] / gcc / fortran / trans-intrinsic.c
blob532d3ab237d035d2a53675c880a5ed76e1eb1c5e
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 boolean_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, boolean_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, boolean_type_node, arg[0],
499 tmp);
500 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_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, boolean_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 symbol_attribute attr;
1875 gfc_clear_attr (&attr);
1876 gfc_conv_expr (&lhs_se, lhs_expr);
1877 lhs_type = TREE_TYPE (lhs_se.expr);
1878 lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr, attr);
1879 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1881 else if ((lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
1882 && lhs_caf_attr.codimension)
1884 lhs_se.want_pointer = 1;
1885 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1886 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1887 has the wrong type if component references are done. */
1888 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1889 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1890 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1891 gfc_get_dtype_rank_type (
1892 gfc_has_vector_subscript (lhs_expr)
1893 ? gfc_find_array_ref (lhs_expr)->dimen
1894 : lhs_expr->rank,
1895 lhs_type));
1897 else
1899 /* If has_vector, pass descriptor for whole array and the
1900 vector bounds separately. */
1901 gfc_array_ref *ar, ar2;
1902 bool has_vector = false;
1904 if (gfc_is_coindexed (lhs_expr) && gfc_has_vector_subscript (lhs_expr))
1906 has_vector = true;
1907 ar = gfc_find_array_ref (lhs_expr);
1908 ar2 = *ar;
1909 memset (ar, '\0', sizeof (*ar));
1910 ar->as = ar2.as;
1911 ar->type = AR_FULL;
1913 lhs_se.want_pointer = 1;
1914 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1915 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1916 has the wrong type if component references are done. */
1917 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1918 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1919 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1920 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1921 : lhs_expr->rank,
1922 lhs_type));
1923 if (has_vector)
1925 vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
1926 *ar = ar2;
1930 lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
1932 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
1933 temporary and a loop. */
1934 if (!gfc_is_coindexed (lhs_expr)
1935 && (!lhs_caf_attr.codimension
1936 || !(lhs_expr->rank > 0
1937 && (lhs_caf_attr.allocatable || lhs_caf_attr.pointer))))
1939 bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
1940 gcc_assert (gfc_is_coindexed (rhs_expr));
1941 gfc_init_se (&rhs_se, NULL);
1942 if (lhs_expr->rank == 0 && lhs_caf_attr.allocatable)
1944 gfc_se scal_se;
1945 gfc_init_se (&scal_se, NULL);
1946 scal_se.want_pointer = 1;
1947 gfc_conv_expr (&scal_se, lhs_expr);
1948 /* Ensure scalar on lhs is allocated. */
1949 gfc_add_block_to_block (&block, &scal_se.pre);
1951 gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
1952 TYPE_SIZE_UNIT (
1953 gfc_typenode_for_spec (&lhs_expr->ts)),
1954 NULL_TREE);
1955 tmp = fold_build2 (EQ_EXPR, boolean_type_node, scal_se.expr,
1956 null_pointer_node);
1957 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1958 tmp, gfc_finish_block (&scal_se.pre),
1959 build_empty_stmt (input_location));
1960 gfc_add_expr_to_block (&block, tmp);
1962 else
1963 lhs_may_realloc = lhs_may_realloc
1964 && gfc_full_array_ref_p (lhs_expr->ref, NULL);
1965 gfc_add_block_to_block (&block, &lhs_se.pre);
1966 gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
1967 may_require_tmp, lhs_may_realloc,
1968 &rhs_caf_attr);
1969 gfc_add_block_to_block (&block, &rhs_se.pre);
1970 gfc_add_block_to_block (&block, &rhs_se.post);
1971 gfc_add_block_to_block (&block, &lhs_se.post);
1972 return gfc_finish_block (&block);
1975 gfc_add_block_to_block (&block, &lhs_se.pre);
1977 /* Obtain token, offset and image index for the LHS. */
1978 caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
1979 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1980 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1981 image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
1982 tmp = lhs_se.expr;
1983 if (lhs_caf_attr.alloc_comp)
1984 gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL_TREE,
1985 NULL);
1986 else
1987 gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
1988 lhs_expr);
1989 lhs_se.expr = tmp;
1991 /* RHS. */
1992 gfc_init_se (&rhs_se, NULL);
1993 if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
1994 && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
1995 rhs_expr = rhs_expr->value.function.actual->expr;
1996 if (rhs_expr->rank == 0)
1998 symbol_attribute attr;
1999 gfc_clear_attr (&attr);
2000 gfc_conv_expr (&rhs_se, rhs_expr);
2001 rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
2002 rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
2004 else if ((rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2005 && rhs_caf_attr.codimension)
2007 tree tmp2;
2008 rhs_se.want_pointer = 1;
2009 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2010 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2011 has the wrong type if component references are done. */
2012 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2013 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2014 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2015 gfc_get_dtype_rank_type (
2016 gfc_has_vector_subscript (rhs_expr)
2017 ? gfc_find_array_ref (rhs_expr)->dimen
2018 : rhs_expr->rank,
2019 tmp2));
2021 else
2023 /* If has_vector, pass descriptor for whole array and the
2024 vector bounds separately. */
2025 gfc_array_ref *ar, ar2;
2026 bool has_vector = false;
2027 tree tmp2;
2029 if (gfc_is_coindexed (rhs_expr) && gfc_has_vector_subscript (rhs_expr))
2031 has_vector = true;
2032 ar = gfc_find_array_ref (rhs_expr);
2033 ar2 = *ar;
2034 memset (ar, '\0', sizeof (*ar));
2035 ar->as = ar2.as;
2036 ar->type = AR_FULL;
2038 rhs_se.want_pointer = 1;
2039 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2040 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2041 has the wrong type if component references are done. */
2042 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2043 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2044 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2045 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2046 : rhs_expr->rank,
2047 tmp2));
2048 if (has_vector)
2050 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
2051 *ar = ar2;
2055 gfc_add_block_to_block (&block, &rhs_se.pre);
2057 rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
2059 tmp_stat = gfc_find_stat_co (lhs_expr);
2061 if (tmp_stat)
2063 gfc_se stat_se;
2064 gfc_init_se (&stat_se, NULL);
2065 gfc_conv_expr_reference (&stat_se, tmp_stat);
2066 dst_stat = stat_se.expr;
2067 gfc_add_block_to_block (&block, &stat_se.pre);
2068 gfc_add_block_to_block (&block, &stat_se.post);
2071 if (!gfc_is_coindexed (rhs_expr))
2073 if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
2075 tree reference, dst_realloc;
2076 reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2077 dst_realloc = lhs_caf_attr.allocatable ? boolean_true_node
2078 : boolean_false_node;
2079 tmp = build_call_expr_loc (input_location,
2080 gfor_fndecl_caf_send_by_ref,
2081 9, token, image_index, rhs_se.expr,
2082 reference, lhs_kind, rhs_kind,
2083 may_require_tmp, dst_realloc, src_stat);
2085 else
2086 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 10,
2087 token, offset, image_index, lhs_se.expr, vec,
2088 rhs_se.expr, lhs_kind, rhs_kind,
2089 may_require_tmp, src_stat);
2091 else
2093 tree rhs_token, rhs_offset, rhs_image_index;
2095 /* It guarantees memory consistency within the same segment. */
2096 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2097 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2098 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2099 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2100 ASM_VOLATILE_P (tmp) = 1;
2101 gfc_add_expr_to_block (&block, tmp);
2103 caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
2104 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2105 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2106 rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
2107 tmp = rhs_se.expr;
2108 if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2110 tmp_stat = gfc_find_stat_co (lhs_expr);
2112 if (tmp_stat)
2114 gfc_se stat_se;
2115 gfc_init_se (&stat_se, NULL);
2116 gfc_conv_expr_reference (&stat_se, tmp_stat);
2117 src_stat = stat_se.expr;
2118 gfc_add_block_to_block (&block, &stat_se.pre);
2119 gfc_add_block_to_block (&block, &stat_se.post);
2122 gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL, caf_decl,
2123 NULL_TREE, NULL);
2124 tree lhs_reference, rhs_reference;
2125 lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2126 rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
2127 tmp = build_call_expr_loc (input_location,
2128 gfor_fndecl_caf_sendget_by_ref, 11,
2129 token, image_index, lhs_reference,
2130 rhs_token, rhs_image_index, rhs_reference,
2131 lhs_kind, rhs_kind, may_require_tmp,
2132 dst_stat, src_stat);
2134 else
2136 gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
2137 tmp, rhs_expr);
2138 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
2139 14, token, offset, image_index,
2140 lhs_se.expr, vec, rhs_token, rhs_offset,
2141 rhs_image_index, tmp, rhs_vec, lhs_kind,
2142 rhs_kind, may_require_tmp, src_stat);
2145 gfc_add_expr_to_block (&block, tmp);
2146 gfc_add_block_to_block (&block, &lhs_se.post);
2147 gfc_add_block_to_block (&block, &rhs_se.post);
2149 /* It guarantees memory consistency within the same segment. */
2150 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
2151 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2152 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2153 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2154 ASM_VOLATILE_P (tmp) = 1;
2155 gfc_add_expr_to_block (&block, tmp);
2157 return gfc_finish_block (&block);
2161 static void
2162 trans_this_image (gfc_se * se, gfc_expr *expr)
2164 stmtblock_t loop;
2165 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
2166 lbound, ubound, extent, ml;
2167 gfc_se argse;
2168 int rank, corank;
2169 gfc_expr *distance = expr->value.function.actual->next->next->expr;
2171 if (expr->value.function.actual->expr
2172 && !gfc_is_coarray (expr->value.function.actual->expr))
2173 distance = expr->value.function.actual->expr;
2175 /* The case -fcoarray=single is handled elsewhere. */
2176 gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
2178 /* Argument-free version: THIS_IMAGE(). */
2179 if (distance || expr->value.function.actual->expr == NULL)
2181 if (distance)
2183 gfc_init_se (&argse, NULL);
2184 gfc_conv_expr_val (&argse, distance);
2185 gfc_add_block_to_block (&se->pre, &argse.pre);
2186 gfc_add_block_to_block (&se->post, &argse.post);
2187 tmp = fold_convert (integer_type_node, argse.expr);
2189 else
2190 tmp = integer_zero_node;
2191 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2192 tmp);
2193 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2194 tmp);
2195 return;
2198 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2200 type = gfc_get_int_type (gfc_default_integer_kind);
2201 corank = gfc_get_corank (expr->value.function.actual->expr);
2202 rank = expr->value.function.actual->expr->rank;
2204 /* Obtain the descriptor of the COARRAY. */
2205 gfc_init_se (&argse, NULL);
2206 argse.want_coarray = 1;
2207 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2208 gfc_add_block_to_block (&se->pre, &argse.pre);
2209 gfc_add_block_to_block (&se->post, &argse.post);
2210 desc = argse.expr;
2212 if (se->ss)
2214 /* Create an implicit second parameter from the loop variable. */
2215 gcc_assert (!expr->value.function.actual->next->expr);
2216 gcc_assert (corank > 0);
2217 gcc_assert (se->loop->dimen == 1);
2218 gcc_assert (se->ss->info->expr == expr);
2220 dim_arg = se->loop->loopvar[0];
2221 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
2222 gfc_array_index_type, dim_arg,
2223 build_int_cst (TREE_TYPE (dim_arg), 1));
2224 gfc_advance_se_ss_chain (se);
2226 else
2228 /* Use the passed DIM= argument. */
2229 gcc_assert (expr->value.function.actual->next->expr);
2230 gfc_init_se (&argse, NULL);
2231 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
2232 gfc_array_index_type);
2233 gfc_add_block_to_block (&se->pre, &argse.pre);
2234 dim_arg = argse.expr;
2236 if (INTEGER_CST_P (dim_arg))
2238 if (wi::ltu_p (wi::to_wide (dim_arg), 1)
2239 || wi::gtu_p (wi::to_wide (dim_arg),
2240 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2241 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2242 "dimension index", expr->value.function.isym->name,
2243 &expr->where);
2245 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2247 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
2248 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2249 dim_arg,
2250 build_int_cst (TREE_TYPE (dim_arg), 1));
2251 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2252 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2253 dim_arg, tmp);
2254 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2255 boolean_type_node, cond, tmp);
2256 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2257 gfc_msg_fault);
2261 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2262 one always has a dim_arg argument.
2264 m = this_image() - 1
2265 if (corank == 1)
2267 sub(1) = m + lcobound(corank)
2268 return;
2270 i = rank
2271 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2272 for (;;)
2274 extent = gfc_extent(i)
2275 ml = m
2276 m = m/extent
2277 if (i >= min_var)
2278 goto exit_label
2281 exit_label:
2282 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2283 : m + lcobound(corank)
2286 /* this_image () - 1. */
2287 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2288 integer_zero_node);
2289 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
2290 fold_convert (type, tmp), build_int_cst (type, 1));
2291 if (corank == 1)
2293 /* sub(1) = m + lcobound(corank). */
2294 lbound = gfc_conv_descriptor_lbound_get (desc,
2295 build_int_cst (TREE_TYPE (gfc_array_index_type),
2296 corank+rank-1));
2297 lbound = fold_convert (type, lbound);
2298 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2300 se->expr = tmp;
2301 return;
2304 m = gfc_create_var (type, NULL);
2305 ml = gfc_create_var (type, NULL);
2306 loop_var = gfc_create_var (integer_type_node, NULL);
2307 min_var = gfc_create_var (integer_type_node, NULL);
2309 /* m = this_image () - 1. */
2310 gfc_add_modify (&se->pre, m, tmp);
2312 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2313 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2314 fold_convert (integer_type_node, dim_arg),
2315 build_int_cst (integer_type_node, rank - 1));
2316 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
2317 build_int_cst (integer_type_node, rank + corank - 2),
2318 tmp);
2319 gfc_add_modify (&se->pre, min_var, tmp);
2321 /* i = rank. */
2322 tmp = build_int_cst (integer_type_node, rank);
2323 gfc_add_modify (&se->pre, loop_var, tmp);
2325 exit_label = gfc_build_label_decl (NULL_TREE);
2326 TREE_USED (exit_label) = 1;
2328 /* Loop body. */
2329 gfc_init_block (&loop);
2331 /* ml = m. */
2332 gfc_add_modify (&loop, ml, m);
2334 /* extent = ... */
2335 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
2336 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
2337 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2338 extent = fold_convert (type, extent);
2340 /* m = m/extent. */
2341 gfc_add_modify (&loop, m,
2342 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
2343 m, extent));
2345 /* Exit condition: if (i >= min_var) goto exit_label. */
2346 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, loop_var,
2347 min_var);
2348 tmp = build1_v (GOTO_EXPR, exit_label);
2349 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
2350 build_empty_stmt (input_location));
2351 gfc_add_expr_to_block (&loop, tmp);
2353 /* Increment loop variable: i++. */
2354 gfc_add_modify (&loop, loop_var,
2355 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2356 loop_var,
2357 build_int_cst (integer_type_node, 1)));
2359 /* Making the loop... actually loop! */
2360 tmp = gfc_finish_block (&loop);
2361 tmp = build1_v (LOOP_EXPR, tmp);
2362 gfc_add_expr_to_block (&se->pre, tmp);
2364 /* The exit label. */
2365 tmp = build1_v (LABEL_EXPR, exit_label);
2366 gfc_add_expr_to_block (&se->pre, tmp);
2368 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2369 : m + lcobound(corank) */
2371 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, dim_arg,
2372 build_int_cst (TREE_TYPE (dim_arg), corank));
2374 lbound = gfc_conv_descriptor_lbound_get (desc,
2375 fold_build2_loc (input_location, PLUS_EXPR,
2376 gfc_array_index_type, dim_arg,
2377 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
2378 lbound = fold_convert (type, lbound);
2380 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
2381 fold_build2_loc (input_location, MULT_EXPR, type,
2382 m, extent));
2383 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2385 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
2386 fold_build2_loc (input_location, PLUS_EXPR, type,
2387 m, lbound));
2391 /* Convert a call to image_status. */
2393 static void
2394 conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
2396 unsigned int num_args;
2397 tree *args, tmp;
2399 num_args = gfc_intrinsic_argument_list_length (expr);
2400 args = XALLOCAVEC (tree, num_args);
2401 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2402 /* In args[0] the number of the image the status is desired for has to be
2403 given. */
2405 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2407 tree arg;
2408 arg = gfc_evaluate_now (args[0], &se->pre);
2409 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2410 fold_convert (integer_type_node, arg),
2411 integer_one_node);
2412 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2413 tmp, integer_zero_node,
2414 build_int_cst (integer_type_node,
2415 GFC_STAT_STOPPED_IMAGE));
2417 else if (flag_coarray == GFC_FCOARRAY_LIB)
2418 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
2419 args[0], build_int_cst (integer_type_node, -1));
2420 else
2421 gcc_unreachable ();
2423 se->expr = tmp;
2427 static void
2428 trans_image_index (gfc_se * se, gfc_expr *expr)
2430 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
2431 tmp, invalid_bound;
2432 gfc_se argse, subse;
2433 int rank, corank, codim;
2435 type = gfc_get_int_type (gfc_default_integer_kind);
2436 corank = gfc_get_corank (expr->value.function.actual->expr);
2437 rank = expr->value.function.actual->expr->rank;
2439 /* Obtain the descriptor of the COARRAY. */
2440 gfc_init_se (&argse, NULL);
2441 argse.want_coarray = 1;
2442 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2443 gfc_add_block_to_block (&se->pre, &argse.pre);
2444 gfc_add_block_to_block (&se->post, &argse.post);
2445 desc = argse.expr;
2447 /* Obtain a handle to the SUB argument. */
2448 gfc_init_se (&subse, NULL);
2449 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
2450 gfc_add_block_to_block (&se->pre, &subse.pre);
2451 gfc_add_block_to_block (&se->post, &subse.post);
2452 subdesc = build_fold_indirect_ref_loc (input_location,
2453 gfc_conv_descriptor_data_get (subse.expr));
2455 /* Fortran 2008 does not require that the values remain in the cobounds,
2456 thus we need explicitly check this - and return 0 if they are exceeded. */
2458 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2459 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
2460 invalid_bound = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2461 fold_convert (gfc_array_index_type, tmp),
2462 lbound);
2464 for (codim = corank + rank - 2; codim >= rank; codim--)
2466 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2467 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2468 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2469 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2470 fold_convert (gfc_array_index_type, tmp),
2471 lbound);
2472 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2473 boolean_type_node, invalid_bound, cond);
2474 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2475 fold_convert (gfc_array_index_type, tmp),
2476 ubound);
2477 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2478 boolean_type_node, invalid_bound, cond);
2481 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
2483 /* See Fortran 2008, C.10 for the following algorithm. */
2485 /* coindex = sub(corank) - lcobound(n). */
2486 coindex = fold_convert (gfc_array_index_type,
2487 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
2488 NULL));
2489 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2490 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2491 fold_convert (gfc_array_index_type, coindex),
2492 lbound);
2494 for (codim = corank + rank - 2; codim >= rank; codim--)
2496 tree extent, ubound;
2498 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2499 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2500 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2501 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2503 /* coindex *= extent. */
2504 coindex = fold_build2_loc (input_location, MULT_EXPR,
2505 gfc_array_index_type, coindex, extent);
2507 /* coindex += sub(codim). */
2508 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2509 coindex = fold_build2_loc (input_location, PLUS_EXPR,
2510 gfc_array_index_type, coindex,
2511 fold_convert (gfc_array_index_type, tmp));
2513 /* coindex -= lbound(codim). */
2514 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2515 coindex = fold_build2_loc (input_location, MINUS_EXPR,
2516 gfc_array_index_type, coindex, lbound);
2519 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
2520 fold_convert(type, coindex),
2521 build_int_cst (type, 1));
2523 /* Return 0 if "coindex" exceeds num_images(). */
2525 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2526 num_images = build_int_cst (type, 1);
2527 else
2529 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2530 integer_zero_node,
2531 build_int_cst (integer_type_node, -1));
2532 num_images = fold_convert (type, tmp);
2535 tmp = gfc_create_var (type, NULL);
2536 gfc_add_modify (&se->pre, tmp, coindex);
2538 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, tmp,
2539 num_images);
2540 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
2541 cond,
2542 fold_convert (boolean_type_node, invalid_bound));
2543 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
2544 build_int_cst (type, 0), tmp);
2548 static void
2549 trans_num_images (gfc_se * se, gfc_expr *expr)
2551 tree tmp, distance, failed;
2552 gfc_se argse;
2554 if (expr->value.function.actual->expr)
2556 gfc_init_se (&argse, NULL);
2557 gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
2558 gfc_add_block_to_block (&se->pre, &argse.pre);
2559 gfc_add_block_to_block (&se->post, &argse.post);
2560 distance = fold_convert (integer_type_node, argse.expr);
2562 else
2563 distance = integer_zero_node;
2565 if (expr->value.function.actual->next->expr)
2567 gfc_init_se (&argse, NULL);
2568 gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
2569 gfc_add_block_to_block (&se->pre, &argse.pre);
2570 gfc_add_block_to_block (&se->post, &argse.post);
2571 failed = fold_convert (integer_type_node, argse.expr);
2573 else
2574 failed = build_int_cst (integer_type_node, -1);
2576 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2577 distance, failed);
2578 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
2582 static void
2583 gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
2585 gfc_se argse;
2587 gfc_init_se (&argse, NULL);
2588 argse.data_not_needed = 1;
2589 argse.descriptor_only = 1;
2591 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2592 gfc_add_block_to_block (&se->pre, &argse.pre);
2593 gfc_add_block_to_block (&se->post, &argse.post);
2595 se->expr = gfc_conv_descriptor_rank (argse.expr);
2599 /* Evaluate a single upper or lower bound. */
2600 /* TODO: bound intrinsic generates way too much unnecessary code. */
2602 static void
2603 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
2605 gfc_actual_arglist *arg;
2606 gfc_actual_arglist *arg2;
2607 tree desc;
2608 tree type;
2609 tree bound;
2610 tree tmp;
2611 tree cond, cond1, cond3, cond4, size;
2612 tree ubound;
2613 tree lbound;
2614 gfc_se argse;
2615 gfc_array_spec * as;
2616 bool assumed_rank_lb_one;
2618 arg = expr->value.function.actual;
2619 arg2 = arg->next;
2621 if (se->ss)
2623 /* Create an implicit second parameter from the loop variable. */
2624 gcc_assert (!arg2->expr);
2625 gcc_assert (se->loop->dimen == 1);
2626 gcc_assert (se->ss->info->expr == expr);
2627 gfc_advance_se_ss_chain (se);
2628 bound = se->loop->loopvar[0];
2629 bound = fold_build2_loc (input_location, MINUS_EXPR,
2630 gfc_array_index_type, bound,
2631 se->loop->from[0]);
2633 else
2635 /* use the passed argument. */
2636 gcc_assert (arg2->expr);
2637 gfc_init_se (&argse, NULL);
2638 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2639 gfc_add_block_to_block (&se->pre, &argse.pre);
2640 bound = argse.expr;
2641 /* Convert from one based to zero based. */
2642 bound = fold_build2_loc (input_location, MINUS_EXPR,
2643 gfc_array_index_type, bound,
2644 gfc_index_one_node);
2647 /* TODO: don't re-evaluate the descriptor on each iteration. */
2648 /* Get a descriptor for the first parameter. */
2649 gfc_init_se (&argse, NULL);
2650 gfc_conv_expr_descriptor (&argse, arg->expr);
2651 gfc_add_block_to_block (&se->pre, &argse.pre);
2652 gfc_add_block_to_block (&se->post, &argse.post);
2654 desc = argse.expr;
2656 as = gfc_get_full_arrayspec_from_expr (arg->expr);
2658 if (INTEGER_CST_P (bound))
2660 if (((!as || as->type != AS_ASSUMED_RANK)
2661 && wi::geu_p (wi::to_wide (bound),
2662 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
2663 || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS))
2664 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2665 "dimension index", upper ? "UBOUND" : "LBOUND",
2666 &expr->where);
2669 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
2671 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2673 bound = gfc_evaluate_now (bound, &se->pre);
2674 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2675 bound, build_int_cst (TREE_TYPE (bound), 0));
2676 if (as && as->type == AS_ASSUMED_RANK)
2677 tmp = gfc_conv_descriptor_rank (desc);
2678 else
2679 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
2680 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
2681 bound, fold_convert(TREE_TYPE (bound), tmp));
2682 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2683 boolean_type_node, cond, tmp);
2684 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2685 gfc_msg_fault);
2689 /* Take care of the lbound shift for assumed-rank arrays, which are
2690 nonallocatable and nonpointers. Those has a lbound of 1. */
2691 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
2692 && ((arg->expr->ts.type != BT_CLASS
2693 && !arg->expr->symtree->n.sym->attr.allocatable
2694 && !arg->expr->symtree->n.sym->attr.pointer)
2695 || (arg->expr->ts.type == BT_CLASS
2696 && !CLASS_DATA (arg->expr)->attr.allocatable
2697 && !CLASS_DATA (arg->expr)->attr.class_pointer));
2699 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
2700 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
2702 /* 13.14.53: Result value for LBOUND
2704 Case (i): For an array section or for an array expression other than a
2705 whole array or array structure component, LBOUND(ARRAY, DIM)
2706 has the value 1. For a whole array or array structure
2707 component, LBOUND(ARRAY, DIM) has the value:
2708 (a) equal to the lower bound for subscript DIM of ARRAY if
2709 dimension DIM of ARRAY does not have extent zero
2710 or if ARRAY is an assumed-size array of rank DIM,
2711 or (b) 1 otherwise.
2713 13.14.113: Result value for UBOUND
2715 Case (i): For an array section or for an array expression other than a
2716 whole array or array structure component, UBOUND(ARRAY, DIM)
2717 has the value equal to the number of elements in the given
2718 dimension; otherwise, it has a value equal to the upper bound
2719 for subscript DIM of ARRAY if dimension DIM of ARRAY does
2720 not have size zero and has value zero if dimension DIM has
2721 size zero. */
2723 if (!upper && assumed_rank_lb_one)
2724 se->expr = gfc_index_one_node;
2725 else if (as)
2727 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
2729 cond1 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
2730 ubound, lbound);
2731 cond3 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
2732 stride, gfc_index_zero_node);
2733 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2734 boolean_type_node, cond3, cond1);
2735 cond4 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2736 stride, gfc_index_zero_node);
2738 if (upper)
2740 tree cond5;
2741 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2742 boolean_type_node, cond3, cond4);
2743 cond5 = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2744 gfc_index_one_node, lbound);
2745 cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2746 boolean_type_node, cond4, cond5);
2748 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2749 boolean_type_node, cond, cond5);
2751 if (assumed_rank_lb_one)
2753 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2754 gfc_array_index_type, ubound, lbound);
2755 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2756 gfc_array_index_type, tmp, gfc_index_one_node);
2758 else
2759 tmp = ubound;
2761 se->expr = fold_build3_loc (input_location, COND_EXPR,
2762 gfc_array_index_type, cond,
2763 tmp, gfc_index_zero_node);
2765 else
2767 if (as->type == AS_ASSUMED_SIZE)
2768 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2769 bound, build_int_cst (TREE_TYPE (bound),
2770 arg->expr->rank - 1));
2771 else
2772 cond = boolean_false_node;
2774 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2775 boolean_type_node, cond3, cond4);
2776 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2777 boolean_type_node, cond, cond1);
2779 se->expr = fold_build3_loc (input_location, COND_EXPR,
2780 gfc_array_index_type, cond,
2781 lbound, gfc_index_one_node);
2784 else
2786 if (upper)
2788 size = fold_build2_loc (input_location, MINUS_EXPR,
2789 gfc_array_index_type, ubound, lbound);
2790 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
2791 gfc_array_index_type, size,
2792 gfc_index_one_node);
2793 se->expr = fold_build2_loc (input_location, MAX_EXPR,
2794 gfc_array_index_type, se->expr,
2795 gfc_index_zero_node);
2797 else
2798 se->expr = gfc_index_one_node;
2801 type = gfc_typenode_for_spec (&expr->ts);
2802 se->expr = convert (type, se->expr);
2806 static void
2807 conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
2809 gfc_actual_arglist *arg;
2810 gfc_actual_arglist *arg2;
2811 gfc_se argse;
2812 tree bound, resbound, resbound2, desc, cond, tmp;
2813 tree type;
2814 int corank;
2816 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
2817 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
2818 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
2820 arg = expr->value.function.actual;
2821 arg2 = arg->next;
2823 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
2824 corank = gfc_get_corank (arg->expr);
2826 gfc_init_se (&argse, NULL);
2827 argse.want_coarray = 1;
2829 gfc_conv_expr_descriptor (&argse, arg->expr);
2830 gfc_add_block_to_block (&se->pre, &argse.pre);
2831 gfc_add_block_to_block (&se->post, &argse.post);
2832 desc = argse.expr;
2834 if (se->ss)
2836 /* Create an implicit second parameter from the loop variable. */
2837 gcc_assert (!arg2->expr);
2838 gcc_assert (corank > 0);
2839 gcc_assert (se->loop->dimen == 1);
2840 gcc_assert (se->ss->info->expr == expr);
2842 bound = se->loop->loopvar[0];
2843 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2844 bound, gfc_rank_cst[arg->expr->rank]);
2845 gfc_advance_se_ss_chain (se);
2847 else
2849 /* use the passed argument. */
2850 gcc_assert (arg2->expr);
2851 gfc_init_se (&argse, NULL);
2852 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
2853 gfc_add_block_to_block (&se->pre, &argse.pre);
2854 bound = argse.expr;
2856 if (INTEGER_CST_P (bound))
2858 if (wi::ltu_p (wi::to_wide (bound), 1)
2859 || wi::gtu_p (wi::to_wide (bound),
2860 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
2861 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2862 "dimension index", expr->value.function.isym->name,
2863 &expr->where);
2865 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2867 bound = gfc_evaluate_now (bound, &se->pre);
2868 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2869 bound, build_int_cst (TREE_TYPE (bound), 1));
2870 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
2871 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2872 bound, tmp);
2873 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
2874 boolean_type_node, cond, tmp);
2875 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2876 gfc_msg_fault);
2880 /* Subtract 1 to get to zero based and add dimensions. */
2881 switch (arg->expr->rank)
2883 case 0:
2884 bound = fold_build2_loc (input_location, MINUS_EXPR,
2885 gfc_array_index_type, bound,
2886 gfc_index_one_node);
2887 case 1:
2888 break;
2889 default:
2890 bound = fold_build2_loc (input_location, PLUS_EXPR,
2891 gfc_array_index_type, bound,
2892 gfc_rank_cst[arg->expr->rank - 1]);
2896 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
2898 /* Handle UCOBOUND with special handling of the last codimension. */
2899 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
2901 /* Last codimension: For -fcoarray=single just return
2902 the lcobound - otherwise add
2903 ceiling (real (num_images ()) / real (size)) - 1
2904 = (num_images () + size - 1) / size - 1
2905 = (num_images - 1) / size(),
2906 where size is the product of the extent of all but the last
2907 codimension. */
2909 if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
2911 tree cosize;
2913 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
2914 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
2915 2, integer_zero_node,
2916 build_int_cst (integer_type_node, -1));
2917 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2918 gfc_array_index_type,
2919 fold_convert (gfc_array_index_type, tmp),
2920 build_int_cst (gfc_array_index_type, 1));
2921 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
2922 gfc_array_index_type, tmp,
2923 fold_convert (gfc_array_index_type, cosize));
2924 resbound = fold_build2_loc (input_location, PLUS_EXPR,
2925 gfc_array_index_type, resbound, tmp);
2927 else if (flag_coarray != GFC_FCOARRAY_SINGLE)
2929 /* ubound = lbound + num_images() - 1. */
2930 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
2931 2, integer_zero_node,
2932 build_int_cst (integer_type_node, -1));
2933 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2934 gfc_array_index_type,
2935 fold_convert (gfc_array_index_type, tmp),
2936 build_int_cst (gfc_array_index_type, 1));
2937 resbound = fold_build2_loc (input_location, PLUS_EXPR,
2938 gfc_array_index_type, resbound, tmp);
2941 if (corank > 1)
2943 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2944 bound,
2945 build_int_cst (TREE_TYPE (bound),
2946 arg->expr->rank + corank - 1));
2948 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
2949 se->expr = fold_build3_loc (input_location, COND_EXPR,
2950 gfc_array_index_type, cond,
2951 resbound, resbound2);
2953 else
2954 se->expr = resbound;
2956 else
2957 se->expr = resbound;
2959 type = gfc_typenode_for_spec (&expr->ts);
2960 se->expr = convert (type, se->expr);
2964 static void
2965 conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
2967 gfc_actual_arglist *array_arg;
2968 gfc_actual_arglist *dim_arg;
2969 gfc_se argse;
2970 tree desc, tmp;
2972 array_arg = expr->value.function.actual;
2973 dim_arg = array_arg->next;
2975 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
2977 gfc_init_se (&argse, NULL);
2978 gfc_conv_expr_descriptor (&argse, array_arg->expr);
2979 gfc_add_block_to_block (&se->pre, &argse.pre);
2980 gfc_add_block_to_block (&se->post, &argse.post);
2981 desc = argse.expr;
2983 gcc_assert (dim_arg->expr);
2984 gfc_init_se (&argse, NULL);
2985 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
2986 gfc_add_block_to_block (&se->pre, &argse.pre);
2987 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2988 argse.expr, gfc_index_one_node);
2989 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
2993 static void
2994 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
2996 tree arg, cabs;
2998 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3000 switch (expr->value.function.actual->expr->ts.type)
3002 case BT_INTEGER:
3003 case BT_REAL:
3004 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
3005 arg);
3006 break;
3008 case BT_COMPLEX:
3009 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
3010 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
3011 break;
3013 default:
3014 gcc_unreachable ();
3019 /* Create a complex value from one or two real components. */
3021 static void
3022 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
3024 tree real;
3025 tree imag;
3026 tree type;
3027 tree *args;
3028 unsigned int num_args;
3030 num_args = gfc_intrinsic_argument_list_length (expr);
3031 args = XALLOCAVEC (tree, num_args);
3033 type = gfc_typenode_for_spec (&expr->ts);
3034 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3035 real = convert (TREE_TYPE (type), args[0]);
3036 if (both)
3037 imag = convert (TREE_TYPE (type), args[1]);
3038 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
3040 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
3041 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
3042 imag = convert (TREE_TYPE (type), imag);
3044 else
3045 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
3047 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
3051 /* Remainder function MOD(A, P) = A - INT(A / P) * P
3052 MODULO(A, P) = A - FLOOR (A / P) * P
3054 The obvious algorithms above are numerically instable for large
3055 arguments, hence these intrinsics are instead implemented via calls
3056 to the fmod family of functions. It is the responsibility of the
3057 user to ensure that the second argument is non-zero. */
3059 static void
3060 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
3062 tree type;
3063 tree tmp;
3064 tree test;
3065 tree test2;
3066 tree fmod;
3067 tree zero;
3068 tree args[2];
3070 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3072 switch (expr->ts.type)
3074 case BT_INTEGER:
3075 /* Integer case is easy, we've got a builtin op. */
3076 type = TREE_TYPE (args[0]);
3078 if (modulo)
3079 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
3080 args[0], args[1]);
3081 else
3082 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3083 args[0], args[1]);
3084 break;
3086 case BT_REAL:
3087 fmod = NULL_TREE;
3088 /* Check if we have a builtin fmod. */
3089 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
3091 /* The builtin should always be available. */
3092 gcc_assert (fmod != NULL_TREE);
3094 tmp = build_addr (fmod);
3095 se->expr = build_call_array_loc (input_location,
3096 TREE_TYPE (TREE_TYPE (fmod)),
3097 tmp, 2, args);
3098 if (modulo == 0)
3099 return;
3101 type = TREE_TYPE (args[0]);
3103 args[0] = gfc_evaluate_now (args[0], &se->pre);
3104 args[1] = gfc_evaluate_now (args[1], &se->pre);
3106 /* Definition:
3107 modulo = arg - floor (arg/arg2) * arg2
3109 In order to calculate the result accurately, we use the fmod
3110 function as follows.
3112 res = fmod (arg, arg2);
3113 if (res)
3115 if ((arg < 0) xor (arg2 < 0))
3116 res += arg2;
3118 else
3119 res = copysign (0., arg2);
3121 => As two nested ternary exprs:
3123 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3124 : copysign (0., arg2);
3128 zero = gfc_build_const (type, integer_zero_node);
3129 tmp = gfc_evaluate_now (se->expr, &se->pre);
3130 if (!flag_signed_zeros)
3132 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
3133 args[0], zero);
3134 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
3135 args[1], zero);
3136 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3137 boolean_type_node, test, test2);
3138 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
3139 tmp, zero);
3140 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3141 boolean_type_node, test, test2);
3142 test = gfc_evaluate_now (test, &se->pre);
3143 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3144 fold_build2_loc (input_location,
3145 PLUS_EXPR,
3146 type, tmp, args[1]),
3147 tmp);
3149 else
3151 tree expr1, copysign, cscall;
3152 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
3153 expr->ts.kind);
3154 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
3155 args[0], zero);
3156 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
3157 args[1], zero);
3158 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
3159 boolean_type_node, test, test2);
3160 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
3161 fold_build2_loc (input_location,
3162 PLUS_EXPR,
3163 type, tmp, args[1]),
3164 tmp);
3165 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
3166 tmp, zero);
3167 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
3168 args[1]);
3169 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3170 expr1, cscall);
3172 return;
3174 default:
3175 gcc_unreachable ();
3179 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3180 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3181 where the right shifts are logical (i.e. 0's are shifted in).
3182 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3183 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3184 DSHIFTL(I,J,0) = I
3185 DSHIFTL(I,J,BITSIZE) = J
3186 DSHIFTR(I,J,0) = J
3187 DSHIFTR(I,J,BITSIZE) = I. */
3189 static void
3190 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
3192 tree type, utype, stype, arg1, arg2, shift, res, left, right;
3193 tree args[3], cond, tmp;
3194 int bitsize;
3196 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3198 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
3199 type = TREE_TYPE (args[0]);
3200 bitsize = TYPE_PRECISION (type);
3201 utype = unsigned_type_for (type);
3202 stype = TREE_TYPE (args[2]);
3204 arg1 = gfc_evaluate_now (args[0], &se->pre);
3205 arg2 = gfc_evaluate_now (args[1], &se->pre);
3206 shift = gfc_evaluate_now (args[2], &se->pre);
3208 /* The generic case. */
3209 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
3210 build_int_cst (stype, bitsize), shift);
3211 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3212 arg1, dshiftl ? shift : tmp);
3214 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
3215 fold_convert (utype, arg2), dshiftl ? tmp : shift);
3216 right = fold_convert (type, right);
3218 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
3220 /* Special cases. */
3221 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
3222 build_int_cst (stype, 0));
3223 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3224 dshiftl ? arg1 : arg2, res);
3226 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
3227 build_int_cst (stype, bitsize));
3228 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3229 dshiftl ? arg2 : arg1, res);
3231 se->expr = res;
3235 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3237 static void
3238 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
3240 tree val;
3241 tree tmp;
3242 tree type;
3243 tree zero;
3244 tree args[2];
3246 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3247 type = TREE_TYPE (args[0]);
3249 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
3250 val = gfc_evaluate_now (val, &se->pre);
3252 zero = gfc_build_const (type, integer_zero_node);
3253 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, val, zero);
3254 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
3258 /* SIGN(A, B) is absolute value of A times sign of B.
3259 The real value versions use library functions to ensure the correct
3260 handling of negative zero. Integer case implemented as:
3261 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3264 static void
3265 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
3267 tree tmp;
3268 tree type;
3269 tree args[2];
3271 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3272 if (expr->ts.type == BT_REAL)
3274 tree abs;
3276 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
3277 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
3279 /* We explicitly have to ignore the minus sign. We do so by using
3280 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3281 if (!flag_sign_zero
3282 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
3284 tree cond, zero;
3285 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
3286 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
3287 args[1], zero);
3288 se->expr = fold_build3_loc (input_location, COND_EXPR,
3289 TREE_TYPE (args[0]), cond,
3290 build_call_expr_loc (input_location, abs, 1,
3291 args[0]),
3292 build_call_expr_loc (input_location, tmp, 2,
3293 args[0], args[1]));
3295 else
3296 se->expr = build_call_expr_loc (input_location, tmp, 2,
3297 args[0], args[1]);
3298 return;
3301 /* Having excluded floating point types, we know we are now dealing
3302 with signed integer types. */
3303 type = TREE_TYPE (args[0]);
3305 /* Args[0] is used multiple times below. */
3306 args[0] = gfc_evaluate_now (args[0], &se->pre);
3308 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3309 the signs of A and B are the same, and of all ones if they differ. */
3310 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
3311 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
3312 build_int_cst (type, TYPE_PRECISION (type) - 1));
3313 tmp = gfc_evaluate_now (tmp, &se->pre);
3315 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3316 is all ones (i.e. -1). */
3317 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
3318 fold_build2_loc (input_location, PLUS_EXPR,
3319 type, args[0], tmp), tmp);
3323 /* Test for the presence of an optional argument. */
3325 static void
3326 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
3328 gfc_expr *arg;
3330 arg = expr->value.function.actual->expr;
3331 gcc_assert (arg->expr_type == EXPR_VARIABLE);
3332 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
3333 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3337 /* Calculate the double precision product of two single precision values. */
3339 static void
3340 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
3342 tree type;
3343 tree args[2];
3345 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3347 /* Convert the args to double precision before multiplying. */
3348 type = gfc_typenode_for_spec (&expr->ts);
3349 args[0] = convert (type, args[0]);
3350 args[1] = convert (type, args[1]);
3351 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
3352 args[1]);
3356 /* Return a length one character string containing an ascii character. */
3358 static void
3359 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
3361 tree arg[2];
3362 tree var;
3363 tree type;
3364 unsigned int num_args;
3366 num_args = gfc_intrinsic_argument_list_length (expr);
3367 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
3369 type = gfc_get_char_type (expr->ts.kind);
3370 var = gfc_create_var (type, "char");
3372 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
3373 gfc_add_modify (&se->pre, var, arg[0]);
3374 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
3375 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
3379 static void
3380 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
3382 tree var;
3383 tree len;
3384 tree tmp;
3385 tree cond;
3386 tree fndecl;
3387 tree *args;
3388 unsigned int num_args;
3390 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3391 args = XALLOCAVEC (tree, num_args);
3393 var = gfc_create_var (pchar_type_node, "pstr");
3394 len = gfc_create_var (gfc_charlen_type_node, "len");
3396 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3397 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3398 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3400 fndecl = build_addr (gfor_fndecl_ctime);
3401 tmp = build_call_array_loc (input_location,
3402 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
3403 fndecl, num_args, args);
3404 gfc_add_expr_to_block (&se->pre, tmp);
3406 /* Free the temporary afterwards, if necessary. */
3407 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
3408 len, build_int_cst (TREE_TYPE (len), 0));
3409 tmp = gfc_call_free (var);
3410 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3411 gfc_add_expr_to_block (&se->post, tmp);
3413 se->expr = var;
3414 se->string_length = len;
3418 static void
3419 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
3421 tree var;
3422 tree len;
3423 tree tmp;
3424 tree cond;
3425 tree fndecl;
3426 tree *args;
3427 unsigned int num_args;
3429 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3430 args = XALLOCAVEC (tree, num_args);
3432 var = gfc_create_var (pchar_type_node, "pstr");
3433 len = gfc_create_var (gfc_charlen_type_node, "len");
3435 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3436 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3437 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3439 fndecl = build_addr (gfor_fndecl_fdate);
3440 tmp = build_call_array_loc (input_location,
3441 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
3442 fndecl, num_args, args);
3443 gfc_add_expr_to_block (&se->pre, tmp);
3445 /* Free the temporary afterwards, if necessary. */
3446 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
3447 len, build_int_cst (TREE_TYPE (len), 0));
3448 tmp = gfc_call_free (var);
3449 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3450 gfc_add_expr_to_block (&se->post, tmp);
3452 se->expr = var;
3453 se->string_length = len;
3457 /* Generate a direct call to free() for the FREE subroutine. */
3459 static tree
3460 conv_intrinsic_free (gfc_code *code)
3462 stmtblock_t block;
3463 gfc_se argse;
3464 tree arg, call;
3466 gfc_init_se (&argse, NULL);
3467 gfc_conv_expr (&argse, code->ext.actual->expr);
3468 arg = fold_convert (ptr_type_node, argse.expr);
3470 gfc_init_block (&block);
3471 call = build_call_expr_loc (input_location,
3472 builtin_decl_explicit (BUILT_IN_FREE), 1, arg);
3473 gfc_add_expr_to_block (&block, call);
3474 return gfc_finish_block (&block);
3478 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3479 conversions. */
3481 static tree
3482 conv_intrinsic_system_clock (gfc_code *code)
3484 stmtblock_t block;
3485 gfc_se count_se, count_rate_se, count_max_se;
3486 tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
3487 tree tmp;
3488 int least;
3490 gfc_expr *count = code->ext.actual->expr;
3491 gfc_expr *count_rate = code->ext.actual->next->expr;
3492 gfc_expr *count_max = code->ext.actual->next->next->expr;
3494 /* Evaluate our arguments. */
3495 if (count)
3497 gfc_init_se (&count_se, NULL);
3498 gfc_conv_expr (&count_se, count);
3501 if (count_rate)
3503 gfc_init_se (&count_rate_se, NULL);
3504 gfc_conv_expr (&count_rate_se, count_rate);
3507 if (count_max)
3509 gfc_init_se (&count_max_se, NULL);
3510 gfc_conv_expr (&count_max_se, count_max);
3513 /* Find the smallest kind found of the arguments. */
3514 least = 16;
3515 least = (count && count->ts.kind < least) ? count->ts.kind : least;
3516 least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
3517 : least;
3518 least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
3519 : least;
3521 /* Prepare temporary variables. */
3523 if (count)
3525 if (least >= 8)
3526 arg1 = gfc_create_var (gfc_get_int_type (8), "count");
3527 else if (least == 4)
3528 arg1 = gfc_create_var (gfc_get_int_type (4), "count");
3529 else if (count->ts.kind == 1)
3530 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
3531 count->ts.kind);
3532 else
3533 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
3534 count->ts.kind);
3537 if (count_rate)
3539 if (least >= 8)
3540 arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
3541 else if (least == 4)
3542 arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
3543 else
3544 arg2 = integer_zero_node;
3547 if (count_max)
3549 if (least >= 8)
3550 arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
3551 else if (least == 4)
3552 arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
3553 else
3554 arg3 = integer_zero_node;
3557 /* Make the function call. */
3558 gfc_init_block (&block);
3560 if (least <= 2)
3562 if (least == 1)
3564 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3565 : null_pointer_node;
3566 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3567 : null_pointer_node;
3568 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3569 : null_pointer_node;
3572 if (least == 2)
3574 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3575 : null_pointer_node;
3576 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3577 : null_pointer_node;
3578 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3579 : null_pointer_node;
3582 else
3584 if (least == 4)
3586 tmp = build_call_expr_loc (input_location,
3587 gfor_fndecl_system_clock4, 3,
3588 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3589 : null_pointer_node,
3590 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3591 : null_pointer_node,
3592 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3593 : null_pointer_node);
3594 gfc_add_expr_to_block (&block, tmp);
3596 /* Handle kind>=8, 10, or 16 arguments */
3597 if (least >= 8)
3599 tmp = build_call_expr_loc (input_location,
3600 gfor_fndecl_system_clock8, 3,
3601 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3602 : null_pointer_node,
3603 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3604 : null_pointer_node,
3605 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3606 : null_pointer_node);
3607 gfc_add_expr_to_block (&block, tmp);
3611 /* And store values back if needed. */
3612 if (arg1 && arg1 != count_se.expr)
3613 gfc_add_modify (&block, count_se.expr,
3614 fold_convert (TREE_TYPE (count_se.expr), arg1));
3615 if (arg2 && arg2 != count_rate_se.expr)
3616 gfc_add_modify (&block, count_rate_se.expr,
3617 fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
3618 if (arg3 && arg3 != count_max_se.expr)
3619 gfc_add_modify (&block, count_max_se.expr,
3620 fold_convert (TREE_TYPE (count_max_se.expr), arg3));
3622 return gfc_finish_block (&block);
3626 /* Return a character string containing the tty name. */
3628 static void
3629 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
3631 tree var;
3632 tree len;
3633 tree tmp;
3634 tree cond;
3635 tree fndecl;
3636 tree *args;
3637 unsigned int num_args;
3639 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3640 args = XALLOCAVEC (tree, num_args);
3642 var = gfc_create_var (pchar_type_node, "pstr");
3643 len = gfc_create_var (gfc_charlen_type_node, "len");
3645 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3646 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3647 args[1] = gfc_build_addr_expr (NULL_TREE, len);
3649 fndecl = build_addr (gfor_fndecl_ttynam);
3650 tmp = build_call_array_loc (input_location,
3651 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
3652 fndecl, num_args, args);
3653 gfc_add_expr_to_block (&se->pre, tmp);
3655 /* Free the temporary afterwards, if necessary. */
3656 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
3657 len, build_int_cst (TREE_TYPE (len), 0));
3658 tmp = gfc_call_free (var);
3659 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3660 gfc_add_expr_to_block (&se->post, tmp);
3662 se->expr = var;
3663 se->string_length = len;
3667 /* Get the minimum/maximum value of all the parameters.
3668 minmax (a1, a2, a3, ...)
3670 mvar = a1;
3671 if (a2 .op. mvar || isnan (mvar))
3672 mvar = a2;
3673 if (a3 .op. mvar || isnan (mvar))
3674 mvar = a3;
3676 return mvar
3680 /* TODO: Mismatching types can occur when specific names are used.
3681 These should be handled during resolution. */
3682 static void
3683 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
3685 tree tmp;
3686 tree mvar;
3687 tree val;
3688 tree thencase;
3689 tree *args;
3690 tree type;
3691 gfc_actual_arglist *argexpr;
3692 unsigned int i, nargs;
3694 nargs = gfc_intrinsic_argument_list_length (expr);
3695 args = XALLOCAVEC (tree, nargs);
3697 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
3698 type = gfc_typenode_for_spec (&expr->ts);
3700 argexpr = expr->value.function.actual;
3701 if (TREE_TYPE (args[0]) != type)
3702 args[0] = convert (type, args[0]);
3703 /* Only evaluate the argument once. */
3704 if (!VAR_P (args[0]) && !TREE_CONSTANT (args[0]))
3705 args[0] = gfc_evaluate_now (args[0], &se->pre);
3707 mvar = gfc_create_var (type, "M");
3708 gfc_add_modify (&se->pre, mvar, args[0]);
3709 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
3711 tree cond, isnan;
3713 val = args[i];
3715 /* Handle absent optional arguments by ignoring the comparison. */
3716 if (argexpr->expr->expr_type == EXPR_VARIABLE
3717 && argexpr->expr->symtree->n.sym->attr.optional
3718 && TREE_CODE (val) == INDIRECT_REF)
3719 cond = fold_build2_loc (input_location,
3720 NE_EXPR, boolean_type_node,
3721 TREE_OPERAND (val, 0),
3722 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
3723 else
3725 cond = NULL_TREE;
3727 /* Only evaluate the argument once. */
3728 if (!VAR_P (val) && !TREE_CONSTANT (val))
3729 val = gfc_evaluate_now (val, &se->pre);
3732 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
3734 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3735 convert (type, val), mvar);
3737 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
3738 __builtin_isnan might be made dependent on that module being loaded,
3739 to help performance of programs that don't rely on IEEE semantics. */
3740 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
3742 isnan = build_call_expr_loc (input_location,
3743 builtin_decl_explicit (BUILT_IN_ISNAN),
3744 1, mvar);
3745 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3746 boolean_type_node, tmp,
3747 fold_convert (boolean_type_node, isnan));
3749 tmp = build3_v (COND_EXPR, tmp, thencase,
3750 build_empty_stmt (input_location));
3752 if (cond != NULL_TREE)
3753 tmp = build3_v (COND_EXPR, cond, tmp,
3754 build_empty_stmt (input_location));
3756 gfc_add_expr_to_block (&se->pre, tmp);
3757 argexpr = argexpr->next;
3759 se->expr = mvar;
3763 /* Generate library calls for MIN and MAX intrinsics for character
3764 variables. */
3765 static void
3766 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
3768 tree *args;
3769 tree var, len, fndecl, tmp, cond, function;
3770 unsigned int nargs;
3772 nargs = gfc_intrinsic_argument_list_length (expr);
3773 args = XALLOCAVEC (tree, nargs + 4);
3774 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
3776 /* Create the result variables. */
3777 len = gfc_create_var (gfc_charlen_type_node, "len");
3778 args[0] = gfc_build_addr_expr (NULL_TREE, len);
3779 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
3780 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
3781 args[2] = build_int_cst (integer_type_node, op);
3782 args[3] = build_int_cst (integer_type_node, nargs / 2);
3784 if (expr->ts.kind == 1)
3785 function = gfor_fndecl_string_minmax;
3786 else if (expr->ts.kind == 4)
3787 function = gfor_fndecl_string_minmax_char4;
3788 else
3789 gcc_unreachable ();
3791 /* Make the function call. */
3792 fndecl = build_addr (function);
3793 tmp = build_call_array_loc (input_location,
3794 TREE_TYPE (TREE_TYPE (function)), fndecl,
3795 nargs + 4, args);
3796 gfc_add_expr_to_block (&se->pre, tmp);
3798 /* Free the temporary afterwards, if necessary. */
3799 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
3800 len, build_int_cst (TREE_TYPE (len), 0));
3801 tmp = gfc_call_free (var);
3802 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3803 gfc_add_expr_to_block (&se->post, tmp);
3805 se->expr = var;
3806 se->string_length = len;
3810 /* Create a symbol node for this intrinsic. The symbol from the frontend
3811 has the generic name. */
3813 static gfc_symbol *
3814 gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
3816 gfc_symbol *sym;
3818 /* TODO: Add symbols for intrinsic function to the global namespace. */
3819 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
3820 sym = gfc_new_symbol (expr->value.function.name, NULL);
3822 sym->ts = expr->ts;
3823 sym->attr.external = 1;
3824 sym->attr.function = 1;
3825 sym->attr.always_explicit = 1;
3826 sym->attr.proc = PROC_INTRINSIC;
3827 sym->attr.flavor = FL_PROCEDURE;
3828 sym->result = sym;
3829 if (expr->rank > 0)
3831 sym->attr.dimension = 1;
3832 sym->as = gfc_get_array_spec ();
3833 sym->as->type = AS_ASSUMED_SHAPE;
3834 sym->as->rank = expr->rank;
3837 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
3838 ignore_optional ? expr->value.function.actual
3839 : NULL);
3841 return sym;
3844 /* Generate a call to an external intrinsic function. */
3845 static void
3846 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
3848 gfc_symbol *sym;
3849 vec<tree, va_gc> *append_args;
3851 gcc_assert (!se->ss || se->ss->info->expr == expr);
3853 if (se->ss)
3854 gcc_assert (expr->rank > 0);
3855 else
3856 gcc_assert (expr->rank == 0);
3858 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
3860 /* Calls to libgfortran_matmul need to be appended special arguments,
3861 to be able to call the BLAS ?gemm functions if required and possible. */
3862 append_args = NULL;
3863 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
3864 && sym->ts.type != BT_LOGICAL)
3866 tree cint = gfc_get_int_type (gfc_c_int_kind);
3868 if (flag_external_blas
3869 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
3870 && (sym->ts.kind == 4 || sym->ts.kind == 8))
3872 tree gemm_fndecl;
3874 if (sym->ts.type == BT_REAL)
3876 if (sym->ts.kind == 4)
3877 gemm_fndecl = gfor_fndecl_sgemm;
3878 else
3879 gemm_fndecl = gfor_fndecl_dgemm;
3881 else
3883 if (sym->ts.kind == 4)
3884 gemm_fndecl = gfor_fndecl_cgemm;
3885 else
3886 gemm_fndecl = gfor_fndecl_zgemm;
3889 vec_alloc (append_args, 3);
3890 append_args->quick_push (build_int_cst (cint, 1));
3891 append_args->quick_push (build_int_cst (cint,
3892 flag_blas_matmul_limit));
3893 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
3894 gemm_fndecl));
3896 else
3898 vec_alloc (append_args, 3);
3899 append_args->quick_push (build_int_cst (cint, 0));
3900 append_args->quick_push (build_int_cst (cint, 0));
3901 append_args->quick_push (null_pointer_node);
3905 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
3906 append_args);
3907 gfc_free_symbol (sym);
3910 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
3911 Implemented as
3912 any(a)
3914 forall (i=...)
3915 if (a[i] != 0)
3916 return 1
3917 end forall
3918 return 0
3920 all(a)
3922 forall (i=...)
3923 if (a[i] == 0)
3924 return 0
3925 end forall
3926 return 1
3929 static void
3930 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
3932 tree resvar;
3933 stmtblock_t block;
3934 stmtblock_t body;
3935 tree type;
3936 tree tmp;
3937 tree found;
3938 gfc_loopinfo loop;
3939 gfc_actual_arglist *actual;
3940 gfc_ss *arrayss;
3941 gfc_se arrayse;
3942 tree exit_label;
3944 if (se->ss)
3946 gfc_conv_intrinsic_funcall (se, expr);
3947 return;
3950 actual = expr->value.function.actual;
3951 type = gfc_typenode_for_spec (&expr->ts);
3952 /* Initialize the result. */
3953 resvar = gfc_create_var (type, "test");
3954 if (op == EQ_EXPR)
3955 tmp = convert (type, boolean_true_node);
3956 else
3957 tmp = convert (type, boolean_false_node);
3958 gfc_add_modify (&se->pre, resvar, tmp);
3960 /* Walk the arguments. */
3961 arrayss = gfc_walk_expr (actual->expr);
3962 gcc_assert (arrayss != gfc_ss_terminator);
3964 /* Initialize the scalarizer. */
3965 gfc_init_loopinfo (&loop);
3966 exit_label = gfc_build_label_decl (NULL_TREE);
3967 TREE_USED (exit_label) = 1;
3968 gfc_add_ss_to_loop (&loop, arrayss);
3970 /* Initialize the loop. */
3971 gfc_conv_ss_startstride (&loop);
3972 gfc_conv_loop_setup (&loop, &expr->where);
3974 gfc_mark_ss_chain_used (arrayss, 1);
3975 /* Generate the loop body. */
3976 gfc_start_scalarized_body (&loop, &body);
3978 /* If the condition matches then set the return value. */
3979 gfc_start_block (&block);
3980 if (op == EQ_EXPR)
3981 tmp = convert (type, boolean_false_node);
3982 else
3983 tmp = convert (type, boolean_true_node);
3984 gfc_add_modify (&block, resvar, tmp);
3986 /* And break out of the loop. */
3987 tmp = build1_v (GOTO_EXPR, exit_label);
3988 gfc_add_expr_to_block (&block, tmp);
3990 found = gfc_finish_block (&block);
3992 /* Check this element. */
3993 gfc_init_se (&arrayse, NULL);
3994 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3995 arrayse.ss = arrayss;
3996 gfc_conv_expr_val (&arrayse, actual->expr);
3998 gfc_add_block_to_block (&body, &arrayse.pre);
3999 tmp = fold_build2_loc (input_location, op, boolean_type_node, arrayse.expr,
4000 build_int_cst (TREE_TYPE (arrayse.expr), 0));
4001 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
4002 gfc_add_expr_to_block (&body, tmp);
4003 gfc_add_block_to_block (&body, &arrayse.post);
4005 gfc_trans_scalarizing_loops (&loop, &body);
4007 /* Add the exit label. */
4008 tmp = build1_v (LABEL_EXPR, exit_label);
4009 gfc_add_expr_to_block (&loop.pre, tmp);
4011 gfc_add_block_to_block (&se->pre, &loop.pre);
4012 gfc_add_block_to_block (&se->pre, &loop.post);
4013 gfc_cleanup_loop (&loop);
4015 se->expr = resvar;
4018 /* COUNT(A) = Number of true elements in A. */
4019 static void
4020 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
4022 tree resvar;
4023 tree type;
4024 stmtblock_t body;
4025 tree tmp;
4026 gfc_loopinfo loop;
4027 gfc_actual_arglist *actual;
4028 gfc_ss *arrayss;
4029 gfc_se arrayse;
4031 if (se->ss)
4033 gfc_conv_intrinsic_funcall (se, expr);
4034 return;
4037 actual = expr->value.function.actual;
4039 type = gfc_typenode_for_spec (&expr->ts);
4040 /* Initialize the result. */
4041 resvar = gfc_create_var (type, "count");
4042 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4044 /* Walk the arguments. */
4045 arrayss = gfc_walk_expr (actual->expr);
4046 gcc_assert (arrayss != gfc_ss_terminator);
4048 /* Initialize the scalarizer. */
4049 gfc_init_loopinfo (&loop);
4050 gfc_add_ss_to_loop (&loop, arrayss);
4052 /* Initialize the loop. */
4053 gfc_conv_ss_startstride (&loop);
4054 gfc_conv_loop_setup (&loop, &expr->where);
4056 gfc_mark_ss_chain_used (arrayss, 1);
4057 /* Generate the loop body. */
4058 gfc_start_scalarized_body (&loop, &body);
4060 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
4061 resvar, build_int_cst (TREE_TYPE (resvar), 1));
4062 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
4064 gfc_init_se (&arrayse, NULL);
4065 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4066 arrayse.ss = arrayss;
4067 gfc_conv_expr_val (&arrayse, actual->expr);
4068 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
4069 build_empty_stmt (input_location));
4071 gfc_add_block_to_block (&body, &arrayse.pre);
4072 gfc_add_expr_to_block (&body, tmp);
4073 gfc_add_block_to_block (&body, &arrayse.post);
4075 gfc_trans_scalarizing_loops (&loop, &body);
4077 gfc_add_block_to_block (&se->pre, &loop.pre);
4078 gfc_add_block_to_block (&se->pre, &loop.post);
4079 gfc_cleanup_loop (&loop);
4081 se->expr = resvar;
4085 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4086 struct and return the corresponding loopinfo. */
4088 static gfc_loopinfo *
4089 enter_nested_loop (gfc_se *se)
4091 se->ss = se->ss->nested_ss;
4092 gcc_assert (se->ss == se->ss->loop->ss);
4094 return se->ss->loop;
4098 /* Inline implementation of the sum and product intrinsics. */
4099 static void
4100 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
4101 bool norm2)
4103 tree resvar;
4104 tree scale = NULL_TREE;
4105 tree type;
4106 stmtblock_t body;
4107 stmtblock_t block;
4108 tree tmp;
4109 gfc_loopinfo loop, *ploop;
4110 gfc_actual_arglist *arg_array, *arg_mask;
4111 gfc_ss *arrayss = NULL;
4112 gfc_ss *maskss = NULL;
4113 gfc_se arrayse;
4114 gfc_se maskse;
4115 gfc_se *parent_se;
4116 gfc_expr *arrayexpr;
4117 gfc_expr *maskexpr;
4119 if (expr->rank > 0)
4121 gcc_assert (gfc_inline_intrinsic_function_p (expr));
4122 parent_se = se;
4124 else
4125 parent_se = NULL;
4127 type = gfc_typenode_for_spec (&expr->ts);
4128 /* Initialize the result. */
4129 resvar = gfc_create_var (type, "val");
4130 if (norm2)
4132 /* result = 0.0;
4133 scale = 1.0. */
4134 scale = gfc_create_var (type, "scale");
4135 gfc_add_modify (&se->pre, scale,
4136 gfc_build_const (type, integer_one_node));
4137 tmp = gfc_build_const (type, integer_zero_node);
4139 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4140 tmp = gfc_build_const (type, integer_zero_node);
4141 else if (op == NE_EXPR)
4142 /* PARITY. */
4143 tmp = convert (type, boolean_false_node);
4144 else if (op == BIT_AND_EXPR)
4145 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
4146 type, integer_one_node));
4147 else
4148 tmp = gfc_build_const (type, integer_one_node);
4150 gfc_add_modify (&se->pre, resvar, tmp);
4152 arg_array = expr->value.function.actual;
4154 arrayexpr = arg_array->expr;
4156 if (op == NE_EXPR || norm2)
4157 /* PARITY and NORM2. */
4158 maskexpr = NULL;
4159 else
4161 arg_mask = arg_array->next->next;
4162 gcc_assert (arg_mask != NULL);
4163 maskexpr = arg_mask->expr;
4166 if (expr->rank == 0)
4168 /* Walk the arguments. */
4169 arrayss = gfc_walk_expr (arrayexpr);
4170 gcc_assert (arrayss != gfc_ss_terminator);
4172 if (maskexpr && maskexpr->rank > 0)
4174 maskss = gfc_walk_expr (maskexpr);
4175 gcc_assert (maskss != gfc_ss_terminator);
4177 else
4178 maskss = NULL;
4180 /* Initialize the scalarizer. */
4181 gfc_init_loopinfo (&loop);
4182 gfc_add_ss_to_loop (&loop, arrayss);
4183 if (maskexpr && maskexpr->rank > 0)
4184 gfc_add_ss_to_loop (&loop, maskss);
4186 /* Initialize the loop. */
4187 gfc_conv_ss_startstride (&loop);
4188 gfc_conv_loop_setup (&loop, &expr->where);
4190 gfc_mark_ss_chain_used (arrayss, 1);
4191 if (maskexpr && maskexpr->rank > 0)
4192 gfc_mark_ss_chain_used (maskss, 1);
4194 ploop = &loop;
4196 else
4197 /* All the work has been done in the parent loops. */
4198 ploop = enter_nested_loop (se);
4200 gcc_assert (ploop);
4202 /* Generate the loop body. */
4203 gfc_start_scalarized_body (ploop, &body);
4205 /* If we have a mask, only add this element if the mask is set. */
4206 if (maskexpr && maskexpr->rank > 0)
4208 gfc_init_se (&maskse, parent_se);
4209 gfc_copy_loopinfo_to_se (&maskse, ploop);
4210 if (expr->rank == 0)
4211 maskse.ss = maskss;
4212 gfc_conv_expr_val (&maskse, maskexpr);
4213 gfc_add_block_to_block (&body, &maskse.pre);
4215 gfc_start_block (&block);
4217 else
4218 gfc_init_block (&block);
4220 /* Do the actual summation/product. */
4221 gfc_init_se (&arrayse, parent_se);
4222 gfc_copy_loopinfo_to_se (&arrayse, ploop);
4223 if (expr->rank == 0)
4224 arrayse.ss = arrayss;
4225 gfc_conv_expr_val (&arrayse, arrayexpr);
4226 gfc_add_block_to_block (&block, &arrayse.pre);
4228 if (norm2)
4230 /* if (x (i) != 0.0)
4232 absX = abs(x(i))
4233 if (absX > scale)
4235 val = scale/absX;
4236 result = 1.0 + result * val * val;
4237 scale = absX;
4239 else
4241 val = absX/scale;
4242 result += val * val;
4244 } */
4245 tree res1, res2, cond, absX, val;
4246 stmtblock_t ifblock1, ifblock2, ifblock3;
4248 gfc_init_block (&ifblock1);
4250 absX = gfc_create_var (type, "absX");
4251 gfc_add_modify (&ifblock1, absX,
4252 fold_build1_loc (input_location, ABS_EXPR, type,
4253 arrayse.expr));
4254 val = gfc_create_var (type, "val");
4255 gfc_add_expr_to_block (&ifblock1, val);
4257 gfc_init_block (&ifblock2);
4258 gfc_add_modify (&ifblock2, val,
4259 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
4260 absX));
4261 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4262 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
4263 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
4264 gfc_build_const (type, integer_one_node));
4265 gfc_add_modify (&ifblock2, resvar, res1);
4266 gfc_add_modify (&ifblock2, scale, absX);
4267 res1 = gfc_finish_block (&ifblock2);
4269 gfc_init_block (&ifblock3);
4270 gfc_add_modify (&ifblock3, val,
4271 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
4272 scale));
4273 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
4274 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
4275 gfc_add_modify (&ifblock3, resvar, res2);
4276 res2 = gfc_finish_block (&ifblock3);
4278 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
4279 absX, scale);
4280 tmp = build3_v (COND_EXPR, cond, res1, res2);
4281 gfc_add_expr_to_block (&ifblock1, tmp);
4282 tmp = gfc_finish_block (&ifblock1);
4284 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
4285 arrayse.expr,
4286 gfc_build_const (type, integer_zero_node));
4288 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4289 gfc_add_expr_to_block (&block, tmp);
4291 else
4293 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
4294 gfc_add_modify (&block, resvar, tmp);
4297 gfc_add_block_to_block (&block, &arrayse.post);
4299 if (maskexpr && maskexpr->rank > 0)
4301 /* We enclose the above in if (mask) {...} . */
4303 tmp = gfc_finish_block (&block);
4304 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4305 build_empty_stmt (input_location));
4307 else
4308 tmp = gfc_finish_block (&block);
4309 gfc_add_expr_to_block (&body, tmp);
4311 gfc_trans_scalarizing_loops (ploop, &body);
4313 /* For a scalar mask, enclose the loop in an if statement. */
4314 if (maskexpr && maskexpr->rank == 0)
4316 gfc_init_block (&block);
4317 gfc_add_block_to_block (&block, &ploop->pre);
4318 gfc_add_block_to_block (&block, &ploop->post);
4319 tmp = gfc_finish_block (&block);
4321 if (expr->rank > 0)
4323 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
4324 build_empty_stmt (input_location));
4325 gfc_advance_se_ss_chain (se);
4327 else
4329 gcc_assert (expr->rank == 0);
4330 gfc_init_se (&maskse, NULL);
4331 gfc_conv_expr_val (&maskse, maskexpr);
4332 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4333 build_empty_stmt (input_location));
4336 gfc_add_expr_to_block (&block, tmp);
4337 gfc_add_block_to_block (&se->pre, &block);
4338 gcc_assert (se->post.head == NULL);
4340 else
4342 gfc_add_block_to_block (&se->pre, &ploop->pre);
4343 gfc_add_block_to_block (&se->pre, &ploop->post);
4346 if (expr->rank == 0)
4347 gfc_cleanup_loop (ploop);
4349 if (norm2)
4351 /* result = scale * sqrt(result). */
4352 tree sqrt;
4353 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
4354 resvar = build_call_expr_loc (input_location,
4355 sqrt, 1, resvar);
4356 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
4359 se->expr = resvar;
4363 /* Inline implementation of the dot_product intrinsic. This function
4364 is based on gfc_conv_intrinsic_arith (the previous function). */
4365 static void
4366 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
4368 tree resvar;
4369 tree type;
4370 stmtblock_t body;
4371 stmtblock_t block;
4372 tree tmp;
4373 gfc_loopinfo loop;
4374 gfc_actual_arglist *actual;
4375 gfc_ss *arrayss1, *arrayss2;
4376 gfc_se arrayse1, arrayse2;
4377 gfc_expr *arrayexpr1, *arrayexpr2;
4379 type = gfc_typenode_for_spec (&expr->ts);
4381 /* Initialize the result. */
4382 resvar = gfc_create_var (type, "val");
4383 if (expr->ts.type == BT_LOGICAL)
4384 tmp = build_int_cst (type, 0);
4385 else
4386 tmp = gfc_build_const (type, integer_zero_node);
4388 gfc_add_modify (&se->pre, resvar, tmp);
4390 /* Walk argument #1. */
4391 actual = expr->value.function.actual;
4392 arrayexpr1 = actual->expr;
4393 arrayss1 = gfc_walk_expr (arrayexpr1);
4394 gcc_assert (arrayss1 != gfc_ss_terminator);
4396 /* Walk argument #2. */
4397 actual = actual->next;
4398 arrayexpr2 = actual->expr;
4399 arrayss2 = gfc_walk_expr (arrayexpr2);
4400 gcc_assert (arrayss2 != gfc_ss_terminator);
4402 /* Initialize the scalarizer. */
4403 gfc_init_loopinfo (&loop);
4404 gfc_add_ss_to_loop (&loop, arrayss1);
4405 gfc_add_ss_to_loop (&loop, arrayss2);
4407 /* Initialize the loop. */
4408 gfc_conv_ss_startstride (&loop);
4409 gfc_conv_loop_setup (&loop, &expr->where);
4411 gfc_mark_ss_chain_used (arrayss1, 1);
4412 gfc_mark_ss_chain_used (arrayss2, 1);
4414 /* Generate the loop body. */
4415 gfc_start_scalarized_body (&loop, &body);
4416 gfc_init_block (&block);
4418 /* Make the tree expression for [conjg(]array1[)]. */
4419 gfc_init_se (&arrayse1, NULL);
4420 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
4421 arrayse1.ss = arrayss1;
4422 gfc_conv_expr_val (&arrayse1, arrayexpr1);
4423 if (expr->ts.type == BT_COMPLEX)
4424 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
4425 arrayse1.expr);
4426 gfc_add_block_to_block (&block, &arrayse1.pre);
4428 /* Make the tree expression for array2. */
4429 gfc_init_se (&arrayse2, NULL);
4430 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
4431 arrayse2.ss = arrayss2;
4432 gfc_conv_expr_val (&arrayse2, arrayexpr2);
4433 gfc_add_block_to_block (&block, &arrayse2.pre);
4435 /* Do the actual product and sum. */
4436 if (expr->ts.type == BT_LOGICAL)
4438 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
4439 arrayse1.expr, arrayse2.expr);
4440 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
4442 else
4444 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
4445 arrayse2.expr);
4446 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
4448 gfc_add_modify (&block, resvar, tmp);
4450 /* Finish up the loop block and the loop. */
4451 tmp = gfc_finish_block (&block);
4452 gfc_add_expr_to_block (&body, tmp);
4454 gfc_trans_scalarizing_loops (&loop, &body);
4455 gfc_add_block_to_block (&se->pre, &loop.pre);
4456 gfc_add_block_to_block (&se->pre, &loop.post);
4457 gfc_cleanup_loop (&loop);
4459 se->expr = resvar;
4463 /* Emit code for minloc or maxloc intrinsic. There are many different cases
4464 we need to handle. For performance reasons we sometimes create two
4465 loops instead of one, where the second one is much simpler.
4466 Examples for minloc intrinsic:
4467 1) Result is an array, a call is generated
4468 2) Array mask is used and NaNs need to be supported:
4469 limit = Infinity;
4470 pos = 0;
4471 S = from;
4472 while (S <= to) {
4473 if (mask[S]) {
4474 if (pos == 0) pos = S + (1 - from);
4475 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4477 S++;
4479 goto lab2;
4480 lab1:;
4481 while (S <= to) {
4482 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4483 S++;
4485 lab2:;
4486 3) NaNs need to be supported, but it is known at compile time or cheaply
4487 at runtime whether array is nonempty or not:
4488 limit = Infinity;
4489 pos = 0;
4490 S = from;
4491 while (S <= to) {
4492 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4493 S++;
4495 if (from <= to) pos = 1;
4496 goto lab2;
4497 lab1:;
4498 while (S <= to) {
4499 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4500 S++;
4502 lab2:;
4503 4) NaNs aren't supported, array mask is used:
4504 limit = infinities_supported ? Infinity : huge (limit);
4505 pos = 0;
4506 S = from;
4507 while (S <= to) {
4508 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4509 S++;
4511 goto lab2;
4512 lab1:;
4513 while (S <= to) {
4514 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4515 S++;
4517 lab2:;
4518 5) Same without array mask:
4519 limit = infinities_supported ? Infinity : huge (limit);
4520 pos = (from <= to) ? 1 : 0;
4521 S = from;
4522 while (S <= to) {
4523 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4524 S++;
4526 For 3) and 5), if mask is scalar, this all goes into a conditional,
4527 setting pos = 0; in the else branch. */
4529 static void
4530 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
4532 stmtblock_t body;
4533 stmtblock_t block;
4534 stmtblock_t ifblock;
4535 stmtblock_t elseblock;
4536 tree limit;
4537 tree type;
4538 tree tmp;
4539 tree cond;
4540 tree elsetmp;
4541 tree ifbody;
4542 tree offset;
4543 tree nonempty;
4544 tree lab1, lab2;
4545 gfc_loopinfo loop;
4546 gfc_actual_arglist *actual;
4547 gfc_ss *arrayss;
4548 gfc_ss *maskss;
4549 gfc_se arrayse;
4550 gfc_se maskse;
4551 gfc_expr *arrayexpr;
4552 gfc_expr *maskexpr;
4553 tree pos;
4554 int n;
4556 if (se->ss)
4558 gfc_conv_intrinsic_funcall (se, expr);
4559 return;
4562 /* Initialize the result. */
4563 pos = gfc_create_var (gfc_array_index_type, "pos");
4564 offset = gfc_create_var (gfc_array_index_type, "offset");
4565 type = gfc_typenode_for_spec (&expr->ts);
4567 /* Walk the arguments. */
4568 actual = expr->value.function.actual;
4569 arrayexpr = actual->expr;
4570 arrayss = gfc_walk_expr (arrayexpr);
4571 gcc_assert (arrayss != gfc_ss_terminator);
4573 actual = actual->next->next;
4574 gcc_assert (actual);
4575 maskexpr = actual->expr;
4576 nonempty = NULL;
4577 if (maskexpr && maskexpr->rank != 0)
4579 maskss = gfc_walk_expr (maskexpr);
4580 gcc_assert (maskss != gfc_ss_terminator);
4582 else
4584 mpz_t asize;
4585 if (gfc_array_size (arrayexpr, &asize))
4587 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
4588 mpz_clear (asize);
4589 nonempty = fold_build2_loc (input_location, GT_EXPR,
4590 boolean_type_node, nonempty,
4591 gfc_index_zero_node);
4593 maskss = NULL;
4596 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
4597 switch (arrayexpr->ts.type)
4599 case BT_REAL:
4600 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
4601 break;
4603 case BT_INTEGER:
4604 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
4605 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
4606 arrayexpr->ts.kind);
4607 break;
4609 default:
4610 gcc_unreachable ();
4613 /* We start with the most negative possible value for MAXLOC, and the most
4614 positive possible value for MINLOC. The most negative possible value is
4615 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
4616 possible value is HUGE in both cases. */
4617 if (op == GT_EXPR)
4618 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
4619 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
4620 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
4621 build_int_cst (TREE_TYPE (tmp), 1));
4623 gfc_add_modify (&se->pre, limit, tmp);
4625 /* Initialize the scalarizer. */
4626 gfc_init_loopinfo (&loop);
4627 gfc_add_ss_to_loop (&loop, arrayss);
4628 if (maskss)
4629 gfc_add_ss_to_loop (&loop, maskss);
4631 /* Initialize the loop. */
4632 gfc_conv_ss_startstride (&loop);
4634 /* The code generated can have more than one loop in sequence (see the
4635 comment at the function header). This doesn't work well with the
4636 scalarizer, which changes arrays' offset when the scalarization loops
4637 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
4638 are currently inlined in the scalar case only (for which loop is of rank
4639 one). As there is no dependency to care about in that case, there is no
4640 temporary, so that we can use the scalarizer temporary code to handle
4641 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
4642 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
4643 to restore offset.
4644 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
4645 should eventually go away. We could either create two loops properly,
4646 or find another way to save/restore the array offsets between the two
4647 loops (without conflicting with temporary management), or use a single
4648 loop minmaxloc implementation. See PR 31067. */
4649 loop.temp_dim = loop.dimen;
4650 gfc_conv_loop_setup (&loop, &expr->where);
4652 gcc_assert (loop.dimen == 1);
4653 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
4654 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
4655 loop.from[0], loop.to[0]);
4657 lab1 = NULL;
4658 lab2 = NULL;
4659 /* Initialize the position to zero, following Fortran 2003. We are free
4660 to do this because Fortran 95 allows the result of an entirely false
4661 mask to be processor dependent. If we know at compile time the array
4662 is non-empty and no MASK is used, we can initialize to 1 to simplify
4663 the inner loop. */
4664 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
4665 gfc_add_modify (&loop.pre, pos,
4666 fold_build3_loc (input_location, COND_EXPR,
4667 gfc_array_index_type,
4668 nonempty, gfc_index_one_node,
4669 gfc_index_zero_node));
4670 else
4672 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
4673 lab1 = gfc_build_label_decl (NULL_TREE);
4674 TREE_USED (lab1) = 1;
4675 lab2 = gfc_build_label_decl (NULL_TREE);
4676 TREE_USED (lab2) = 1;
4679 /* An offset must be added to the loop
4680 counter to obtain the required position. */
4681 gcc_assert (loop.from[0]);
4683 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4684 gfc_index_one_node, loop.from[0]);
4685 gfc_add_modify (&loop.pre, offset, tmp);
4687 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
4688 if (maskss)
4689 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
4690 /* Generate the loop body. */
4691 gfc_start_scalarized_body (&loop, &body);
4693 /* If we have a mask, only check this element if the mask is set. */
4694 if (maskss)
4696 gfc_init_se (&maskse, NULL);
4697 gfc_copy_loopinfo_to_se (&maskse, &loop);
4698 maskse.ss = maskss;
4699 gfc_conv_expr_val (&maskse, maskexpr);
4700 gfc_add_block_to_block (&body, &maskse.pre);
4702 gfc_start_block (&block);
4704 else
4705 gfc_init_block (&block);
4707 /* Compare with the current limit. */
4708 gfc_init_se (&arrayse, NULL);
4709 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4710 arrayse.ss = arrayss;
4711 gfc_conv_expr_val (&arrayse, arrayexpr);
4712 gfc_add_block_to_block (&block, &arrayse.pre);
4714 /* We do the following if this is a more extreme value. */
4715 gfc_start_block (&ifblock);
4717 /* Assign the value to the limit... */
4718 gfc_add_modify (&ifblock, limit, arrayse.expr);
4720 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
4722 stmtblock_t ifblock2;
4723 tree ifbody2;
4725 gfc_start_block (&ifblock2);
4726 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4727 loop.loopvar[0], offset);
4728 gfc_add_modify (&ifblock2, pos, tmp);
4729 ifbody2 = gfc_finish_block (&ifblock2);
4730 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, pos,
4731 gfc_index_zero_node);
4732 tmp = build3_v (COND_EXPR, cond, ifbody2,
4733 build_empty_stmt (input_location));
4734 gfc_add_expr_to_block (&block, tmp);
4737 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4738 loop.loopvar[0], offset);
4739 gfc_add_modify (&ifblock, pos, tmp);
4741 if (lab1)
4742 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
4744 ifbody = gfc_finish_block (&ifblock);
4746 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
4748 if (lab1)
4749 cond = fold_build2_loc (input_location,
4750 op == GT_EXPR ? GE_EXPR : LE_EXPR,
4751 boolean_type_node, arrayse.expr, limit);
4752 else
4753 cond = fold_build2_loc (input_location, op, boolean_type_node,
4754 arrayse.expr, limit);
4756 ifbody = build3_v (COND_EXPR, cond, ifbody,
4757 build_empty_stmt (input_location));
4759 gfc_add_expr_to_block (&block, ifbody);
4761 if (maskss)
4763 /* We enclose the above in if (mask) {...}. */
4764 tmp = gfc_finish_block (&block);
4766 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4767 build_empty_stmt (input_location));
4769 else
4770 tmp = gfc_finish_block (&block);
4771 gfc_add_expr_to_block (&body, tmp);
4773 if (lab1)
4775 gfc_trans_scalarized_loop_boundary (&loop, &body);
4777 if (HONOR_NANS (DECL_MODE (limit)))
4779 if (nonempty != NULL)
4781 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
4782 tmp = build3_v (COND_EXPR, nonempty, ifbody,
4783 build_empty_stmt (input_location));
4784 gfc_add_expr_to_block (&loop.code[0], tmp);
4788 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
4789 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
4791 /* If we have a mask, only check this element if the mask is set. */
4792 if (maskss)
4794 gfc_init_se (&maskse, NULL);
4795 gfc_copy_loopinfo_to_se (&maskse, &loop);
4796 maskse.ss = maskss;
4797 gfc_conv_expr_val (&maskse, maskexpr);
4798 gfc_add_block_to_block (&body, &maskse.pre);
4800 gfc_start_block (&block);
4802 else
4803 gfc_init_block (&block);
4805 /* Compare with the current limit. */
4806 gfc_init_se (&arrayse, NULL);
4807 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4808 arrayse.ss = arrayss;
4809 gfc_conv_expr_val (&arrayse, arrayexpr);
4810 gfc_add_block_to_block (&block, &arrayse.pre);
4812 /* We do the following if this is a more extreme value. */
4813 gfc_start_block (&ifblock);
4815 /* Assign the value to the limit... */
4816 gfc_add_modify (&ifblock, limit, arrayse.expr);
4818 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4819 loop.loopvar[0], offset);
4820 gfc_add_modify (&ifblock, pos, tmp);
4822 ifbody = gfc_finish_block (&ifblock);
4824 cond = fold_build2_loc (input_location, op, boolean_type_node,
4825 arrayse.expr, limit);
4827 tmp = build3_v (COND_EXPR, cond, ifbody,
4828 build_empty_stmt (input_location));
4829 gfc_add_expr_to_block (&block, tmp);
4831 if (maskss)
4833 /* We enclose the above in if (mask) {...}. */
4834 tmp = gfc_finish_block (&block);
4836 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4837 build_empty_stmt (input_location));
4839 else
4840 tmp = gfc_finish_block (&block);
4841 gfc_add_expr_to_block (&body, tmp);
4842 /* Avoid initializing loopvar[0] again, it should be left where
4843 it finished by the first loop. */
4844 loop.from[0] = loop.loopvar[0];
4847 gfc_trans_scalarizing_loops (&loop, &body);
4849 if (lab2)
4850 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
4852 /* For a scalar mask, enclose the loop in an if statement. */
4853 if (maskexpr && maskss == NULL)
4855 gfc_init_se (&maskse, NULL);
4856 gfc_conv_expr_val (&maskse, maskexpr);
4857 gfc_init_block (&block);
4858 gfc_add_block_to_block (&block, &loop.pre);
4859 gfc_add_block_to_block (&block, &loop.post);
4860 tmp = gfc_finish_block (&block);
4862 /* For the else part of the scalar mask, just initialize
4863 the pos variable the same way as above. */
4865 gfc_init_block (&elseblock);
4866 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
4867 elsetmp = gfc_finish_block (&elseblock);
4869 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
4870 gfc_add_expr_to_block (&block, tmp);
4871 gfc_add_block_to_block (&se->pre, &block);
4873 else
4875 gfc_add_block_to_block (&se->pre, &loop.pre);
4876 gfc_add_block_to_block (&se->pre, &loop.post);
4878 gfc_cleanup_loop (&loop);
4880 se->expr = convert (type, pos);
4883 /* Emit code for minval or maxval intrinsic. There are many different cases
4884 we need to handle. For performance reasons we sometimes create two
4885 loops instead of one, where the second one is much simpler.
4886 Examples for minval intrinsic:
4887 1) Result is an array, a call is generated
4888 2) Array mask is used and NaNs need to be supported, rank 1:
4889 limit = Infinity;
4890 nonempty = false;
4891 S = from;
4892 while (S <= to) {
4893 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
4894 S++;
4896 limit = nonempty ? NaN : huge (limit);
4897 lab:
4898 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
4899 3) NaNs need to be supported, but it is known at compile time or cheaply
4900 at runtime whether array is nonempty or not, rank 1:
4901 limit = Infinity;
4902 S = from;
4903 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
4904 limit = (from <= to) ? NaN : huge (limit);
4905 lab:
4906 while (S <= to) { limit = min (a[S], limit); S++; }
4907 4) Array mask is used and NaNs need to be supported, rank > 1:
4908 limit = Infinity;
4909 nonempty = false;
4910 fast = false;
4911 S1 = from1;
4912 while (S1 <= to1) {
4913 S2 = from2;
4914 while (S2 <= to2) {
4915 if (mask[S1][S2]) {
4916 if (fast) limit = min (a[S1][S2], limit);
4917 else {
4918 nonempty = true;
4919 if (a[S1][S2] <= limit) {
4920 limit = a[S1][S2];
4921 fast = true;
4925 S2++;
4927 S1++;
4929 if (!fast)
4930 limit = nonempty ? NaN : huge (limit);
4931 5) NaNs need to be supported, but it is known at compile time or cheaply
4932 at runtime whether array is nonempty or not, rank > 1:
4933 limit = Infinity;
4934 fast = false;
4935 S1 = from1;
4936 while (S1 <= to1) {
4937 S2 = from2;
4938 while (S2 <= to2) {
4939 if (fast) limit = min (a[S1][S2], limit);
4940 else {
4941 if (a[S1][S2] <= limit) {
4942 limit = a[S1][S2];
4943 fast = true;
4946 S2++;
4948 S1++;
4950 if (!fast)
4951 limit = (nonempty_array) ? NaN : huge (limit);
4952 6) NaNs aren't supported, but infinities are. Array mask is used:
4953 limit = Infinity;
4954 nonempty = false;
4955 S = from;
4956 while (S <= to) {
4957 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
4958 S++;
4960 limit = nonempty ? limit : huge (limit);
4961 7) Same without array mask:
4962 limit = Infinity;
4963 S = from;
4964 while (S <= to) { limit = min (a[S], limit); S++; }
4965 limit = (from <= to) ? limit : huge (limit);
4966 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
4967 limit = huge (limit);
4968 S = from;
4969 while (S <= to) { limit = min (a[S], limit); S++); }
4971 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
4972 with array mask instead).
4973 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
4974 setting limit = huge (limit); in the else branch. */
4976 static void
4977 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
4979 tree limit;
4980 tree type;
4981 tree tmp;
4982 tree ifbody;
4983 tree nonempty;
4984 tree nonempty_var;
4985 tree lab;
4986 tree fast;
4987 tree huge_cst = NULL, nan_cst = NULL;
4988 stmtblock_t body;
4989 stmtblock_t block, block2;
4990 gfc_loopinfo loop;
4991 gfc_actual_arglist *actual;
4992 gfc_ss *arrayss;
4993 gfc_ss *maskss;
4994 gfc_se arrayse;
4995 gfc_se maskse;
4996 gfc_expr *arrayexpr;
4997 gfc_expr *maskexpr;
4998 int n;
5000 if (se->ss)
5002 gfc_conv_intrinsic_funcall (se, expr);
5003 return;
5006 type = gfc_typenode_for_spec (&expr->ts);
5007 /* Initialize the result. */
5008 limit = gfc_create_var (type, "limit");
5009 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
5010 switch (expr->ts.type)
5012 case BT_REAL:
5013 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
5014 expr->ts.kind, 0);
5015 if (HONOR_INFINITIES (DECL_MODE (limit)))
5017 REAL_VALUE_TYPE real;
5018 real_inf (&real);
5019 tmp = build_real (type, real);
5021 else
5022 tmp = huge_cst;
5023 if (HONOR_NANS (DECL_MODE (limit)))
5024 nan_cst = gfc_build_nan (type, "");
5025 break;
5027 case BT_INTEGER:
5028 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
5029 break;
5031 default:
5032 gcc_unreachable ();
5035 /* We start with the most negative possible value for MAXVAL, and the most
5036 positive possible value for MINVAL. The most negative possible value is
5037 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5038 possible value is HUGE in both cases. */
5039 if (op == GT_EXPR)
5041 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
5042 if (huge_cst)
5043 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
5044 TREE_TYPE (huge_cst), huge_cst);
5047 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
5048 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
5049 tmp, build_int_cst (type, 1));
5051 gfc_add_modify (&se->pre, limit, tmp);
5053 /* Walk the arguments. */
5054 actual = expr->value.function.actual;
5055 arrayexpr = actual->expr;
5056 arrayss = gfc_walk_expr (arrayexpr);
5057 gcc_assert (arrayss != gfc_ss_terminator);
5059 actual = actual->next->next;
5060 gcc_assert (actual);
5061 maskexpr = actual->expr;
5062 nonempty = NULL;
5063 if (maskexpr && maskexpr->rank != 0)
5065 maskss = gfc_walk_expr (maskexpr);
5066 gcc_assert (maskss != gfc_ss_terminator);
5068 else
5070 mpz_t asize;
5071 if (gfc_array_size (arrayexpr, &asize))
5073 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
5074 mpz_clear (asize);
5075 nonempty = fold_build2_loc (input_location, GT_EXPR,
5076 boolean_type_node, nonempty,
5077 gfc_index_zero_node);
5079 maskss = NULL;
5082 /* Initialize the scalarizer. */
5083 gfc_init_loopinfo (&loop);
5084 gfc_add_ss_to_loop (&loop, arrayss);
5085 if (maskss)
5086 gfc_add_ss_to_loop (&loop, maskss);
5088 /* Initialize the loop. */
5089 gfc_conv_ss_startstride (&loop);
5091 /* The code generated can have more than one loop in sequence (see the
5092 comment at the function header). This doesn't work well with the
5093 scalarizer, which changes arrays' offset when the scalarization loops
5094 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
5095 are currently inlined in the scalar case only. As there is no dependency
5096 to care about in that case, there is no temporary, so that we can use the
5097 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
5098 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
5099 gfc_trans_scalarized_loop_boundary even later to restore offset.
5100 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
5101 should eventually go away. We could either create two loops properly,
5102 or find another way to save/restore the array offsets between the two
5103 loops (without conflicting with temporary management), or use a single
5104 loop minmaxval implementation. See PR 31067. */
5105 loop.temp_dim = loop.dimen;
5106 gfc_conv_loop_setup (&loop, &expr->where);
5108 if (nonempty == NULL && maskss == NULL
5109 && loop.dimen == 1 && loop.from[0] && loop.to[0])
5110 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
5111 loop.from[0], loop.to[0]);
5112 nonempty_var = NULL;
5113 if (nonempty == NULL
5114 && (HONOR_INFINITIES (DECL_MODE (limit))
5115 || HONOR_NANS (DECL_MODE (limit))))
5117 nonempty_var = gfc_create_var (boolean_type_node, "nonempty");
5118 gfc_add_modify (&se->pre, nonempty_var, boolean_false_node);
5119 nonempty = nonempty_var;
5121 lab = NULL;
5122 fast = NULL;
5123 if (HONOR_NANS (DECL_MODE (limit)))
5125 if (loop.dimen == 1)
5127 lab = gfc_build_label_decl (NULL_TREE);
5128 TREE_USED (lab) = 1;
5130 else
5132 fast = gfc_create_var (boolean_type_node, "fast");
5133 gfc_add_modify (&se->pre, fast, boolean_false_node);
5137 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
5138 if (maskss)
5139 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
5140 /* Generate the loop body. */
5141 gfc_start_scalarized_body (&loop, &body);
5143 /* If we have a mask, only add this element if the mask is set. */
5144 if (maskss)
5146 gfc_init_se (&maskse, NULL);
5147 gfc_copy_loopinfo_to_se (&maskse, &loop);
5148 maskse.ss = maskss;
5149 gfc_conv_expr_val (&maskse, maskexpr);
5150 gfc_add_block_to_block (&body, &maskse.pre);
5152 gfc_start_block (&block);
5154 else
5155 gfc_init_block (&block);
5157 /* Compare with the current limit. */
5158 gfc_init_se (&arrayse, NULL);
5159 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5160 arrayse.ss = arrayss;
5161 gfc_conv_expr_val (&arrayse, arrayexpr);
5162 gfc_add_block_to_block (&block, &arrayse.pre);
5164 gfc_init_block (&block2);
5166 if (nonempty_var)
5167 gfc_add_modify (&block2, nonempty_var, boolean_true_node);
5169 if (HONOR_NANS (DECL_MODE (limit)))
5171 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5172 boolean_type_node, arrayse.expr, limit);
5173 if (lab)
5174 ifbody = build1_v (GOTO_EXPR, lab);
5175 else
5177 stmtblock_t ifblock;
5179 gfc_init_block (&ifblock);
5180 gfc_add_modify (&ifblock, limit, arrayse.expr);
5181 gfc_add_modify (&ifblock, fast, boolean_true_node);
5182 ifbody = gfc_finish_block (&ifblock);
5184 tmp = build3_v (COND_EXPR, tmp, ifbody,
5185 build_empty_stmt (input_location));
5186 gfc_add_expr_to_block (&block2, tmp);
5188 else
5190 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5191 signed zeros. */
5192 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5194 tmp = fold_build2_loc (input_location, op, boolean_type_node,
5195 arrayse.expr, limit);
5196 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5197 tmp = build3_v (COND_EXPR, tmp, ifbody,
5198 build_empty_stmt (input_location));
5199 gfc_add_expr_to_block (&block2, tmp);
5201 else
5203 tmp = fold_build2_loc (input_location,
5204 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5205 type, arrayse.expr, limit);
5206 gfc_add_modify (&block2, limit, tmp);
5210 if (fast)
5212 tree elsebody = gfc_finish_block (&block2);
5214 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5215 signed zeros. */
5216 if (HONOR_NANS (DECL_MODE (limit))
5217 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5219 tmp = fold_build2_loc (input_location, op, boolean_type_node,
5220 arrayse.expr, limit);
5221 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5222 ifbody = build3_v (COND_EXPR, tmp, ifbody,
5223 build_empty_stmt (input_location));
5225 else
5227 tmp = fold_build2_loc (input_location,
5228 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5229 type, arrayse.expr, limit);
5230 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5232 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
5233 gfc_add_expr_to_block (&block, tmp);
5235 else
5236 gfc_add_block_to_block (&block, &block2);
5238 gfc_add_block_to_block (&block, &arrayse.post);
5240 tmp = gfc_finish_block (&block);
5241 if (maskss)
5242 /* We enclose the above in if (mask) {...}. */
5243 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5244 build_empty_stmt (input_location));
5245 gfc_add_expr_to_block (&body, tmp);
5247 if (lab)
5249 gfc_trans_scalarized_loop_boundary (&loop, &body);
5251 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5252 nan_cst, huge_cst);
5253 gfc_add_modify (&loop.code[0], limit, tmp);
5254 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
5256 /* If we have a mask, only add this element if the mask is set. */
5257 if (maskss)
5259 gfc_init_se (&maskse, NULL);
5260 gfc_copy_loopinfo_to_se (&maskse, &loop);
5261 maskse.ss = maskss;
5262 gfc_conv_expr_val (&maskse, maskexpr);
5263 gfc_add_block_to_block (&body, &maskse.pre);
5265 gfc_start_block (&block);
5267 else
5268 gfc_init_block (&block);
5270 /* Compare with the current limit. */
5271 gfc_init_se (&arrayse, NULL);
5272 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5273 arrayse.ss = arrayss;
5274 gfc_conv_expr_val (&arrayse, arrayexpr);
5275 gfc_add_block_to_block (&block, &arrayse.pre);
5277 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5278 signed zeros. */
5279 if (HONOR_NANS (DECL_MODE (limit))
5280 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
5282 tmp = fold_build2_loc (input_location, op, boolean_type_node,
5283 arrayse.expr, limit);
5284 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
5285 tmp = build3_v (COND_EXPR, tmp, ifbody,
5286 build_empty_stmt (input_location));
5287 gfc_add_expr_to_block (&block, tmp);
5289 else
5291 tmp = fold_build2_loc (input_location,
5292 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
5293 type, arrayse.expr, limit);
5294 gfc_add_modify (&block, limit, tmp);
5297 gfc_add_block_to_block (&block, &arrayse.post);
5299 tmp = gfc_finish_block (&block);
5300 if (maskss)
5301 /* We enclose the above in if (mask) {...}. */
5302 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
5303 build_empty_stmt (input_location));
5304 gfc_add_expr_to_block (&body, tmp);
5305 /* Avoid initializing loopvar[0] again, it should be left where
5306 it finished by the first loop. */
5307 loop.from[0] = loop.loopvar[0];
5309 gfc_trans_scalarizing_loops (&loop, &body);
5311 if (fast)
5313 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
5314 nan_cst, huge_cst);
5315 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
5316 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
5317 ifbody);
5318 gfc_add_expr_to_block (&loop.pre, tmp);
5320 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
5322 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
5323 huge_cst);
5324 gfc_add_modify (&loop.pre, limit, tmp);
5327 /* For a scalar mask, enclose the loop in an if statement. */
5328 if (maskexpr && maskss == NULL)
5330 tree else_stmt;
5332 gfc_init_se (&maskse, NULL);
5333 gfc_conv_expr_val (&maskse, maskexpr);
5334 gfc_init_block (&block);
5335 gfc_add_block_to_block (&block, &loop.pre);
5336 gfc_add_block_to_block (&block, &loop.post);
5337 tmp = gfc_finish_block (&block);
5339 if (HONOR_INFINITIES (DECL_MODE (limit)))
5340 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
5341 else
5342 else_stmt = build_empty_stmt (input_location);
5343 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
5344 gfc_add_expr_to_block (&block, tmp);
5345 gfc_add_block_to_block (&se->pre, &block);
5347 else
5349 gfc_add_block_to_block (&se->pre, &loop.pre);
5350 gfc_add_block_to_block (&se->pre, &loop.post);
5353 gfc_cleanup_loop (&loop);
5355 se->expr = limit;
5358 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
5359 static void
5360 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
5362 tree args[2];
5363 tree type;
5364 tree tmp;
5366 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5367 type = TREE_TYPE (args[0]);
5369 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5370 build_int_cst (type, 1), args[1]);
5371 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
5372 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
5373 build_int_cst (type, 0));
5374 type = gfc_typenode_for_spec (&expr->ts);
5375 se->expr = convert (type, tmp);
5379 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
5380 static void
5381 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
5383 tree args[2];
5385 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5387 /* Convert both arguments to the unsigned type of the same size. */
5388 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
5389 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
5391 /* If they have unequal type size, convert to the larger one. */
5392 if (TYPE_PRECISION (TREE_TYPE (args[0]))
5393 > TYPE_PRECISION (TREE_TYPE (args[1])))
5394 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
5395 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
5396 > TYPE_PRECISION (TREE_TYPE (args[0])))
5397 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
5399 /* Now, we compare them. */
5400 se->expr = fold_build2_loc (input_location, op, boolean_type_node,
5401 args[0], args[1]);
5405 /* Generate code to perform the specified operation. */
5406 static void
5407 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
5409 tree args[2];
5411 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5412 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
5413 args[0], args[1]);
5416 /* Bitwise not. */
5417 static void
5418 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
5420 tree arg;
5422 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5423 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
5424 TREE_TYPE (arg), arg);
5427 /* Set or clear a single bit. */
5428 static void
5429 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
5431 tree args[2];
5432 tree type;
5433 tree tmp;
5434 enum tree_code op;
5436 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5437 type = TREE_TYPE (args[0]);
5439 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
5440 build_int_cst (type, 1), args[1]);
5441 if (set)
5442 op = BIT_IOR_EXPR;
5443 else
5445 op = BIT_AND_EXPR;
5446 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
5448 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
5451 /* Extract a sequence of bits.
5452 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
5453 static void
5454 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
5456 tree args[3];
5457 tree type;
5458 tree tmp;
5459 tree mask;
5461 gfc_conv_intrinsic_function_args (se, expr, args, 3);
5462 type = TREE_TYPE (args[0]);
5464 mask = build_int_cst (type, -1);
5465 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
5466 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
5468 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
5470 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
5473 static void
5474 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
5475 bool arithmetic)
5477 tree args[2], type, num_bits, cond;
5479 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5481 args[0] = gfc_evaluate_now (args[0], &se->pre);
5482 args[1] = gfc_evaluate_now (args[1], &se->pre);
5483 type = TREE_TYPE (args[0]);
5485 if (!arithmetic)
5486 args[0] = fold_convert (unsigned_type_for (type), args[0]);
5487 else
5488 gcc_assert (right_shift);
5490 se->expr = fold_build2_loc (input_location,
5491 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
5492 TREE_TYPE (args[0]), args[0], args[1]);
5494 if (!arithmetic)
5495 se->expr = fold_convert (type, se->expr);
5497 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5498 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5499 special case. */
5500 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
5501 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
5502 args[1], num_bits);
5504 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5505 build_int_cst (type, 0), se->expr);
5508 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
5510 : ((shift >= 0) ? i << shift : i >> -shift)
5511 where all shifts are logical shifts. */
5512 static void
5513 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
5515 tree args[2];
5516 tree type;
5517 tree utype;
5518 tree tmp;
5519 tree width;
5520 tree num_bits;
5521 tree cond;
5522 tree lshift;
5523 tree rshift;
5525 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5527 args[0] = gfc_evaluate_now (args[0], &se->pre);
5528 args[1] = gfc_evaluate_now (args[1], &se->pre);
5530 type = TREE_TYPE (args[0]);
5531 utype = unsigned_type_for (type);
5533 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
5534 args[1]);
5536 /* Left shift if positive. */
5537 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
5539 /* Right shift if negative.
5540 We convert to an unsigned type because we want a logical shift.
5541 The standard doesn't define the case of shifting negative
5542 numbers, and we try to be compatible with other compilers, most
5543 notably g77, here. */
5544 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
5545 utype, convert (utype, args[0]), width));
5547 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, args[1],
5548 build_int_cst (TREE_TYPE (args[1]), 0));
5549 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
5551 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5552 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5553 special case. */
5554 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
5555 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, width,
5556 num_bits);
5557 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
5558 build_int_cst (type, 0), tmp);
5562 /* Circular shift. AKA rotate or barrel shift. */
5564 static void
5565 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
5567 tree *args;
5568 tree type;
5569 tree tmp;
5570 tree lrot;
5571 tree rrot;
5572 tree zero;
5573 unsigned int num_args;
5575 num_args = gfc_intrinsic_argument_list_length (expr);
5576 args = XALLOCAVEC (tree, num_args);
5578 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
5580 if (num_args == 3)
5582 /* Use a library function for the 3 parameter version. */
5583 tree int4type = gfc_get_int_type (4);
5585 type = TREE_TYPE (args[0]);
5586 /* We convert the first argument to at least 4 bytes, and
5587 convert back afterwards. This removes the need for library
5588 functions for all argument sizes, and function will be
5589 aligned to at least 32 bits, so there's no loss. */
5590 if (expr->ts.kind < 4)
5591 args[0] = convert (int4type, args[0]);
5593 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
5594 need loads of library functions. They cannot have values >
5595 BIT_SIZE (I) so the conversion is safe. */
5596 args[1] = convert (int4type, args[1]);
5597 args[2] = convert (int4type, args[2]);
5599 switch (expr->ts.kind)
5601 case 1:
5602 case 2:
5603 case 4:
5604 tmp = gfor_fndecl_math_ishftc4;
5605 break;
5606 case 8:
5607 tmp = gfor_fndecl_math_ishftc8;
5608 break;
5609 case 16:
5610 tmp = gfor_fndecl_math_ishftc16;
5611 break;
5612 default:
5613 gcc_unreachable ();
5615 se->expr = build_call_expr_loc (input_location,
5616 tmp, 3, args[0], args[1], args[2]);
5617 /* Convert the result back to the original type, if we extended
5618 the first argument's width above. */
5619 if (expr->ts.kind < 4)
5620 se->expr = convert (type, se->expr);
5622 return;
5624 type = TREE_TYPE (args[0]);
5626 /* Evaluate arguments only once. */
5627 args[0] = gfc_evaluate_now (args[0], &se->pre);
5628 args[1] = gfc_evaluate_now (args[1], &se->pre);
5630 /* Rotate left if positive. */
5631 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
5633 /* Rotate right if negative. */
5634 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
5635 args[1]);
5636 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
5638 zero = build_int_cst (TREE_TYPE (args[1]), 0);
5639 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, args[1],
5640 zero);
5641 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
5643 /* Do nothing if shift == 0. */
5644 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, args[1],
5645 zero);
5646 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
5647 rrot);
5651 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
5652 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
5654 The conditional expression is necessary because the result of LEADZ(0)
5655 is defined, but the result of __builtin_clz(0) is undefined for most
5656 targets.
5658 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
5659 difference in bit size between the argument of LEADZ and the C int. */
5661 static void
5662 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
5664 tree arg;
5665 tree arg_type;
5666 tree cond;
5667 tree result_type;
5668 tree leadz;
5669 tree bit_size;
5670 tree tmp;
5671 tree func;
5672 int s, argsize;
5674 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5675 argsize = TYPE_PRECISION (TREE_TYPE (arg));
5677 /* Which variant of __builtin_clz* should we call? */
5678 if (argsize <= INT_TYPE_SIZE)
5680 arg_type = unsigned_type_node;
5681 func = builtin_decl_explicit (BUILT_IN_CLZ);
5683 else if (argsize <= LONG_TYPE_SIZE)
5685 arg_type = long_unsigned_type_node;
5686 func = builtin_decl_explicit (BUILT_IN_CLZL);
5688 else if (argsize <= LONG_LONG_TYPE_SIZE)
5690 arg_type = long_long_unsigned_type_node;
5691 func = builtin_decl_explicit (BUILT_IN_CLZLL);
5693 else
5695 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
5696 arg_type = gfc_build_uint_type (argsize);
5697 func = NULL_TREE;
5700 /* Convert the actual argument twice: first, to the unsigned type of the
5701 same size; then, to the proper argument type for the built-in
5702 function. But the return type is of the default INTEGER kind. */
5703 arg = fold_convert (gfc_build_uint_type (argsize), arg);
5704 arg = fold_convert (arg_type, arg);
5705 arg = gfc_evaluate_now (arg, &se->pre);
5706 result_type = gfc_get_int_type (gfc_default_integer_kind);
5708 /* Compute LEADZ for the case i .ne. 0. */
5709 if (func)
5711 s = TYPE_PRECISION (arg_type) - argsize;
5712 tmp = fold_convert (result_type,
5713 build_call_expr_loc (input_location, func,
5714 1, arg));
5715 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
5716 tmp, build_int_cst (result_type, s));
5718 else
5720 /* We end up here if the argument type is larger than 'long long'.
5721 We generate this code:
5723 if (x & (ULL_MAX << ULL_SIZE) != 0)
5724 return clzll ((unsigned long long) (x >> ULLSIZE));
5725 else
5726 return ULL_SIZE + clzll ((unsigned long long) x);
5727 where ULL_MAX is the largest value that a ULL_MAX can hold
5728 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
5729 is the bit-size of the long long type (64 in this example). */
5730 tree ullsize, ullmax, tmp1, tmp2, btmp;
5732 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
5733 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
5734 long_long_unsigned_type_node,
5735 build_int_cst (long_long_unsigned_type_node,
5736 0));
5738 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
5739 fold_convert (arg_type, ullmax), ullsize);
5740 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
5741 arg, cond);
5742 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5743 cond, build_int_cst (arg_type, 0));
5745 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
5746 arg, ullsize);
5747 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
5748 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
5749 tmp1 = fold_convert (result_type,
5750 build_call_expr_loc (input_location, btmp, 1, tmp1));
5752 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
5753 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
5754 tmp2 = fold_convert (result_type,
5755 build_call_expr_loc (input_location, btmp, 1, tmp2));
5756 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
5757 tmp2, ullsize);
5759 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
5760 cond, tmp1, tmp2);
5763 /* Build BIT_SIZE. */
5764 bit_size = build_int_cst (result_type, argsize);
5766 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5767 arg, build_int_cst (arg_type, 0));
5768 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
5769 bit_size, leadz);
5773 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
5775 The conditional expression is necessary because the result of TRAILZ(0)
5776 is defined, but the result of __builtin_ctz(0) is undefined for most
5777 targets. */
5779 static void
5780 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
5782 tree arg;
5783 tree arg_type;
5784 tree cond;
5785 tree result_type;
5786 tree trailz;
5787 tree bit_size;
5788 tree func;
5789 int argsize;
5791 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5792 argsize = TYPE_PRECISION (TREE_TYPE (arg));
5794 /* Which variant of __builtin_ctz* should we call? */
5795 if (argsize <= INT_TYPE_SIZE)
5797 arg_type = unsigned_type_node;
5798 func = builtin_decl_explicit (BUILT_IN_CTZ);
5800 else if (argsize <= LONG_TYPE_SIZE)
5802 arg_type = long_unsigned_type_node;
5803 func = builtin_decl_explicit (BUILT_IN_CTZL);
5805 else if (argsize <= LONG_LONG_TYPE_SIZE)
5807 arg_type = long_long_unsigned_type_node;
5808 func = builtin_decl_explicit (BUILT_IN_CTZLL);
5810 else
5812 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
5813 arg_type = gfc_build_uint_type (argsize);
5814 func = NULL_TREE;
5817 /* Convert the actual argument twice: first, to the unsigned type of the
5818 same size; then, to the proper argument type for the built-in
5819 function. But the return type is of the default INTEGER kind. */
5820 arg = fold_convert (gfc_build_uint_type (argsize), arg);
5821 arg = fold_convert (arg_type, arg);
5822 arg = gfc_evaluate_now (arg, &se->pre);
5823 result_type = gfc_get_int_type (gfc_default_integer_kind);
5825 /* Compute TRAILZ for the case i .ne. 0. */
5826 if (func)
5827 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
5828 func, 1, arg));
5829 else
5831 /* We end up here if the argument type is larger than 'long long'.
5832 We generate this code:
5834 if ((x & ULL_MAX) == 0)
5835 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
5836 else
5837 return ctzll ((unsigned long long) x);
5839 where ULL_MAX is the largest value that a ULL_MAX can hold
5840 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
5841 is the bit-size of the long long type (64 in this example). */
5842 tree ullsize, ullmax, tmp1, tmp2, btmp;
5844 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
5845 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
5846 long_long_unsigned_type_node,
5847 build_int_cst (long_long_unsigned_type_node, 0));
5849 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
5850 fold_convert (arg_type, ullmax));
5851 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, cond,
5852 build_int_cst (arg_type, 0));
5854 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
5855 arg, ullsize);
5856 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
5857 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
5858 tmp1 = fold_convert (result_type,
5859 build_call_expr_loc (input_location, btmp, 1, tmp1));
5860 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
5861 tmp1, ullsize);
5863 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
5864 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
5865 tmp2 = fold_convert (result_type,
5866 build_call_expr_loc (input_location, btmp, 1, tmp2));
5868 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
5869 cond, tmp1, tmp2);
5872 /* Build BIT_SIZE. */
5873 bit_size = build_int_cst (result_type, argsize);
5875 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5876 arg, build_int_cst (arg_type, 0));
5877 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
5878 bit_size, trailz);
5881 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
5882 for types larger than "long long", we call the long long built-in for
5883 the lower and higher bits and combine the result. */
5885 static void
5886 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
5888 tree arg;
5889 tree arg_type;
5890 tree result_type;
5891 tree func;
5892 int argsize;
5894 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5895 argsize = TYPE_PRECISION (TREE_TYPE (arg));
5896 result_type = gfc_get_int_type (gfc_default_integer_kind);
5898 /* Which variant of the builtin should we call? */
5899 if (argsize <= INT_TYPE_SIZE)
5901 arg_type = unsigned_type_node;
5902 func = builtin_decl_explicit (parity
5903 ? BUILT_IN_PARITY
5904 : BUILT_IN_POPCOUNT);
5906 else if (argsize <= LONG_TYPE_SIZE)
5908 arg_type = long_unsigned_type_node;
5909 func = builtin_decl_explicit (parity
5910 ? BUILT_IN_PARITYL
5911 : BUILT_IN_POPCOUNTL);
5913 else if (argsize <= LONG_LONG_TYPE_SIZE)
5915 arg_type = long_long_unsigned_type_node;
5916 func = builtin_decl_explicit (parity
5917 ? BUILT_IN_PARITYLL
5918 : BUILT_IN_POPCOUNTLL);
5920 else
5922 /* Our argument type is larger than 'long long', which mean none
5923 of the POPCOUNT builtins covers it. We thus call the 'long long'
5924 variant multiple times, and add the results. */
5925 tree utype, arg2, call1, call2;
5927 /* For now, we only cover the case where argsize is twice as large
5928 as 'long long'. */
5929 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
5931 func = builtin_decl_explicit (parity
5932 ? BUILT_IN_PARITYLL
5933 : BUILT_IN_POPCOUNTLL);
5935 /* Convert it to an integer, and store into a variable. */
5936 utype = gfc_build_uint_type (argsize);
5937 arg = fold_convert (utype, arg);
5938 arg = gfc_evaluate_now (arg, &se->pre);
5940 /* Call the builtin twice. */
5941 call1 = build_call_expr_loc (input_location, func, 1,
5942 fold_convert (long_long_unsigned_type_node,
5943 arg));
5945 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
5946 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
5947 call2 = build_call_expr_loc (input_location, func, 1,
5948 fold_convert (long_long_unsigned_type_node,
5949 arg2));
5951 /* Combine the results. */
5952 if (parity)
5953 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
5954 call1, call2);
5955 else
5956 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
5957 call1, call2);
5959 return;
5962 /* Convert the actual argument twice: first, to the unsigned type of the
5963 same size; then, to the proper argument type for the built-in
5964 function. */
5965 arg = fold_convert (gfc_build_uint_type (argsize), arg);
5966 arg = fold_convert (arg_type, arg);
5968 se->expr = fold_convert (result_type,
5969 build_call_expr_loc (input_location, func, 1, arg));
5973 /* Process an intrinsic with unspecified argument-types that has an optional
5974 argument (which could be of type character), e.g. EOSHIFT. For those, we
5975 need to append the string length of the optional argument if it is not
5976 present and the type is really character.
5977 primary specifies the position (starting at 1) of the non-optional argument
5978 specifying the type and optional gives the position of the optional
5979 argument in the arglist. */
5981 static void
5982 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
5983 unsigned primary, unsigned optional)
5985 gfc_actual_arglist* prim_arg;
5986 gfc_actual_arglist* opt_arg;
5987 unsigned cur_pos;
5988 gfc_actual_arglist* arg;
5989 gfc_symbol* sym;
5990 vec<tree, va_gc> *append_args;
5992 /* Find the two arguments given as position. */
5993 cur_pos = 0;
5994 prim_arg = NULL;
5995 opt_arg = NULL;
5996 for (arg = expr->value.function.actual; arg; arg = arg->next)
5998 ++cur_pos;
6000 if (cur_pos == primary)
6001 prim_arg = arg;
6002 if (cur_pos == optional)
6003 opt_arg = arg;
6005 if (cur_pos >= primary && cur_pos >= optional)
6006 break;
6008 gcc_assert (prim_arg);
6009 gcc_assert (prim_arg->expr);
6010 gcc_assert (opt_arg);
6012 /* If we do have type CHARACTER and the optional argument is really absent,
6013 append a dummy 0 as string length. */
6014 append_args = NULL;
6015 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
6017 tree dummy;
6019 dummy = build_int_cst (gfc_charlen_type_node, 0);
6020 vec_alloc (append_args, 1);
6021 append_args->quick_push (dummy);
6024 /* Build the call itself. */
6025 gcc_assert (!se->ignore_optional);
6026 sym = gfc_get_symbol_for_expr (expr, false);
6027 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
6028 append_args);
6029 gfc_free_symbol (sym);
6033 /* The length of a character string. */
6034 static void
6035 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
6037 tree len;
6038 tree type;
6039 tree decl;
6040 gfc_symbol *sym;
6041 gfc_se argse;
6042 gfc_expr *arg;
6044 gcc_assert (!se->ss);
6046 arg = expr->value.function.actual->expr;
6048 type = gfc_typenode_for_spec (&expr->ts);
6049 switch (arg->expr_type)
6051 case EXPR_CONSTANT:
6052 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
6053 break;
6055 case EXPR_ARRAY:
6056 /* Obtain the string length from the function used by
6057 trans-array.c(gfc_trans_array_constructor). */
6058 len = NULL_TREE;
6059 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
6060 break;
6062 case EXPR_VARIABLE:
6063 if (arg->ref == NULL
6064 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
6066 /* This doesn't catch all cases.
6067 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
6068 and the surrounding thread. */
6069 sym = arg->symtree->n.sym;
6070 decl = gfc_get_symbol_decl (sym);
6071 if (decl == current_function_decl && sym->attr.function
6072 && (sym->result == sym))
6073 decl = gfc_get_fake_result_decl (sym, 0);
6075 len = sym->ts.u.cl->backend_decl;
6076 gcc_assert (len);
6077 break;
6080 /* Fall through. */
6082 default:
6083 /* Anybody stupid enough to do this deserves inefficient code. */
6084 gfc_init_se (&argse, se);
6085 if (arg->rank == 0)
6086 gfc_conv_expr (&argse, arg);
6087 else
6088 gfc_conv_expr_descriptor (&argse, arg);
6089 gfc_add_block_to_block (&se->pre, &argse.pre);
6090 gfc_add_block_to_block (&se->post, &argse.post);
6091 len = argse.string_length;
6092 break;
6094 se->expr = convert (type, len);
6097 /* The length of a character string not including trailing blanks. */
6098 static void
6099 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
6101 int kind = expr->value.function.actual->expr->ts.kind;
6102 tree args[2], type, fndecl;
6104 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6105 type = gfc_typenode_for_spec (&expr->ts);
6107 if (kind == 1)
6108 fndecl = gfor_fndecl_string_len_trim;
6109 else if (kind == 4)
6110 fndecl = gfor_fndecl_string_len_trim_char4;
6111 else
6112 gcc_unreachable ();
6114 se->expr = build_call_expr_loc (input_location,
6115 fndecl, 2, args[0], args[1]);
6116 se->expr = convert (type, se->expr);
6120 /* Returns the starting position of a substring within a string. */
6122 static void
6123 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
6124 tree function)
6126 tree logical4_type_node = gfc_get_logical_type (4);
6127 tree type;
6128 tree fndecl;
6129 tree *args;
6130 unsigned int num_args;
6132 args = XALLOCAVEC (tree, 5);
6134 /* Get number of arguments; characters count double due to the
6135 string length argument. Kind= is not passed to the library
6136 and thus ignored. */
6137 if (expr->value.function.actual->next->next->expr == NULL)
6138 num_args = 4;
6139 else
6140 num_args = 5;
6142 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6143 type = gfc_typenode_for_spec (&expr->ts);
6145 if (num_args == 4)
6146 args[4] = build_int_cst (logical4_type_node, 0);
6147 else
6148 args[4] = convert (logical4_type_node, args[4]);
6150 fndecl = build_addr (function);
6151 se->expr = build_call_array_loc (input_location,
6152 TREE_TYPE (TREE_TYPE (function)), fndecl,
6153 5, args);
6154 se->expr = convert (type, se->expr);
6158 /* The ascii value for a single character. */
6159 static void
6160 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
6162 tree args[3], type, pchartype;
6163 int nargs;
6165 nargs = gfc_intrinsic_argument_list_length (expr);
6166 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6167 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
6168 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
6169 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
6170 type = gfc_typenode_for_spec (&expr->ts);
6172 se->expr = build_fold_indirect_ref_loc (input_location,
6173 args[1]);
6174 se->expr = convert (type, se->expr);
6178 /* Intrinsic ISNAN calls __builtin_isnan. */
6180 static void
6181 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
6183 tree arg;
6185 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6186 se->expr = build_call_expr_loc (input_location,
6187 builtin_decl_explicit (BUILT_IN_ISNAN),
6188 1, arg);
6189 STRIP_TYPE_NOPS (se->expr);
6190 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6194 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
6195 their argument against a constant integer value. */
6197 static void
6198 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
6200 tree arg;
6202 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6203 se->expr = fold_build2_loc (input_location, EQ_EXPR,
6204 gfc_typenode_for_spec (&expr->ts),
6205 arg, build_int_cst (TREE_TYPE (arg), value));
6210 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
6212 static void
6213 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
6215 tree tsource;
6216 tree fsource;
6217 tree mask;
6218 tree type;
6219 tree len, len2;
6220 tree *args;
6221 unsigned int num_args;
6223 num_args = gfc_intrinsic_argument_list_length (expr);
6224 args = XALLOCAVEC (tree, num_args);
6226 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6227 if (expr->ts.type != BT_CHARACTER)
6229 tsource = args[0];
6230 fsource = args[1];
6231 mask = args[2];
6233 else
6235 /* We do the same as in the non-character case, but the argument
6236 list is different because of the string length arguments. We
6237 also have to set the string length for the result. */
6238 len = args[0];
6239 tsource = args[1];
6240 len2 = args[2];
6241 fsource = args[3];
6242 mask = args[4];
6244 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
6245 &se->pre);
6246 se->string_length = len;
6248 type = TREE_TYPE (tsource);
6249 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
6250 fold_convert (type, fsource));
6254 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
6256 static void
6257 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
6259 tree args[3], mask, type;
6261 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6262 mask = gfc_evaluate_now (args[2], &se->pre);
6264 type = TREE_TYPE (args[0]);
6265 gcc_assert (TREE_TYPE (args[1]) == type);
6266 gcc_assert (TREE_TYPE (mask) == type);
6268 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
6269 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
6270 fold_build1_loc (input_location, BIT_NOT_EXPR,
6271 type, mask));
6272 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
6273 args[0], args[1]);
6277 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
6278 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
6280 static void
6281 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
6283 tree arg, allones, type, utype, res, cond, bitsize;
6284 int i;
6286 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6287 arg = gfc_evaluate_now (arg, &se->pre);
6289 type = gfc_get_int_type (expr->ts.kind);
6290 utype = unsigned_type_for (type);
6292 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
6293 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
6295 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
6296 build_int_cst (utype, 0));
6298 if (left)
6300 /* Left-justified mask. */
6301 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
6302 bitsize, arg);
6303 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6304 fold_convert (utype, res));
6306 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
6307 smaller than type width. */
6308 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
6309 build_int_cst (TREE_TYPE (arg), 0));
6310 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
6311 build_int_cst (utype, 0), res);
6313 else
6315 /* Right-justified mask. */
6316 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
6317 fold_convert (utype, arg));
6318 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
6320 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
6321 strictly smaller than type width. */
6322 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
6323 arg, bitsize);
6324 res = fold_build3_loc (input_location, COND_EXPR, utype,
6325 cond, allones, res);
6328 se->expr = fold_convert (type, res);
6332 /* FRACTION (s) is translated into:
6333 isfinite (s) ? frexp (s, &dummy_int) : NaN */
6334 static void
6335 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
6337 tree arg, type, tmp, res, frexp, cond;
6339 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6341 type = gfc_typenode_for_spec (&expr->ts);
6342 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6343 arg = gfc_evaluate_now (arg, &se->pre);
6345 cond = build_call_expr_loc (input_location,
6346 builtin_decl_explicit (BUILT_IN_ISFINITE),
6347 1, arg);
6349 tmp = gfc_create_var (integer_type_node, NULL);
6350 res = build_call_expr_loc (input_location, frexp, 2,
6351 fold_convert (type, arg),
6352 gfc_build_addr_expr (NULL_TREE, tmp));
6353 res = fold_convert (type, res);
6355 se->expr = fold_build3_loc (input_location, COND_EXPR, type,
6356 cond, res, gfc_build_nan (type, ""));
6360 /* NEAREST (s, dir) is translated into
6361 tmp = copysign (HUGE_VAL, dir);
6362 return nextafter (s, tmp);
6364 static void
6365 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
6367 tree args[2], type, tmp, nextafter, copysign, huge_val;
6369 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
6370 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
6372 type = gfc_typenode_for_spec (&expr->ts);
6373 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6375 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
6376 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
6377 fold_convert (type, args[1]));
6378 se->expr = build_call_expr_loc (input_location, nextafter, 2,
6379 fold_convert (type, args[0]), tmp);
6380 se->expr = fold_convert (type, se->expr);
6384 /* SPACING (s) is translated into
6385 int e;
6386 if (!isfinite (s))
6387 res = NaN;
6388 else if (s == 0)
6389 res = tiny;
6390 else
6392 frexp (s, &e);
6393 e = e - prec;
6394 e = MAX_EXPR (e, emin);
6395 res = scalbn (1., e);
6397 return res;
6399 where prec is the precision of s, gfc_real_kinds[k].digits,
6400 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
6401 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
6403 static void
6404 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
6406 tree arg, type, prec, emin, tiny, res, e;
6407 tree cond, nan, tmp, frexp, scalbn;
6408 int k;
6409 stmtblock_t block;
6411 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
6412 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
6413 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
6414 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
6416 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6417 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6419 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6420 arg = gfc_evaluate_now (arg, &se->pre);
6422 type = gfc_typenode_for_spec (&expr->ts);
6423 e = gfc_create_var (integer_type_node, NULL);
6424 res = gfc_create_var (type, NULL);
6427 /* Build the block for s /= 0. */
6428 gfc_start_block (&block);
6429 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
6430 gfc_build_addr_expr (NULL_TREE, e));
6431 gfc_add_expr_to_block (&block, tmp);
6433 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
6434 prec);
6435 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
6436 integer_type_node, tmp, emin));
6438 tmp = build_call_expr_loc (input_location, scalbn, 2,
6439 build_real_from_int_cst (type, integer_one_node), e);
6440 gfc_add_modify (&block, res, tmp);
6442 /* Finish by building the IF statement for value zero. */
6443 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
6444 build_real_from_int_cst (type, integer_zero_node));
6445 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
6446 gfc_finish_block (&block));
6448 /* And deal with infinities and NaNs. */
6449 cond = build_call_expr_loc (input_location,
6450 builtin_decl_explicit (BUILT_IN_ISFINITE),
6451 1, arg);
6452 nan = gfc_build_nan (type, "");
6453 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
6455 gfc_add_expr_to_block (&se->pre, tmp);
6456 se->expr = res;
6460 /* RRSPACING (s) is translated into
6461 int e;
6462 real x;
6463 x = fabs (s);
6464 if (isfinite (x))
6466 if (x != 0)
6468 frexp (s, &e);
6469 x = scalbn (x, precision - e);
6472 else
6473 x = NaN;
6474 return x;
6476 where precision is gfc_real_kinds[k].digits. */
6478 static void
6479 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
6481 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
6482 int prec, k;
6483 stmtblock_t block;
6485 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
6486 prec = gfc_real_kinds[k].digits;
6488 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6489 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6490 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
6492 type = gfc_typenode_for_spec (&expr->ts);
6493 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6494 arg = gfc_evaluate_now (arg, &se->pre);
6496 e = gfc_create_var (integer_type_node, NULL);
6497 x = gfc_create_var (type, NULL);
6498 gfc_add_modify (&se->pre, x,
6499 build_call_expr_loc (input_location, fabs, 1, arg));
6502 gfc_start_block (&block);
6503 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
6504 gfc_build_addr_expr (NULL_TREE, e));
6505 gfc_add_expr_to_block (&block, tmp);
6507 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
6508 build_int_cst (integer_type_node, prec), e);
6509 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
6510 gfc_add_modify (&block, x, tmp);
6511 stmt = gfc_finish_block (&block);
6513 /* if (x != 0) */
6514 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, x,
6515 build_real_from_int_cst (type, integer_zero_node));
6516 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
6518 /* And deal with infinities and NaNs. */
6519 cond = build_call_expr_loc (input_location,
6520 builtin_decl_explicit (BUILT_IN_ISFINITE),
6521 1, x);
6522 nan = gfc_build_nan (type, "");
6523 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
6525 gfc_add_expr_to_block (&se->pre, tmp);
6526 se->expr = fold_convert (type, x);
6530 /* SCALE (s, i) is translated into scalbn (s, i). */
6531 static void
6532 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
6534 tree args[2], type, scalbn;
6536 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6538 type = gfc_typenode_for_spec (&expr->ts);
6539 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6540 se->expr = build_call_expr_loc (input_location, scalbn, 2,
6541 fold_convert (type, args[0]),
6542 fold_convert (integer_type_node, args[1]));
6543 se->expr = fold_convert (type, se->expr);
6547 /* SET_EXPONENT (s, i) is translated into
6548 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
6549 static void
6550 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
6552 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
6554 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
6555 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
6557 type = gfc_typenode_for_spec (&expr->ts);
6558 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6559 args[0] = gfc_evaluate_now (args[0], &se->pre);
6561 tmp = gfc_create_var (integer_type_node, NULL);
6562 tmp = build_call_expr_loc (input_location, frexp, 2,
6563 fold_convert (type, args[0]),
6564 gfc_build_addr_expr (NULL_TREE, tmp));
6565 res = build_call_expr_loc (input_location, scalbn, 2, tmp,
6566 fold_convert (integer_type_node, args[1]));
6567 res = fold_convert (type, res);
6569 /* Call to isfinite */
6570 cond = build_call_expr_loc (input_location,
6571 builtin_decl_explicit (BUILT_IN_ISFINITE),
6572 1, args[0]);
6573 nan = gfc_build_nan (type, "");
6575 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
6576 res, nan);
6580 static void
6581 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
6583 gfc_actual_arglist *actual;
6584 tree arg1;
6585 tree type;
6586 tree fncall0;
6587 tree fncall1;
6588 gfc_se argse;
6590 gfc_init_se (&argse, NULL);
6591 actual = expr->value.function.actual;
6593 if (actual->expr->ts.type == BT_CLASS)
6594 gfc_add_class_array_ref (actual->expr);
6596 argse.data_not_needed = 1;
6597 if (gfc_is_alloc_class_array_function (actual->expr))
6599 /* For functions that return a class array conv_expr_descriptor is not
6600 able to get the descriptor right. Therefore this special case. */
6601 gfc_conv_expr_reference (&argse, actual->expr);
6602 argse.expr = gfc_build_addr_expr (NULL_TREE,
6603 gfc_class_data_get (argse.expr));
6605 else
6607 argse.want_pointer = 1;
6608 gfc_conv_expr_descriptor (&argse, actual->expr);
6610 gfc_add_block_to_block (&se->pre, &argse.pre);
6611 gfc_add_block_to_block (&se->post, &argse.post);
6612 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
6614 /* Build the call to size0. */
6615 fncall0 = build_call_expr_loc (input_location,
6616 gfor_fndecl_size0, 1, arg1);
6618 actual = actual->next;
6620 if (actual->expr)
6622 gfc_init_se (&argse, NULL);
6623 gfc_conv_expr_type (&argse, actual->expr,
6624 gfc_array_index_type);
6625 gfc_add_block_to_block (&se->pre, &argse.pre);
6627 /* Unusually, for an intrinsic, size does not exclude
6628 an optional arg2, so we must test for it. */
6629 if (actual->expr->expr_type == EXPR_VARIABLE
6630 && actual->expr->symtree->n.sym->attr.dummy
6631 && actual->expr->symtree->n.sym->attr.optional)
6633 tree tmp;
6634 /* Build the call to size1. */
6635 fncall1 = build_call_expr_loc (input_location,
6636 gfor_fndecl_size1, 2,
6637 arg1, argse.expr);
6639 gfc_init_se (&argse, NULL);
6640 argse.want_pointer = 1;
6641 argse.data_not_needed = 1;
6642 gfc_conv_expr (&argse, actual->expr);
6643 gfc_add_block_to_block (&se->pre, &argse.pre);
6644 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6645 argse.expr, null_pointer_node);
6646 tmp = gfc_evaluate_now (tmp, &se->pre);
6647 se->expr = fold_build3_loc (input_location, COND_EXPR,
6648 pvoid_type_node, tmp, fncall1, fncall0);
6650 else
6652 se->expr = NULL_TREE;
6653 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
6654 gfc_array_index_type,
6655 argse.expr, gfc_index_one_node);
6658 else if (expr->value.function.actual->expr->rank == 1)
6660 argse.expr = gfc_index_zero_node;
6661 se->expr = NULL_TREE;
6663 else
6664 se->expr = fncall0;
6666 if (se->expr == NULL_TREE)
6668 tree ubound, lbound;
6670 arg1 = build_fold_indirect_ref_loc (input_location,
6671 arg1);
6672 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
6673 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
6674 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
6675 gfc_array_index_type, ubound, lbound);
6676 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
6677 gfc_array_index_type,
6678 se->expr, gfc_index_one_node);
6679 se->expr = fold_build2_loc (input_location, MAX_EXPR,
6680 gfc_array_index_type, se->expr,
6681 gfc_index_zero_node);
6684 type = gfc_typenode_for_spec (&expr->ts);
6685 se->expr = convert (type, se->expr);
6689 /* Helper function to compute the size of a character variable,
6690 excluding the terminating null characters. The result has
6691 gfc_array_index_type type. */
6693 tree
6694 size_of_string_in_bytes (int kind, tree string_length)
6696 tree bytesize;
6697 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
6699 bytesize = build_int_cst (gfc_array_index_type,
6700 gfc_character_kinds[i].bit_size / 8);
6702 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6703 bytesize,
6704 fold_convert (gfc_array_index_type, string_length));
6708 static void
6709 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
6711 gfc_expr *arg;
6712 gfc_se argse;
6713 tree source_bytes;
6714 tree tmp;
6715 tree lower;
6716 tree upper;
6717 tree byte_size;
6718 int n;
6720 gfc_init_se (&argse, NULL);
6721 arg = expr->value.function.actual->expr;
6723 if (arg->rank || arg->ts.type == BT_ASSUMED)
6724 gfc_conv_expr_descriptor (&argse, arg);
6725 else
6726 gfc_conv_expr_reference (&argse, arg);
6728 if (arg->ts.type == BT_ASSUMED)
6730 /* This only works if an array descriptor has been passed; thus, extract
6731 the size from the descriptor. */
6732 gcc_assert (TYPE_PRECISION (gfc_array_index_type)
6733 == TYPE_PRECISION (size_type_node));
6734 tmp = arg->symtree->n.sym->backend_decl;
6735 tmp = DECL_LANG_SPECIFIC (tmp)
6736 && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
6737 ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
6738 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
6739 tmp = build_fold_indirect_ref_loc (input_location, tmp);
6740 tmp = fold_convert (size_type_node, gfc_conv_descriptor_dtype (tmp));
6741 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, TREE_TYPE (tmp), tmp,
6742 build_int_cst (TREE_TYPE (tmp),
6743 GFC_DTYPE_SIZE_SHIFT));
6744 byte_size = fold_convert (gfc_array_index_type, tmp);
6746 else if (arg->ts.type == BT_CLASS)
6748 /* Conv_expr_descriptor returns a component_ref to _data component of the
6749 class object. The class object may be a non-pointer object, e.g.
6750 located on the stack, or a memory location pointed to, e.g. a
6751 parameter, i.e., an indirect_ref. */
6752 if (arg->rank < 0
6753 || (arg->rank > 0 && !VAR_P (argse.expr)
6754 && ((INDIRECT_REF_P (TREE_OPERAND (argse.expr, 0))
6755 && GFC_DECL_CLASS (TREE_OPERAND (
6756 TREE_OPERAND (argse.expr, 0), 0)))
6757 || GFC_DECL_CLASS (TREE_OPERAND (argse.expr, 0)))))
6758 byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
6759 else if (arg->rank > 0
6760 || (arg->rank == 0
6761 && arg->ref && arg->ref->type == REF_COMPONENT))
6762 /* The scalarizer added an additional temp. To get the class' vptr
6763 one has to look at the original backend_decl. */
6764 byte_size = gfc_class_vtab_size_get (
6765 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
6766 else
6767 byte_size = gfc_class_vtab_size_get (argse.expr);
6769 else
6771 if (arg->ts.type == BT_CHARACTER)
6772 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
6773 else
6775 if (arg->rank == 0)
6776 byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
6777 argse.expr));
6778 else
6779 byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
6780 byte_size = fold_convert (gfc_array_index_type,
6781 size_in_bytes (byte_size));
6785 if (arg->rank == 0)
6786 se->expr = byte_size;
6787 else
6789 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
6790 gfc_add_modify (&argse.pre, source_bytes, byte_size);
6792 if (arg->rank == -1)
6794 tree cond, loop_var, exit_label;
6795 stmtblock_t body;
6797 tmp = fold_convert (gfc_array_index_type,
6798 gfc_conv_descriptor_rank (argse.expr));
6799 loop_var = gfc_create_var (gfc_array_index_type, "i");
6800 gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
6801 exit_label = gfc_build_label_decl (NULL_TREE);
6803 /* Create loop:
6804 for (;;)
6806 if (i >= rank)
6807 goto exit;
6808 source_bytes = source_bytes * array.dim[i].extent;
6809 i = i + 1;
6811 exit: */
6812 gfc_start_block (&body);
6813 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
6814 loop_var, tmp);
6815 tmp = build1_v (GOTO_EXPR, exit_label);
6816 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
6817 cond, tmp, build_empty_stmt (input_location));
6818 gfc_add_expr_to_block (&body, tmp);
6820 lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
6821 upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
6822 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
6823 tmp = fold_build2_loc (input_location, MULT_EXPR,
6824 gfc_array_index_type, tmp, source_bytes);
6825 gfc_add_modify (&body, source_bytes, tmp);
6827 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6828 gfc_array_index_type, loop_var,
6829 gfc_index_one_node);
6830 gfc_add_modify_loc (input_location, &body, loop_var, tmp);
6832 tmp = gfc_finish_block (&body);
6834 tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
6835 tmp);
6836 gfc_add_expr_to_block (&argse.pre, tmp);
6838 tmp = build1_v (LABEL_EXPR, exit_label);
6839 gfc_add_expr_to_block (&argse.pre, tmp);
6841 else
6843 /* Obtain the size of the array in bytes. */
6844 for (n = 0; n < arg->rank; n++)
6846 tree idx;
6847 idx = gfc_rank_cst[n];
6848 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
6849 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
6850 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
6851 tmp = fold_build2_loc (input_location, MULT_EXPR,
6852 gfc_array_index_type, tmp, source_bytes);
6853 gfc_add_modify (&argse.pre, source_bytes, tmp);
6856 se->expr = source_bytes;
6859 gfc_add_block_to_block (&se->pre, &argse.pre);
6863 static void
6864 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
6866 gfc_expr *arg;
6867 gfc_se argse;
6868 tree type, result_type, tmp;
6870 arg = expr->value.function.actual->expr;
6872 gfc_init_se (&argse, NULL);
6873 result_type = gfc_get_int_type (expr->ts.kind);
6875 if (arg->rank == 0)
6877 if (arg->ts.type == BT_CLASS)
6879 gfc_add_vptr_component (arg);
6880 gfc_add_size_component (arg);
6881 gfc_conv_expr (&argse, arg);
6882 tmp = fold_convert (result_type, argse.expr);
6883 goto done;
6886 gfc_conv_expr_reference (&argse, arg);
6887 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
6888 argse.expr));
6890 else
6892 argse.want_pointer = 0;
6893 gfc_conv_expr_descriptor (&argse, arg);
6894 if (arg->ts.type == BT_CLASS)
6896 if (arg->rank > 0)
6897 tmp = gfc_class_vtab_size_get (
6898 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
6899 else
6900 tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
6901 tmp = fold_convert (result_type, tmp);
6902 goto done;
6904 type = gfc_get_element_type (TREE_TYPE (argse.expr));
6907 /* Obtain the argument's word length. */
6908 if (arg->ts.type == BT_CHARACTER)
6909 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
6910 else
6911 tmp = size_in_bytes (type);
6912 tmp = fold_convert (result_type, tmp);
6914 done:
6915 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
6916 build_int_cst (result_type, BITS_PER_UNIT));
6917 gfc_add_block_to_block (&se->pre, &argse.pre);
6921 /* Intrinsic string comparison functions. */
6923 static void
6924 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
6926 tree args[4];
6928 gfc_conv_intrinsic_function_args (se, expr, args, 4);
6930 se->expr
6931 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
6932 expr->value.function.actual->expr->ts.kind,
6933 op);
6934 se->expr = fold_build2_loc (input_location, op,
6935 gfc_typenode_for_spec (&expr->ts), se->expr,
6936 build_int_cst (TREE_TYPE (se->expr), 0));
6939 /* Generate a call to the adjustl/adjustr library function. */
6940 static void
6941 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
6943 tree args[3];
6944 tree len;
6945 tree type;
6946 tree var;
6947 tree tmp;
6949 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
6950 len = args[1];
6952 type = TREE_TYPE (args[2]);
6953 var = gfc_conv_string_tmp (se, type, len);
6954 args[0] = var;
6956 tmp = build_call_expr_loc (input_location,
6957 fndecl, 3, args[0], args[1], args[2]);
6958 gfc_add_expr_to_block (&se->pre, tmp);
6959 se->expr = var;
6960 se->string_length = len;
6964 /* Generate code for the TRANSFER intrinsic:
6965 For scalar results:
6966 DEST = TRANSFER (SOURCE, MOLD)
6967 where:
6968 typeof<DEST> = typeof<MOLD>
6969 and:
6970 MOLD is scalar.
6972 For array results:
6973 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
6974 where:
6975 typeof<DEST> = typeof<MOLD>
6976 and:
6977 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
6978 sizeof (DEST(0) * SIZE). */
6979 static void
6980 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
6982 tree tmp;
6983 tree tmpdecl;
6984 tree ptr;
6985 tree extent;
6986 tree source;
6987 tree source_type;
6988 tree source_bytes;
6989 tree mold_type;
6990 tree dest_word_len;
6991 tree size_words;
6992 tree size_bytes;
6993 tree upper;
6994 tree lower;
6995 tree stmt;
6996 gfc_actual_arglist *arg;
6997 gfc_se argse;
6998 gfc_array_info *info;
6999 stmtblock_t block;
7000 int n;
7001 bool scalar_mold;
7002 gfc_expr *source_expr, *mold_expr;
7004 info = NULL;
7005 if (se->loop)
7006 info = &se->ss->info->data.array;
7008 /* Convert SOURCE. The output from this stage is:-
7009 source_bytes = length of the source in bytes
7010 source = pointer to the source data. */
7011 arg = expr->value.function.actual;
7012 source_expr = arg->expr;
7014 /* Ensure double transfer through LOGICAL preserves all
7015 the needed bits. */
7016 if (arg->expr->expr_type == EXPR_FUNCTION
7017 && arg->expr->value.function.esym == NULL
7018 && arg->expr->value.function.isym != NULL
7019 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
7020 && arg->expr->ts.type == BT_LOGICAL
7021 && expr->ts.type != arg->expr->ts.type)
7022 arg->expr->value.function.name = "__transfer_in_transfer";
7024 gfc_init_se (&argse, NULL);
7026 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
7028 /* Obtain the pointer to source and the length of source in bytes. */
7029 if (arg->expr->rank == 0)
7031 gfc_conv_expr_reference (&argse, arg->expr);
7032 if (arg->expr->ts.type == BT_CLASS)
7033 source = gfc_class_data_get (argse.expr);
7034 else
7035 source = argse.expr;
7037 /* Obtain the source word length. */
7038 switch (arg->expr->ts.type)
7040 case BT_CHARACTER:
7041 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7042 argse.string_length);
7043 break;
7044 case BT_CLASS:
7045 tmp = gfc_class_vtab_size_get (argse.expr);
7046 break;
7047 default:
7048 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7049 source));
7050 tmp = fold_convert (gfc_array_index_type,
7051 size_in_bytes (source_type));
7052 break;
7055 else
7057 argse.want_pointer = 0;
7058 gfc_conv_expr_descriptor (&argse, arg->expr);
7059 source = gfc_conv_descriptor_data_get (argse.expr);
7060 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7062 /* Repack the source if not simply contiguous. */
7063 if (!gfc_is_simply_contiguous (arg->expr, false, true))
7065 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
7067 if (warn_array_temporaries)
7068 gfc_warning (OPT_Warray_temporaries,
7069 "Creating array temporary at %L", &expr->where);
7071 source = build_call_expr_loc (input_location,
7072 gfor_fndecl_in_pack, 1, tmp);
7073 source = gfc_evaluate_now (source, &argse.pre);
7075 /* Free the temporary. */
7076 gfc_start_block (&block);
7077 tmp = gfc_call_free (source);
7078 gfc_add_expr_to_block (&block, tmp);
7079 stmt = gfc_finish_block (&block);
7081 /* Clean up if it was repacked. */
7082 gfc_init_block (&block);
7083 tmp = gfc_conv_array_data (argse.expr);
7084 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7085 source, tmp);
7086 tmp = build3_v (COND_EXPR, tmp, stmt,
7087 build_empty_stmt (input_location));
7088 gfc_add_expr_to_block (&block, tmp);
7089 gfc_add_block_to_block (&block, &se->post);
7090 gfc_init_block (&se->post);
7091 gfc_add_block_to_block (&se->post, &block);
7094 /* Obtain the source word length. */
7095 if (arg->expr->ts.type == BT_CHARACTER)
7096 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
7097 argse.string_length);
7098 else
7099 tmp = fold_convert (gfc_array_index_type,
7100 size_in_bytes (source_type));
7102 /* Obtain the size of the array in bytes. */
7103 extent = gfc_create_var (gfc_array_index_type, NULL);
7104 for (n = 0; n < arg->expr->rank; n++)
7106 tree idx;
7107 idx = gfc_rank_cst[n];
7108 gfc_add_modify (&argse.pre, source_bytes, tmp);
7109 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
7110 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
7111 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7112 gfc_array_index_type, upper, lower);
7113 gfc_add_modify (&argse.pre, extent, tmp);
7114 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7115 gfc_array_index_type, extent,
7116 gfc_index_one_node);
7117 tmp = fold_build2_loc (input_location, MULT_EXPR,
7118 gfc_array_index_type, tmp, source_bytes);
7122 gfc_add_modify (&argse.pre, source_bytes, tmp);
7123 gfc_add_block_to_block (&se->pre, &argse.pre);
7124 gfc_add_block_to_block (&se->post, &argse.post);
7126 /* Now convert MOLD. The outputs are:
7127 mold_type = the TREE type of MOLD
7128 dest_word_len = destination word length in bytes. */
7129 arg = arg->next;
7130 mold_expr = arg->expr;
7132 gfc_init_se (&argse, NULL);
7134 scalar_mold = arg->expr->rank == 0;
7136 if (arg->expr->rank == 0)
7138 gfc_conv_expr_reference (&argse, arg->expr);
7139 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
7140 argse.expr));
7142 else
7144 gfc_init_se (&argse, NULL);
7145 argse.want_pointer = 0;
7146 gfc_conv_expr_descriptor (&argse, arg->expr);
7147 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
7150 gfc_add_block_to_block (&se->pre, &argse.pre);
7151 gfc_add_block_to_block (&se->post, &argse.post);
7153 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
7155 /* If this TRANSFER is nested in another TRANSFER, use a type
7156 that preserves all bits. */
7157 if (arg->expr->ts.type == BT_LOGICAL)
7158 mold_type = gfc_get_int_type (arg->expr->ts.kind);
7161 /* Obtain the destination word length. */
7162 switch (arg->expr->ts.type)
7164 case BT_CHARACTER:
7165 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
7166 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
7167 break;
7168 case BT_CLASS:
7169 tmp = gfc_class_vtab_size_get (argse.expr);
7170 break;
7171 default:
7172 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
7173 break;
7175 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
7176 gfc_add_modify (&se->pre, dest_word_len, tmp);
7178 /* Finally convert SIZE, if it is present. */
7179 arg = arg->next;
7180 size_words = gfc_create_var (gfc_array_index_type, NULL);
7182 if (arg->expr)
7184 gfc_init_se (&argse, NULL);
7185 gfc_conv_expr_reference (&argse, arg->expr);
7186 tmp = convert (gfc_array_index_type,
7187 build_fold_indirect_ref_loc (input_location,
7188 argse.expr));
7189 gfc_add_block_to_block (&se->pre, &argse.pre);
7190 gfc_add_block_to_block (&se->post, &argse.post);
7192 else
7193 tmp = NULL_TREE;
7195 /* Separate array and scalar results. */
7196 if (scalar_mold && tmp == NULL_TREE)
7197 goto scalar_transfer;
7199 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
7200 if (tmp != NULL_TREE)
7201 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7202 tmp, dest_word_len);
7203 else
7204 tmp = source_bytes;
7206 gfc_add_modify (&se->pre, size_bytes, tmp);
7207 gfc_add_modify (&se->pre, size_words,
7208 fold_build2_loc (input_location, CEIL_DIV_EXPR,
7209 gfc_array_index_type,
7210 size_bytes, dest_word_len));
7212 /* Evaluate the bounds of the result. If the loop range exists, we have
7213 to check if it is too large. If so, we modify loop->to be consistent
7214 with min(size, size(source)). Otherwise, size is made consistent with
7215 the loop range, so that the right number of bytes is transferred.*/
7216 n = se->loop->order[0];
7217 if (se->loop->to[n] != NULL_TREE)
7219 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7220 se->loop->to[n], se->loop->from[n]);
7221 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7222 tmp, gfc_index_one_node);
7223 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7224 tmp, size_words);
7225 gfc_add_modify (&se->pre, size_words, tmp);
7226 gfc_add_modify (&se->pre, size_bytes,
7227 fold_build2_loc (input_location, MULT_EXPR,
7228 gfc_array_index_type,
7229 size_words, dest_word_len));
7230 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7231 size_words, se->loop->from[n]);
7232 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7233 upper, gfc_index_one_node);
7235 else
7237 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7238 size_words, gfc_index_one_node);
7239 se->loop->from[n] = gfc_index_zero_node;
7242 se->loop->to[n] = upper;
7244 /* Build a destination descriptor, using the pointer, source, as the
7245 data field. */
7246 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
7247 NULL_TREE, false, true, false, &expr->where);
7249 /* Cast the pointer to the result. */
7250 tmp = gfc_conv_descriptor_data_get (info->descriptor);
7251 tmp = fold_convert (pvoid_type_node, tmp);
7253 /* Use memcpy to do the transfer. */
7255 = build_call_expr_loc (input_location,
7256 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
7257 fold_convert (pvoid_type_node, source),
7258 fold_convert (size_type_node,
7259 fold_build2_loc (input_location,
7260 MIN_EXPR,
7261 gfc_array_index_type,
7262 size_bytes,
7263 source_bytes)));
7264 gfc_add_expr_to_block (&se->pre, tmp);
7266 se->expr = info->descriptor;
7267 if (expr->ts.type == BT_CHARACTER)
7268 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7270 return;
7272 /* Deal with scalar results. */
7273 scalar_transfer:
7274 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
7275 dest_word_len, source_bytes);
7276 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
7277 extent, gfc_index_zero_node);
7279 if (expr->ts.type == BT_CHARACTER)
7281 tree direct, indirect, free;
7283 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
7284 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
7285 "transfer");
7287 /* If source is longer than the destination, use a pointer to
7288 the source directly. */
7289 gfc_init_block (&block);
7290 gfc_add_modify (&block, tmpdecl, ptr);
7291 direct = gfc_finish_block (&block);
7293 /* Otherwise, allocate a string with the length of the destination
7294 and copy the source into it. */
7295 gfc_init_block (&block);
7296 tmp = gfc_get_pchar_type (expr->ts.kind);
7297 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
7298 gfc_add_modify (&block, tmpdecl,
7299 fold_convert (TREE_TYPE (ptr), tmp));
7300 tmp = build_call_expr_loc (input_location,
7301 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7302 fold_convert (pvoid_type_node, tmpdecl),
7303 fold_convert (pvoid_type_node, ptr),
7304 fold_convert (size_type_node, extent));
7305 gfc_add_expr_to_block (&block, tmp);
7306 indirect = gfc_finish_block (&block);
7308 /* Wrap it up with the condition. */
7309 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
7310 dest_word_len, source_bytes);
7311 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
7312 gfc_add_expr_to_block (&se->pre, tmp);
7314 /* Free the temporary string, if necessary. */
7315 free = gfc_call_free (tmpdecl);
7316 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
7317 dest_word_len, source_bytes);
7318 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
7319 gfc_add_expr_to_block (&se->post, tmp);
7321 se->expr = tmpdecl;
7322 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
7324 else
7326 tmpdecl = gfc_create_var (mold_type, "transfer");
7328 ptr = convert (build_pointer_type (mold_type), source);
7330 /* For CLASS results, allocate the needed memory first. */
7331 if (mold_expr->ts.type == BT_CLASS)
7333 tree cdata;
7334 cdata = gfc_class_data_get (tmpdecl);
7335 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
7336 gfc_add_modify (&se->pre, cdata, tmp);
7339 /* Use memcpy to do the transfer. */
7340 if (mold_expr->ts.type == BT_CLASS)
7341 tmp = gfc_class_data_get (tmpdecl);
7342 else
7343 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
7345 tmp = build_call_expr_loc (input_location,
7346 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
7347 fold_convert (pvoid_type_node, tmp),
7348 fold_convert (pvoid_type_node, ptr),
7349 fold_convert (size_type_node, extent));
7350 gfc_add_expr_to_block (&se->pre, tmp);
7352 /* For CLASS results, set the _vptr. */
7353 if (mold_expr->ts.type == BT_CLASS)
7355 tree vptr;
7356 gfc_symbol *vtab;
7357 vptr = gfc_class_vptr_get (tmpdecl);
7358 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
7359 gcc_assert (vtab);
7360 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7361 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
7364 se->expr = tmpdecl;
7369 /* Generate a call to caf_is_present. */
7371 static tree
7372 trans_caf_is_present (gfc_se *se, gfc_expr *expr)
7374 tree caf_reference, caf_decl, token, image_index;
7376 /* Compile the reference chain. */
7377 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
7378 gcc_assert (caf_reference != NULL_TREE);
7380 caf_decl = gfc_get_tree_for_caf_expr (expr);
7381 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
7382 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
7383 image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
7384 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
7385 expr);
7387 return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
7388 3, token, image_index, caf_reference);
7392 /* Test whether this ref-chain refs this image only. */
7394 static bool
7395 caf_this_image_ref (gfc_ref *ref)
7397 for ( ; ref; ref = ref->next)
7398 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
7399 return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
7401 return false;
7405 /* Generate code for the ALLOCATED intrinsic.
7406 Generate inline code that directly check the address of the argument. */
7408 static void
7409 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
7411 gfc_actual_arglist *arg1;
7412 gfc_se arg1se;
7413 tree tmp;
7414 symbol_attribute caf_attr;
7416 gfc_init_se (&arg1se, NULL);
7417 arg1 = expr->value.function.actual;
7419 if (arg1->expr->ts.type == BT_CLASS)
7421 /* Make sure that class array expressions have both a _data
7422 component reference and an array reference.... */
7423 if (CLASS_DATA (arg1->expr)->attr.dimension)
7424 gfc_add_class_array_ref (arg1->expr);
7425 /* .... whilst scalars only need the _data component. */
7426 else
7427 gfc_add_data_component (arg1->expr);
7430 /* When arg1 references an allocatable component in a coarray, then call
7431 the caf-library function caf_is_present (). */
7432 if (flag_coarray == GFC_FCOARRAY_LIB && arg1->expr->expr_type == EXPR_FUNCTION
7433 && arg1->expr->value.function.isym
7434 && arg1->expr->value.function.isym->id == GFC_ISYM_CAF_GET)
7435 caf_attr = gfc_caf_attr (arg1->expr->value.function.actual->expr);
7436 else
7437 gfc_clear_attr (&caf_attr);
7438 if (flag_coarray == GFC_FCOARRAY_LIB && caf_attr.codimension
7439 && !caf_this_image_ref (arg1->expr->value.function.actual->expr->ref))
7440 tmp = trans_caf_is_present (se, arg1->expr->value.function.actual->expr);
7441 else
7443 if (arg1->expr->rank == 0)
7445 /* Allocatable scalar. */
7446 arg1se.want_pointer = 1;
7447 gfc_conv_expr (&arg1se, arg1->expr);
7448 tmp = arg1se.expr;
7450 else
7452 /* Allocatable array. */
7453 arg1se.descriptor_only = 1;
7454 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7455 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
7458 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
7459 fold_convert (TREE_TYPE (tmp), null_pointer_node));
7461 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
7465 /* Generate code for the ASSOCIATED intrinsic.
7466 If both POINTER and TARGET are arrays, generate a call to library function
7467 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
7468 In other cases, generate inline code that directly compare the address of
7469 POINTER with the address of TARGET. */
7471 static void
7472 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
7474 gfc_actual_arglist *arg1;
7475 gfc_actual_arglist *arg2;
7476 gfc_se arg1se;
7477 gfc_se arg2se;
7478 tree tmp2;
7479 tree tmp;
7480 tree nonzero_charlen;
7481 tree nonzero_arraylen;
7482 gfc_ss *ss;
7483 bool scalar;
7485 gfc_init_se (&arg1se, NULL);
7486 gfc_init_se (&arg2se, NULL);
7487 arg1 = expr->value.function.actual;
7488 arg2 = arg1->next;
7490 /* Check whether the expression is a scalar or not; we cannot use
7491 arg1->expr->rank as it can be nonzero for proc pointers. */
7492 ss = gfc_walk_expr (arg1->expr);
7493 scalar = ss == gfc_ss_terminator;
7494 if (!scalar)
7495 gfc_free_ss_chain (ss);
7497 if (!arg2->expr)
7499 /* No optional target. */
7500 if (scalar)
7502 /* A pointer to a scalar. */
7503 arg1se.want_pointer = 1;
7504 gfc_conv_expr (&arg1se, arg1->expr);
7505 if (arg1->expr->symtree->n.sym->attr.proc_pointer
7506 && arg1->expr->symtree->n.sym->attr.dummy)
7507 arg1se.expr = build_fold_indirect_ref_loc (input_location,
7508 arg1se.expr);
7509 if (arg1->expr->ts.type == BT_CLASS)
7511 tmp2 = gfc_class_data_get (arg1se.expr);
7512 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
7513 tmp2 = gfc_conv_descriptor_data_get (tmp2);
7515 else
7516 tmp2 = arg1se.expr;
7518 else
7520 /* A pointer to an array. */
7521 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7522 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
7524 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7525 gfc_add_block_to_block (&se->post, &arg1se.post);
7526 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp2,
7527 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
7528 se->expr = tmp;
7530 else
7532 /* An optional target. */
7533 if (arg2->expr->ts.type == BT_CLASS)
7534 gfc_add_data_component (arg2->expr);
7536 nonzero_charlen = NULL_TREE;
7537 if (arg1->expr->ts.type == BT_CHARACTER)
7538 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
7539 boolean_type_node,
7540 arg1->expr->ts.u.cl->backend_decl,
7541 integer_zero_node);
7542 if (scalar)
7544 /* A pointer to a scalar. */
7545 arg1se.want_pointer = 1;
7546 gfc_conv_expr (&arg1se, arg1->expr);
7547 if (arg1->expr->symtree->n.sym->attr.proc_pointer
7548 && arg1->expr->symtree->n.sym->attr.dummy)
7549 arg1se.expr = build_fold_indirect_ref_loc (input_location,
7550 arg1se.expr);
7551 if (arg1->expr->ts.type == BT_CLASS)
7552 arg1se.expr = gfc_class_data_get (arg1se.expr);
7554 arg2se.want_pointer = 1;
7555 gfc_conv_expr (&arg2se, arg2->expr);
7556 if (arg2->expr->symtree->n.sym->attr.proc_pointer
7557 && arg2->expr->symtree->n.sym->attr.dummy)
7558 arg2se.expr = build_fold_indirect_ref_loc (input_location,
7559 arg2se.expr);
7560 gfc_add_block_to_block (&se->pre, &arg1se.pre);
7561 gfc_add_block_to_block (&se->post, &arg1se.post);
7562 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7563 gfc_add_block_to_block (&se->post, &arg2se.post);
7564 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
7565 arg1se.expr, arg2se.expr);
7566 tmp2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7567 arg1se.expr, null_pointer_node);
7568 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7569 boolean_type_node, tmp, tmp2);
7571 else
7573 /* An array pointer of zero length is not associated if target is
7574 present. */
7575 arg1se.descriptor_only = 1;
7576 gfc_conv_expr_lhs (&arg1se, arg1->expr);
7577 if (arg1->expr->rank == -1)
7579 tmp = gfc_conv_descriptor_rank (arg1se.expr);
7580 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7581 TREE_TYPE (tmp), tmp, gfc_index_one_node);
7583 else
7584 tmp = gfc_rank_cst[arg1->expr->rank - 1];
7585 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
7586 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
7587 boolean_type_node, tmp,
7588 build_int_cst (TREE_TYPE (tmp), 0));
7590 /* A pointer to an array, call library function _gfor_associated. */
7591 arg1se.want_pointer = 1;
7592 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
7594 arg2se.want_pointer = 1;
7595 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
7596 gfc_add_block_to_block (&se->pre, &arg2se.pre);
7597 gfc_add_block_to_block (&se->post, &arg2se.post);
7598 se->expr = build_call_expr_loc (input_location,
7599 gfor_fndecl_associated, 2,
7600 arg1se.expr, arg2se.expr);
7601 se->expr = convert (boolean_type_node, se->expr);
7602 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7603 boolean_type_node, se->expr,
7604 nonzero_arraylen);
7607 /* If target is present zero character length pointers cannot
7608 be associated. */
7609 if (nonzero_charlen != NULL_TREE)
7610 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7611 boolean_type_node,
7612 se->expr, nonzero_charlen);
7615 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7619 /* Generate code for the SAME_TYPE_AS intrinsic.
7620 Generate inline code that directly checks the vindices. */
7622 static void
7623 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
7625 gfc_expr *a, *b;
7626 gfc_se se1, se2;
7627 tree tmp;
7628 tree conda = NULL_TREE, condb = NULL_TREE;
7630 gfc_init_se (&se1, NULL);
7631 gfc_init_se (&se2, NULL);
7633 a = expr->value.function.actual->expr;
7634 b = expr->value.function.actual->next->expr;
7636 if (UNLIMITED_POLY (a))
7638 tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
7639 conda = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7640 tmp, build_int_cst (TREE_TYPE (tmp), 0));
7643 if (UNLIMITED_POLY (b))
7645 tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
7646 condb = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7647 tmp, build_int_cst (TREE_TYPE (tmp), 0));
7650 if (a->ts.type == BT_CLASS)
7652 gfc_add_vptr_component (a);
7653 gfc_add_hash_component (a);
7655 else if (a->ts.type == BT_DERIVED)
7656 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
7657 a->ts.u.derived->hash_value);
7659 if (b->ts.type == BT_CLASS)
7661 gfc_add_vptr_component (b);
7662 gfc_add_hash_component (b);
7664 else if (b->ts.type == BT_DERIVED)
7665 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
7666 b->ts.u.derived->hash_value);
7668 gfc_conv_expr (&se1, a);
7669 gfc_conv_expr (&se2, b);
7671 tmp = fold_build2_loc (input_location, EQ_EXPR,
7672 boolean_type_node, se1.expr,
7673 fold_convert (TREE_TYPE (se1.expr), se2.expr));
7675 if (conda)
7676 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
7677 boolean_type_node, conda, tmp);
7679 if (condb)
7680 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
7681 boolean_type_node, condb, tmp);
7683 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
7687 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
7689 static void
7690 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
7692 tree args[2];
7694 gfc_conv_intrinsic_function_args (se, expr, args, 2);
7695 se->expr = build_call_expr_loc (input_location,
7696 gfor_fndecl_sc_kind, 2, args[0], args[1]);
7697 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7701 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
7703 static void
7704 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
7706 tree arg, type;
7708 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7710 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
7711 type = gfc_get_int_type (4);
7712 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
7714 /* Convert it to the required type. */
7715 type = gfc_typenode_for_spec (&expr->ts);
7716 se->expr = build_call_expr_loc (input_location,
7717 gfor_fndecl_si_kind, 1, arg);
7718 se->expr = fold_convert (type, se->expr);
7722 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
7724 static void
7725 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
7727 gfc_actual_arglist *actual;
7728 tree type;
7729 gfc_se argse;
7730 vec<tree, va_gc> *args = NULL;
7732 for (actual = expr->value.function.actual; actual; actual = actual->next)
7734 gfc_init_se (&argse, se);
7736 /* Pass a NULL pointer for an absent arg. */
7737 if (actual->expr == NULL)
7738 argse.expr = null_pointer_node;
7739 else
7741 gfc_typespec ts;
7742 gfc_clear_ts (&ts);
7744 if (actual->expr->ts.kind != gfc_c_int_kind)
7746 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
7747 ts.type = BT_INTEGER;
7748 ts.kind = gfc_c_int_kind;
7749 gfc_convert_type (actual->expr, &ts, 2);
7751 gfc_conv_expr_reference (&argse, actual->expr);
7754 gfc_add_block_to_block (&se->pre, &argse.pre);
7755 gfc_add_block_to_block (&se->post, &argse.post);
7756 vec_safe_push (args, argse.expr);
7759 /* Convert it to the required type. */
7760 type = gfc_typenode_for_spec (&expr->ts);
7761 se->expr = build_call_expr_loc_vec (input_location,
7762 gfor_fndecl_sr_kind, args);
7763 se->expr = fold_convert (type, se->expr);
7767 /* Generate code for TRIM (A) intrinsic function. */
7769 static void
7770 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
7772 tree var;
7773 tree len;
7774 tree addr;
7775 tree tmp;
7776 tree cond;
7777 tree fndecl;
7778 tree function;
7779 tree *args;
7780 unsigned int num_args;
7782 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
7783 args = XALLOCAVEC (tree, num_args);
7785 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
7786 addr = gfc_build_addr_expr (ppvoid_type_node, var);
7787 len = gfc_create_var (gfc_charlen_type_node, "len");
7789 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
7790 args[0] = gfc_build_addr_expr (NULL_TREE, len);
7791 args[1] = addr;
7793 if (expr->ts.kind == 1)
7794 function = gfor_fndecl_string_trim;
7795 else if (expr->ts.kind == 4)
7796 function = gfor_fndecl_string_trim_char4;
7797 else
7798 gcc_unreachable ();
7800 fndecl = build_addr (function);
7801 tmp = build_call_array_loc (input_location,
7802 TREE_TYPE (TREE_TYPE (function)), fndecl,
7803 num_args, args);
7804 gfc_add_expr_to_block (&se->pre, tmp);
7806 /* Free the temporary afterwards, if necessary. */
7807 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
7808 len, build_int_cst (TREE_TYPE (len), 0));
7809 tmp = gfc_call_free (var);
7810 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
7811 gfc_add_expr_to_block (&se->post, tmp);
7813 se->expr = var;
7814 se->string_length = len;
7818 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
7820 static void
7821 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
7823 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
7824 tree type, cond, tmp, count, exit_label, n, max, largest;
7825 tree size;
7826 stmtblock_t block, body;
7827 int i;
7829 /* We store in charsize the size of a character. */
7830 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
7831 size = build_int_cst (size_type_node, gfc_character_kinds[i].bit_size / 8);
7833 /* Get the arguments. */
7834 gfc_conv_intrinsic_function_args (se, expr, args, 3);
7835 slen = fold_convert (size_type_node, gfc_evaluate_now (args[0], &se->pre));
7836 src = args[1];
7837 ncopies = gfc_evaluate_now (args[2], &se->pre);
7838 ncopies_type = TREE_TYPE (ncopies);
7840 /* Check that NCOPIES is not negative. */
7841 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, ncopies,
7842 build_int_cst (ncopies_type, 0));
7843 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
7844 "Argument NCOPIES of REPEAT intrinsic is negative "
7845 "(its value is %ld)",
7846 fold_convert (long_integer_type_node, ncopies));
7848 /* If the source length is zero, any non negative value of NCOPIES
7849 is valid, and nothing happens. */
7850 n = gfc_create_var (ncopies_type, "ncopies");
7851 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
7852 build_int_cst (size_type_node, 0));
7853 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
7854 build_int_cst (ncopies_type, 0), ncopies);
7855 gfc_add_modify (&se->pre, n, tmp);
7856 ncopies = n;
7858 /* Check that ncopies is not too large: ncopies should be less than
7859 (or equal to) MAX / slen, where MAX is the maximal integer of
7860 the gfc_charlen_type_node type. If slen == 0, we need a special
7861 case to avoid the division by zero. */
7862 i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
7863 max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_charlen_int_kind);
7864 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node,
7865 fold_convert (size_type_node, max), slen);
7866 largest = TYPE_PRECISION (size_type_node) > TYPE_PRECISION (ncopies_type)
7867 ? size_type_node : ncopies_type;
7868 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
7869 fold_convert (largest, ncopies),
7870 fold_convert (largest, max));
7871 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
7872 build_int_cst (size_type_node, 0));
7873 cond = fold_build3_loc (input_location, COND_EXPR, boolean_type_node, tmp,
7874 boolean_false_node, cond);
7875 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
7876 "Argument NCOPIES of REPEAT intrinsic is too large");
7878 /* Compute the destination length. */
7879 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
7880 fold_convert (gfc_charlen_type_node, slen),
7881 fold_convert (gfc_charlen_type_node, ncopies));
7882 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
7883 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
7885 /* Generate the code to do the repeat operation:
7886 for (i = 0; i < ncopies; i++)
7887 memmove (dest + (i * slen * size), src, slen*size); */
7888 gfc_start_block (&block);
7889 count = gfc_create_var (ncopies_type, "count");
7890 gfc_add_modify (&block, count, build_int_cst (ncopies_type, 0));
7891 exit_label = gfc_build_label_decl (NULL_TREE);
7893 /* Start the loop body. */
7894 gfc_start_block (&body);
7896 /* Exit the loop if count >= ncopies. */
7897 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, count,
7898 ncopies);
7899 tmp = build1_v (GOTO_EXPR, exit_label);
7900 TREE_USED (exit_label) = 1;
7901 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
7902 build_empty_stmt (input_location));
7903 gfc_add_expr_to_block (&body, tmp);
7905 /* Call memmove (dest + (i*slen*size), src, slen*size). */
7906 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
7907 fold_convert (gfc_charlen_type_node, slen),
7908 fold_convert (gfc_charlen_type_node, count));
7909 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
7910 tmp, fold_convert (gfc_charlen_type_node, size));
7911 tmp = fold_build_pointer_plus_loc (input_location,
7912 fold_convert (pvoid_type_node, dest), tmp);
7913 tmp = build_call_expr_loc (input_location,
7914 builtin_decl_explicit (BUILT_IN_MEMMOVE),
7915 3, tmp, src,
7916 fold_build2_loc (input_location, MULT_EXPR,
7917 size_type_node, slen,
7918 fold_convert (size_type_node,
7919 size)));
7920 gfc_add_expr_to_block (&body, tmp);
7922 /* Increment count. */
7923 tmp = fold_build2_loc (input_location, PLUS_EXPR, ncopies_type,
7924 count, build_int_cst (TREE_TYPE (count), 1));
7925 gfc_add_modify (&body, count, tmp);
7927 /* Build the loop. */
7928 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
7929 gfc_add_expr_to_block (&block, tmp);
7931 /* Add the exit label. */
7932 tmp = build1_v (LABEL_EXPR, exit_label);
7933 gfc_add_expr_to_block (&block, tmp);
7935 /* Finish the block. */
7936 tmp = gfc_finish_block (&block);
7937 gfc_add_expr_to_block (&se->pre, tmp);
7939 /* Set the result value. */
7940 se->expr = dest;
7941 se->string_length = dlen;
7945 /* Generate code for the IARGC intrinsic. */
7947 static void
7948 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
7950 tree tmp;
7951 tree fndecl;
7952 tree type;
7954 /* Call the library function. This always returns an INTEGER(4). */
7955 fndecl = gfor_fndecl_iargc;
7956 tmp = build_call_expr_loc (input_location,
7957 fndecl, 0);
7959 /* Convert it to the required type. */
7960 type = gfc_typenode_for_spec (&expr->ts);
7961 tmp = fold_convert (type, tmp);
7963 se->expr = tmp;
7967 /* The loc intrinsic returns the address of its argument as
7968 gfc_index_integer_kind integer. */
7970 static void
7971 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
7973 tree temp_var;
7974 gfc_expr *arg_expr;
7976 gcc_assert (!se->ss);
7978 arg_expr = expr->value.function.actual->expr;
7979 if (arg_expr->rank == 0)
7981 if (arg_expr->ts.type == BT_CLASS)
7982 gfc_add_data_component (arg_expr);
7983 gfc_conv_expr_reference (se, arg_expr);
7985 else
7986 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
7987 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
7989 /* Create a temporary variable for loc return value. Without this,
7990 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
7991 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
7992 gfc_add_modify (&se->pre, temp_var, se->expr);
7993 se->expr = temp_var;
7997 /* The following routine generates code for the intrinsic
7998 functions from the ISO_C_BINDING module:
7999 * C_LOC
8000 * C_FUNLOC
8001 * C_ASSOCIATED */
8003 static void
8004 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
8006 gfc_actual_arglist *arg = expr->value.function.actual;
8008 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
8010 if (arg->expr->rank == 0)
8011 gfc_conv_expr_reference (se, arg->expr);
8012 else if (gfc_is_simply_contiguous (arg->expr, false, false))
8013 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
8014 else
8016 gfc_conv_expr_descriptor (se, arg->expr);
8017 se->expr = gfc_conv_descriptor_data_get (se->expr);
8020 /* TODO -- the following two lines shouldn't be necessary, but if
8021 they're removed, a bug is exposed later in the code path.
8022 This workaround was thus introduced, but will have to be
8023 removed; please see PR 35150 for details about the issue. */
8024 se->expr = convert (pvoid_type_node, se->expr);
8025 se->expr = gfc_evaluate_now (se->expr, &se->pre);
8027 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
8028 gfc_conv_expr_reference (se, arg->expr);
8029 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
8031 gfc_se arg1se;
8032 gfc_se arg2se;
8034 /* Build the addr_expr for the first argument. The argument is
8035 already an *address* so we don't need to set want_pointer in
8036 the gfc_se. */
8037 gfc_init_se (&arg1se, NULL);
8038 gfc_conv_expr (&arg1se, arg->expr);
8039 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8040 gfc_add_block_to_block (&se->post, &arg1se.post);
8042 /* See if we were given two arguments. */
8043 if (arg->next->expr == NULL)
8044 /* Only given one arg so generate a null and do a
8045 not-equal comparison against the first arg. */
8046 se->expr = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
8047 arg1se.expr,
8048 fold_convert (TREE_TYPE (arg1se.expr),
8049 null_pointer_node));
8050 else
8052 tree eq_expr;
8053 tree not_null_expr;
8055 /* Given two arguments so build the arg2se from second arg. */
8056 gfc_init_se (&arg2se, NULL);
8057 gfc_conv_expr (&arg2se, arg->next->expr);
8058 gfc_add_block_to_block (&se->pre, &arg2se.pre);
8059 gfc_add_block_to_block (&se->post, &arg2se.post);
8061 /* Generate test to compare that the two args are equal. */
8062 eq_expr = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8063 arg1se.expr, arg2se.expr);
8064 /* Generate test to ensure that the first arg is not null. */
8065 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
8066 boolean_type_node,
8067 arg1se.expr, null_pointer_node);
8069 /* Finally, the generated test must check that both arg1 is not
8070 NULL and that it is equal to the second arg. */
8071 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8072 boolean_type_node,
8073 not_null_expr, eq_expr);
8076 else
8077 gcc_unreachable ();
8081 /* The following routine generates code for the intrinsic
8082 subroutines from the ISO_C_BINDING module:
8083 * C_F_POINTER
8084 * C_F_PROCPOINTER. */
8086 static tree
8087 conv_isocbinding_subroutine (gfc_code *code)
8089 gfc_se se;
8090 gfc_se cptrse;
8091 gfc_se fptrse;
8092 gfc_se shapese;
8093 gfc_ss *shape_ss;
8094 tree desc, dim, tmp, stride, offset;
8095 stmtblock_t body, block;
8096 gfc_loopinfo loop;
8097 gfc_actual_arglist *arg = code->ext.actual;
8099 gfc_init_se (&se, NULL);
8100 gfc_init_se (&cptrse, NULL);
8101 gfc_conv_expr (&cptrse, arg->expr);
8102 gfc_add_block_to_block (&se.pre, &cptrse.pre);
8103 gfc_add_block_to_block (&se.post, &cptrse.post);
8105 gfc_init_se (&fptrse, NULL);
8106 if (arg->next->expr->rank == 0)
8108 fptrse.want_pointer = 1;
8109 gfc_conv_expr (&fptrse, arg->next->expr);
8110 gfc_add_block_to_block (&se.pre, &fptrse.pre);
8111 gfc_add_block_to_block (&se.post, &fptrse.post);
8112 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
8113 && arg->next->expr->symtree->n.sym->attr.dummy)
8114 fptrse.expr = build_fold_indirect_ref_loc (input_location,
8115 fptrse.expr);
8116 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
8117 TREE_TYPE (fptrse.expr),
8118 fptrse.expr,
8119 fold_convert (TREE_TYPE (fptrse.expr),
8120 cptrse.expr));
8121 gfc_add_expr_to_block (&se.pre, se.expr);
8122 gfc_add_block_to_block (&se.pre, &se.post);
8123 return gfc_finish_block (&se.pre);
8126 gfc_start_block (&block);
8128 /* Get the descriptor of the Fortran pointer. */
8129 fptrse.descriptor_only = 1;
8130 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
8131 gfc_add_block_to_block (&block, &fptrse.pre);
8132 desc = fptrse.expr;
8134 /* Set the span field. */
8135 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
8136 tmp = fold_convert (gfc_array_index_type, tmp);
8137 gfc_conv_descriptor_span_set (&block, desc, tmp);
8139 /* Set data value, dtype, and offset. */
8140 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
8141 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
8142 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
8143 gfc_get_dtype (TREE_TYPE (desc)));
8145 /* Start scalarization of the bounds, using the shape argument. */
8147 shape_ss = gfc_walk_expr (arg->next->next->expr);
8148 gcc_assert (shape_ss != gfc_ss_terminator);
8149 gfc_init_se (&shapese, NULL);
8151 gfc_init_loopinfo (&loop);
8152 gfc_add_ss_to_loop (&loop, shape_ss);
8153 gfc_conv_ss_startstride (&loop);
8154 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
8155 gfc_mark_ss_chain_used (shape_ss, 1);
8157 gfc_copy_loopinfo_to_se (&shapese, &loop);
8158 shapese.ss = shape_ss;
8160 stride = gfc_create_var (gfc_array_index_type, "stride");
8161 offset = gfc_create_var (gfc_array_index_type, "offset");
8162 gfc_add_modify (&block, stride, gfc_index_one_node);
8163 gfc_add_modify (&block, offset, gfc_index_zero_node);
8165 /* Loop body. */
8166 gfc_start_scalarized_body (&loop, &body);
8168 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8169 loop.loopvar[0], loop.from[0]);
8171 /* Set bounds and stride. */
8172 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
8173 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
8175 gfc_conv_expr (&shapese, arg->next->next->expr);
8176 gfc_add_block_to_block (&body, &shapese.pre);
8177 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
8178 gfc_add_block_to_block (&body, &shapese.post);
8180 /* Calculate offset. */
8181 gfc_add_modify (&body, offset,
8182 fold_build2_loc (input_location, PLUS_EXPR,
8183 gfc_array_index_type, offset, stride));
8184 /* Update stride. */
8185 gfc_add_modify (&body, stride,
8186 fold_build2_loc (input_location, MULT_EXPR,
8187 gfc_array_index_type, stride,
8188 fold_convert (gfc_array_index_type,
8189 shapese.expr)));
8190 /* Finish scalarization loop. */
8191 gfc_trans_scalarizing_loops (&loop, &body);
8192 gfc_add_block_to_block (&block, &loop.pre);
8193 gfc_add_block_to_block (&block, &loop.post);
8194 gfc_add_block_to_block (&block, &fptrse.post);
8195 gfc_cleanup_loop (&loop);
8197 gfc_add_modify (&block, offset,
8198 fold_build1_loc (input_location, NEGATE_EXPR,
8199 gfc_array_index_type, offset));
8200 gfc_conv_descriptor_offset_set (&block, desc, offset);
8202 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
8203 gfc_add_block_to_block (&se.pre, &se.post);
8204 return gfc_finish_block (&se.pre);
8208 /* Save and restore floating-point state. */
8210 tree
8211 gfc_save_fp_state (stmtblock_t *block)
8213 tree type, fpstate, tmp;
8215 type = build_array_type (char_type_node,
8216 build_range_type (size_type_node, size_zero_node,
8217 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
8218 fpstate = gfc_create_var (type, "fpstate");
8219 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
8221 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
8222 1, fpstate);
8223 gfc_add_expr_to_block (block, tmp);
8225 return fpstate;
8229 void
8230 gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
8232 tree tmp;
8234 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
8235 1, fpstate);
8236 gfc_add_expr_to_block (block, tmp);
8240 /* Generate code for arguments of IEEE functions. */
8242 static void
8243 conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
8244 int nargs)
8246 gfc_actual_arglist *actual;
8247 gfc_expr *e;
8248 gfc_se argse;
8249 int arg;
8251 actual = expr->value.function.actual;
8252 for (arg = 0; arg < nargs; arg++, actual = actual->next)
8254 gcc_assert (actual);
8255 e = actual->expr;
8257 gfc_init_se (&argse, se);
8258 gfc_conv_expr_val (&argse, e);
8260 gfc_add_block_to_block (&se->pre, &argse.pre);
8261 gfc_add_block_to_block (&se->post, &argse.post);
8262 argarray[arg] = argse.expr;
8267 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
8268 and IEEE_UNORDERED, which translate directly to GCC type-generic
8269 built-ins. */
8271 static void
8272 conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
8273 enum built_in_function code, int nargs)
8275 tree args[2];
8276 gcc_assert ((unsigned) nargs <= sizeof(args)/sizeof(args[0]));
8278 conv_ieee_function_args (se, expr, args, nargs);
8279 se->expr = build_call_expr_loc_array (input_location,
8280 builtin_decl_explicit (code),
8281 nargs, args);
8282 STRIP_TYPE_NOPS (se->expr);
8283 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8287 /* Generate code for IEEE_IS_NORMAL intrinsic:
8288 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
8290 static void
8291 conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
8293 tree arg, isnormal, iszero;
8295 /* Convert arg, evaluate it only once. */
8296 conv_ieee_function_args (se, expr, &arg, 1);
8297 arg = gfc_evaluate_now (arg, &se->pre);
8299 isnormal = build_call_expr_loc (input_location,
8300 builtin_decl_explicit (BUILT_IN_ISNORMAL),
8301 1, arg);
8302 iszero = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
8303 build_real_from_int_cst (TREE_TYPE (arg),
8304 integer_zero_node));
8305 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
8306 boolean_type_node, isnormal, iszero);
8307 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8311 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
8312 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
8314 static void
8315 conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
8317 tree arg, signbit, isnan;
8319 /* Convert arg, evaluate it only once. */
8320 conv_ieee_function_args (se, expr, &arg, 1);
8321 arg = gfc_evaluate_now (arg, &se->pre);
8323 isnan = build_call_expr_loc (input_location,
8324 builtin_decl_explicit (BUILT_IN_ISNAN),
8325 1, arg);
8326 STRIP_TYPE_NOPS (isnan);
8328 signbit = build_call_expr_loc (input_location,
8329 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8330 1, arg);
8331 signbit = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
8332 signbit, integer_zero_node);
8334 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8335 boolean_type_node, signbit,
8336 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
8337 TREE_TYPE(isnan), isnan));
8339 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
8343 /* Generate code for IEEE_LOGB and IEEE_RINT. */
8345 static void
8346 conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
8347 enum built_in_function code)
8349 tree arg, decl, call, fpstate;
8350 int argprec;
8352 conv_ieee_function_args (se, expr, &arg, 1);
8353 argprec = TYPE_PRECISION (TREE_TYPE (arg));
8354 decl = builtin_decl_for_precision (code, argprec);
8356 /* Save floating-point state. */
8357 fpstate = gfc_save_fp_state (&se->pre);
8359 /* Make the function call. */
8360 call = build_call_expr_loc (input_location, decl, 1, arg);
8361 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
8363 /* Restore floating-point state. */
8364 gfc_restore_fp_state (&se->post, fpstate);
8368 /* Generate code for IEEE_REM. */
8370 static void
8371 conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
8373 tree args[2], decl, call, fpstate;
8374 int argprec;
8376 conv_ieee_function_args (se, expr, args, 2);
8378 /* If arguments have unequal size, convert them to the larger. */
8379 if (TYPE_PRECISION (TREE_TYPE (args[0]))
8380 > TYPE_PRECISION (TREE_TYPE (args[1])))
8381 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8382 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
8383 > TYPE_PRECISION (TREE_TYPE (args[0])))
8384 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
8386 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8387 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
8389 /* Save floating-point state. */
8390 fpstate = gfc_save_fp_state (&se->pre);
8392 /* Make the function call. */
8393 call = build_call_expr_loc_array (input_location, decl, 2, args);
8394 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8396 /* Restore floating-point state. */
8397 gfc_restore_fp_state (&se->post, fpstate);
8401 /* Generate code for IEEE_NEXT_AFTER. */
8403 static void
8404 conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
8406 tree args[2], decl, call, fpstate;
8407 int argprec;
8409 conv_ieee_function_args (se, expr, args, 2);
8411 /* Result has the characteristics of first argument. */
8412 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
8413 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8414 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
8416 /* Save floating-point state. */
8417 fpstate = gfc_save_fp_state (&se->pre);
8419 /* Make the function call. */
8420 call = build_call_expr_loc_array (input_location, decl, 2, args);
8421 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8423 /* Restore floating-point state. */
8424 gfc_restore_fp_state (&se->post, fpstate);
8428 /* Generate code for IEEE_SCALB. */
8430 static void
8431 conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
8433 tree args[2], decl, call, huge, type;
8434 int argprec, n;
8436 conv_ieee_function_args (se, expr, args, 2);
8438 /* Result has the characteristics of first argument. */
8439 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8440 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
8442 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
8444 /* We need to fold the integer into the range of a C int. */
8445 args[1] = gfc_evaluate_now (args[1], &se->pre);
8446 type = TREE_TYPE (args[1]);
8448 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
8449 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
8450 gfc_c_int_kind);
8451 huge = fold_convert (type, huge);
8452 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
8453 huge);
8454 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
8455 fold_build1_loc (input_location, NEGATE_EXPR,
8456 type, huge));
8459 args[1] = fold_convert (integer_type_node, args[1]);
8461 /* Make the function call. */
8462 call = build_call_expr_loc_array (input_location, decl, 2, args);
8463 se->expr = fold_convert (TREE_TYPE (args[0]), call);
8467 /* Generate code for IEEE_COPY_SIGN. */
8469 static void
8470 conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
8472 tree args[2], decl, sign;
8473 int argprec;
8475 conv_ieee_function_args (se, expr, args, 2);
8477 /* Get the sign of the second argument. */
8478 sign = build_call_expr_loc (input_location,
8479 builtin_decl_explicit (BUILT_IN_SIGNBIT),
8480 1, args[1]);
8481 sign = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
8482 sign, integer_zero_node);
8484 /* Create a value of one, with the right sign. */
8485 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
8486 sign,
8487 fold_build1_loc (input_location, NEGATE_EXPR,
8488 integer_type_node,
8489 integer_one_node),
8490 integer_one_node);
8491 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
8493 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
8494 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
8496 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
8500 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
8501 module. */
8503 bool
8504 gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
8506 const char *name = expr->value.function.name;
8508 #define STARTS_WITH(A,B) (strncmp((A), (B), strlen(B)) == 0)
8510 if (STARTS_WITH (name, "_gfortran_ieee_is_nan"))
8511 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
8512 else if (STARTS_WITH (name, "_gfortran_ieee_is_finite"))
8513 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
8514 else if (STARTS_WITH (name, "_gfortran_ieee_unordered"))
8515 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
8516 else if (STARTS_WITH (name, "_gfortran_ieee_is_normal"))
8517 conv_intrinsic_ieee_is_normal (se, expr);
8518 else if (STARTS_WITH (name, "_gfortran_ieee_is_negative"))
8519 conv_intrinsic_ieee_is_negative (se, expr);
8520 else if (STARTS_WITH (name, "_gfortran_ieee_copy_sign"))
8521 conv_intrinsic_ieee_copy_sign (se, expr);
8522 else if (STARTS_WITH (name, "_gfortran_ieee_scalb"))
8523 conv_intrinsic_ieee_scalb (se, expr);
8524 else if (STARTS_WITH (name, "_gfortran_ieee_next_after"))
8525 conv_intrinsic_ieee_next_after (se, expr);
8526 else if (STARTS_WITH (name, "_gfortran_ieee_rem"))
8527 conv_intrinsic_ieee_rem (se, expr);
8528 else if (STARTS_WITH (name, "_gfortran_ieee_logb"))
8529 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
8530 else if (STARTS_WITH (name, "_gfortran_ieee_rint"))
8531 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
8532 else
8533 /* It is not among the functions we translate directly. We return
8534 false, so a library function call is emitted. */
8535 return false;
8537 #undef STARTS_WITH
8539 return true;
8543 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
8545 static void
8546 gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
8548 tree arg, res, restype;
8550 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
8551 arg = fold_convert (size_type_node, arg);
8552 res = build_call_expr_loc (input_location,
8553 builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
8554 restype = gfc_typenode_for_spec (&expr->ts);
8555 se->expr = fold_convert (restype, res);
8559 /* Generate code for an intrinsic function. Some map directly to library
8560 calls, others get special handling. In some cases the name of the function
8561 used depends on the type specifiers. */
8563 void
8564 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
8566 const char *name;
8567 int lib, kind;
8568 tree fndecl;
8570 name = &expr->value.function.name[2];
8572 if (expr->rank > 0)
8574 lib = gfc_is_intrinsic_libcall (expr);
8575 if (lib != 0)
8577 if (lib == 1)
8578 se->ignore_optional = 1;
8580 switch (expr->value.function.isym->id)
8582 case GFC_ISYM_EOSHIFT:
8583 case GFC_ISYM_PACK:
8584 case GFC_ISYM_RESHAPE:
8585 /* For all of those the first argument specifies the type and the
8586 third is optional. */
8587 conv_generic_with_optional_char_arg (se, expr, 1, 3);
8588 break;
8590 default:
8591 gfc_conv_intrinsic_funcall (se, expr);
8592 break;
8595 return;
8599 switch (expr->value.function.isym->id)
8601 case GFC_ISYM_NONE:
8602 gcc_unreachable ();
8604 case GFC_ISYM_REPEAT:
8605 gfc_conv_intrinsic_repeat (se, expr);
8606 break;
8608 case GFC_ISYM_TRIM:
8609 gfc_conv_intrinsic_trim (se, expr);
8610 break;
8612 case GFC_ISYM_SC_KIND:
8613 gfc_conv_intrinsic_sc_kind (se, expr);
8614 break;
8616 case GFC_ISYM_SI_KIND:
8617 gfc_conv_intrinsic_si_kind (se, expr);
8618 break;
8620 case GFC_ISYM_SR_KIND:
8621 gfc_conv_intrinsic_sr_kind (se, expr);
8622 break;
8624 case GFC_ISYM_EXPONENT:
8625 gfc_conv_intrinsic_exponent (se, expr);
8626 break;
8628 case GFC_ISYM_SCAN:
8629 kind = expr->value.function.actual->expr->ts.kind;
8630 if (kind == 1)
8631 fndecl = gfor_fndecl_string_scan;
8632 else if (kind == 4)
8633 fndecl = gfor_fndecl_string_scan_char4;
8634 else
8635 gcc_unreachable ();
8637 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
8638 break;
8640 case GFC_ISYM_VERIFY:
8641 kind = expr->value.function.actual->expr->ts.kind;
8642 if (kind == 1)
8643 fndecl = gfor_fndecl_string_verify;
8644 else if (kind == 4)
8645 fndecl = gfor_fndecl_string_verify_char4;
8646 else
8647 gcc_unreachable ();
8649 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
8650 break;
8652 case GFC_ISYM_ALLOCATED:
8653 gfc_conv_allocated (se, expr);
8654 break;
8656 case GFC_ISYM_ASSOCIATED:
8657 gfc_conv_associated(se, expr);
8658 break;
8660 case GFC_ISYM_SAME_TYPE_AS:
8661 gfc_conv_same_type_as (se, expr);
8662 break;
8664 case GFC_ISYM_ABS:
8665 gfc_conv_intrinsic_abs (se, expr);
8666 break;
8668 case GFC_ISYM_ADJUSTL:
8669 if (expr->ts.kind == 1)
8670 fndecl = gfor_fndecl_adjustl;
8671 else if (expr->ts.kind == 4)
8672 fndecl = gfor_fndecl_adjustl_char4;
8673 else
8674 gcc_unreachable ();
8676 gfc_conv_intrinsic_adjust (se, expr, fndecl);
8677 break;
8679 case GFC_ISYM_ADJUSTR:
8680 if (expr->ts.kind == 1)
8681 fndecl = gfor_fndecl_adjustr;
8682 else if (expr->ts.kind == 4)
8683 fndecl = gfor_fndecl_adjustr_char4;
8684 else
8685 gcc_unreachable ();
8687 gfc_conv_intrinsic_adjust (se, expr, fndecl);
8688 break;
8690 case GFC_ISYM_AIMAG:
8691 gfc_conv_intrinsic_imagpart (se, expr);
8692 break;
8694 case GFC_ISYM_AINT:
8695 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
8696 break;
8698 case GFC_ISYM_ALL:
8699 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
8700 break;
8702 case GFC_ISYM_ANINT:
8703 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
8704 break;
8706 case GFC_ISYM_AND:
8707 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
8708 break;
8710 case GFC_ISYM_ANY:
8711 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
8712 break;
8714 case GFC_ISYM_BTEST:
8715 gfc_conv_intrinsic_btest (se, expr);
8716 break;
8718 case GFC_ISYM_BGE:
8719 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
8720 break;
8722 case GFC_ISYM_BGT:
8723 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
8724 break;
8726 case GFC_ISYM_BLE:
8727 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
8728 break;
8730 case GFC_ISYM_BLT:
8731 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
8732 break;
8734 case GFC_ISYM_C_ASSOCIATED:
8735 case GFC_ISYM_C_FUNLOC:
8736 case GFC_ISYM_C_LOC:
8737 conv_isocbinding_function (se, expr);
8738 break;
8740 case GFC_ISYM_ACHAR:
8741 case GFC_ISYM_CHAR:
8742 gfc_conv_intrinsic_char (se, expr);
8743 break;
8745 case GFC_ISYM_CONVERSION:
8746 case GFC_ISYM_REAL:
8747 case GFC_ISYM_LOGICAL:
8748 case GFC_ISYM_DBLE:
8749 gfc_conv_intrinsic_conversion (se, expr);
8750 break;
8752 /* Integer conversions are handled separately to make sure we get the
8753 correct rounding mode. */
8754 case GFC_ISYM_INT:
8755 case GFC_ISYM_INT2:
8756 case GFC_ISYM_INT8:
8757 case GFC_ISYM_LONG:
8758 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
8759 break;
8761 case GFC_ISYM_NINT:
8762 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
8763 break;
8765 case GFC_ISYM_CEILING:
8766 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
8767 break;
8769 case GFC_ISYM_FLOOR:
8770 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
8771 break;
8773 case GFC_ISYM_MOD:
8774 gfc_conv_intrinsic_mod (se, expr, 0);
8775 break;
8777 case GFC_ISYM_MODULO:
8778 gfc_conv_intrinsic_mod (se, expr, 1);
8779 break;
8781 case GFC_ISYM_CAF_GET:
8782 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
8783 false, NULL);
8784 break;
8786 case GFC_ISYM_CMPLX:
8787 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
8788 break;
8790 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
8791 gfc_conv_intrinsic_iargc (se, expr);
8792 break;
8794 case GFC_ISYM_COMPLEX:
8795 gfc_conv_intrinsic_cmplx (se, expr, 1);
8796 break;
8798 case GFC_ISYM_CONJG:
8799 gfc_conv_intrinsic_conjg (se, expr);
8800 break;
8802 case GFC_ISYM_COUNT:
8803 gfc_conv_intrinsic_count (se, expr);
8804 break;
8806 case GFC_ISYM_CTIME:
8807 gfc_conv_intrinsic_ctime (se, expr);
8808 break;
8810 case GFC_ISYM_DIM:
8811 gfc_conv_intrinsic_dim (se, expr);
8812 break;
8814 case GFC_ISYM_DOT_PRODUCT:
8815 gfc_conv_intrinsic_dot_product (se, expr);
8816 break;
8818 case GFC_ISYM_DPROD:
8819 gfc_conv_intrinsic_dprod (se, expr);
8820 break;
8822 case GFC_ISYM_DSHIFTL:
8823 gfc_conv_intrinsic_dshift (se, expr, true);
8824 break;
8826 case GFC_ISYM_DSHIFTR:
8827 gfc_conv_intrinsic_dshift (se, expr, false);
8828 break;
8830 case GFC_ISYM_FDATE:
8831 gfc_conv_intrinsic_fdate (se, expr);
8832 break;
8834 case GFC_ISYM_FRACTION:
8835 gfc_conv_intrinsic_fraction (se, expr);
8836 break;
8838 case GFC_ISYM_IALL:
8839 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
8840 break;
8842 case GFC_ISYM_IAND:
8843 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
8844 break;
8846 case GFC_ISYM_IANY:
8847 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
8848 break;
8850 case GFC_ISYM_IBCLR:
8851 gfc_conv_intrinsic_singlebitop (se, expr, 0);
8852 break;
8854 case GFC_ISYM_IBITS:
8855 gfc_conv_intrinsic_ibits (se, expr);
8856 break;
8858 case GFC_ISYM_IBSET:
8859 gfc_conv_intrinsic_singlebitop (se, expr, 1);
8860 break;
8862 case GFC_ISYM_IACHAR:
8863 case GFC_ISYM_ICHAR:
8864 /* We assume ASCII character sequence. */
8865 gfc_conv_intrinsic_ichar (se, expr);
8866 break;
8868 case GFC_ISYM_IARGC:
8869 gfc_conv_intrinsic_iargc (se, expr);
8870 break;
8872 case GFC_ISYM_IEOR:
8873 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
8874 break;
8876 case GFC_ISYM_INDEX:
8877 kind = expr->value.function.actual->expr->ts.kind;
8878 if (kind == 1)
8879 fndecl = gfor_fndecl_string_index;
8880 else if (kind == 4)
8881 fndecl = gfor_fndecl_string_index_char4;
8882 else
8883 gcc_unreachable ();
8885 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
8886 break;
8888 case GFC_ISYM_IOR:
8889 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
8890 break;
8892 case GFC_ISYM_IPARITY:
8893 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
8894 break;
8896 case GFC_ISYM_IS_IOSTAT_END:
8897 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
8898 break;
8900 case GFC_ISYM_IS_IOSTAT_EOR:
8901 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
8902 break;
8904 case GFC_ISYM_ISNAN:
8905 gfc_conv_intrinsic_isnan (se, expr);
8906 break;
8908 case GFC_ISYM_LSHIFT:
8909 gfc_conv_intrinsic_shift (se, expr, false, false);
8910 break;
8912 case GFC_ISYM_RSHIFT:
8913 gfc_conv_intrinsic_shift (se, expr, true, true);
8914 break;
8916 case GFC_ISYM_SHIFTA:
8917 gfc_conv_intrinsic_shift (se, expr, true, true);
8918 break;
8920 case GFC_ISYM_SHIFTL:
8921 gfc_conv_intrinsic_shift (se, expr, false, false);
8922 break;
8924 case GFC_ISYM_SHIFTR:
8925 gfc_conv_intrinsic_shift (se, expr, true, false);
8926 break;
8928 case GFC_ISYM_ISHFT:
8929 gfc_conv_intrinsic_ishft (se, expr);
8930 break;
8932 case GFC_ISYM_ISHFTC:
8933 gfc_conv_intrinsic_ishftc (se, expr);
8934 break;
8936 case GFC_ISYM_LEADZ:
8937 gfc_conv_intrinsic_leadz (se, expr);
8938 break;
8940 case GFC_ISYM_TRAILZ:
8941 gfc_conv_intrinsic_trailz (se, expr);
8942 break;
8944 case GFC_ISYM_POPCNT:
8945 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
8946 break;
8948 case GFC_ISYM_POPPAR:
8949 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
8950 break;
8952 case GFC_ISYM_LBOUND:
8953 gfc_conv_intrinsic_bound (se, expr, 0);
8954 break;
8956 case GFC_ISYM_LCOBOUND:
8957 conv_intrinsic_cobound (se, expr);
8958 break;
8960 case GFC_ISYM_TRANSPOSE:
8961 /* The scalarizer has already been set up for reversed dimension access
8962 order ; now we just get the argument value normally. */
8963 gfc_conv_expr (se, expr->value.function.actual->expr);
8964 break;
8966 case GFC_ISYM_LEN:
8967 gfc_conv_intrinsic_len (se, expr);
8968 break;
8970 case GFC_ISYM_LEN_TRIM:
8971 gfc_conv_intrinsic_len_trim (se, expr);
8972 break;
8974 case GFC_ISYM_LGE:
8975 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
8976 break;
8978 case GFC_ISYM_LGT:
8979 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
8980 break;
8982 case GFC_ISYM_LLE:
8983 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
8984 break;
8986 case GFC_ISYM_LLT:
8987 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
8988 break;
8990 case GFC_ISYM_MALLOC:
8991 gfc_conv_intrinsic_malloc (se, expr);
8992 break;
8994 case GFC_ISYM_MASKL:
8995 gfc_conv_intrinsic_mask (se, expr, 1);
8996 break;
8998 case GFC_ISYM_MASKR:
8999 gfc_conv_intrinsic_mask (se, expr, 0);
9000 break;
9002 case GFC_ISYM_MAX:
9003 if (expr->ts.type == BT_CHARACTER)
9004 gfc_conv_intrinsic_minmax_char (se, expr, 1);
9005 else
9006 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
9007 break;
9009 case GFC_ISYM_MAXLOC:
9010 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
9011 break;
9013 case GFC_ISYM_MAXVAL:
9014 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
9015 break;
9017 case GFC_ISYM_MERGE:
9018 gfc_conv_intrinsic_merge (se, expr);
9019 break;
9021 case GFC_ISYM_MERGE_BITS:
9022 gfc_conv_intrinsic_merge_bits (se, expr);
9023 break;
9025 case GFC_ISYM_MIN:
9026 if (expr->ts.type == BT_CHARACTER)
9027 gfc_conv_intrinsic_minmax_char (se, expr, -1);
9028 else
9029 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
9030 break;
9032 case GFC_ISYM_MINLOC:
9033 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
9034 break;
9036 case GFC_ISYM_MINVAL:
9037 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
9038 break;
9040 case GFC_ISYM_NEAREST:
9041 gfc_conv_intrinsic_nearest (se, expr);
9042 break;
9044 case GFC_ISYM_NORM2:
9045 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
9046 break;
9048 case GFC_ISYM_NOT:
9049 gfc_conv_intrinsic_not (se, expr);
9050 break;
9052 case GFC_ISYM_OR:
9053 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
9054 break;
9056 case GFC_ISYM_PARITY:
9057 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
9058 break;
9060 case GFC_ISYM_PRESENT:
9061 gfc_conv_intrinsic_present (se, expr);
9062 break;
9064 case GFC_ISYM_PRODUCT:
9065 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
9066 break;
9068 case GFC_ISYM_RANK:
9069 gfc_conv_intrinsic_rank (se, expr);
9070 break;
9072 case GFC_ISYM_RRSPACING:
9073 gfc_conv_intrinsic_rrspacing (se, expr);
9074 break;
9076 case GFC_ISYM_SET_EXPONENT:
9077 gfc_conv_intrinsic_set_exponent (se, expr);
9078 break;
9080 case GFC_ISYM_SCALE:
9081 gfc_conv_intrinsic_scale (se, expr);
9082 break;
9084 case GFC_ISYM_SIGN:
9085 gfc_conv_intrinsic_sign (se, expr);
9086 break;
9088 case GFC_ISYM_SIZE:
9089 gfc_conv_intrinsic_size (se, expr);
9090 break;
9092 case GFC_ISYM_SIZEOF:
9093 case GFC_ISYM_C_SIZEOF:
9094 gfc_conv_intrinsic_sizeof (se, expr);
9095 break;
9097 case GFC_ISYM_STORAGE_SIZE:
9098 gfc_conv_intrinsic_storage_size (se, expr);
9099 break;
9101 case GFC_ISYM_SPACING:
9102 gfc_conv_intrinsic_spacing (se, expr);
9103 break;
9105 case GFC_ISYM_STRIDE:
9106 conv_intrinsic_stride (se, expr);
9107 break;
9109 case GFC_ISYM_SUM:
9110 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
9111 break;
9113 case GFC_ISYM_TRANSFER:
9114 if (se->ss && se->ss->info->useflags)
9115 /* Access the previously obtained result. */
9116 gfc_conv_tmp_array_ref (se);
9117 else
9118 gfc_conv_intrinsic_transfer (se, expr);
9119 break;
9121 case GFC_ISYM_TTYNAM:
9122 gfc_conv_intrinsic_ttynam (se, expr);
9123 break;
9125 case GFC_ISYM_UBOUND:
9126 gfc_conv_intrinsic_bound (se, expr, 1);
9127 break;
9129 case GFC_ISYM_UCOBOUND:
9130 conv_intrinsic_cobound (se, expr);
9131 break;
9133 case GFC_ISYM_XOR:
9134 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
9135 break;
9137 case GFC_ISYM_LOC:
9138 gfc_conv_intrinsic_loc (se, expr);
9139 break;
9141 case GFC_ISYM_THIS_IMAGE:
9142 /* For num_images() == 1, handle as LCOBOUND. */
9143 if (expr->value.function.actual->expr
9144 && flag_coarray == GFC_FCOARRAY_SINGLE)
9145 conv_intrinsic_cobound (se, expr);
9146 else
9147 trans_this_image (se, expr);
9148 break;
9150 case GFC_ISYM_IMAGE_INDEX:
9151 trans_image_index (se, expr);
9152 break;
9154 case GFC_ISYM_IMAGE_STATUS:
9155 conv_intrinsic_image_status (se, expr);
9156 break;
9158 case GFC_ISYM_NUM_IMAGES:
9159 trans_num_images (se, expr);
9160 break;
9162 case GFC_ISYM_ACCESS:
9163 case GFC_ISYM_CHDIR:
9164 case GFC_ISYM_CHMOD:
9165 case GFC_ISYM_DTIME:
9166 case GFC_ISYM_ETIME:
9167 case GFC_ISYM_EXTENDS_TYPE_OF:
9168 case GFC_ISYM_FGET:
9169 case GFC_ISYM_FGETC:
9170 case GFC_ISYM_FNUM:
9171 case GFC_ISYM_FPUT:
9172 case GFC_ISYM_FPUTC:
9173 case GFC_ISYM_FSTAT:
9174 case GFC_ISYM_FTELL:
9175 case GFC_ISYM_GETCWD:
9176 case GFC_ISYM_GETGID:
9177 case GFC_ISYM_GETPID:
9178 case GFC_ISYM_GETUID:
9179 case GFC_ISYM_HOSTNM:
9180 case GFC_ISYM_KILL:
9181 case GFC_ISYM_IERRNO:
9182 case GFC_ISYM_IRAND:
9183 case GFC_ISYM_ISATTY:
9184 case GFC_ISYM_JN2:
9185 case GFC_ISYM_LINK:
9186 case GFC_ISYM_LSTAT:
9187 case GFC_ISYM_MATMUL:
9188 case GFC_ISYM_MCLOCK:
9189 case GFC_ISYM_MCLOCK8:
9190 case GFC_ISYM_RAND:
9191 case GFC_ISYM_RENAME:
9192 case GFC_ISYM_SECOND:
9193 case GFC_ISYM_SECNDS:
9194 case GFC_ISYM_SIGNAL:
9195 case GFC_ISYM_STAT:
9196 case GFC_ISYM_SYMLNK:
9197 case GFC_ISYM_SYSTEM:
9198 case GFC_ISYM_TIME:
9199 case GFC_ISYM_TIME8:
9200 case GFC_ISYM_UMASK:
9201 case GFC_ISYM_UNLINK:
9202 case GFC_ISYM_YN2:
9203 gfc_conv_intrinsic_funcall (se, expr);
9204 break;
9206 case GFC_ISYM_EOSHIFT:
9207 case GFC_ISYM_PACK:
9208 case GFC_ISYM_RESHAPE:
9209 /* For those, expr->rank should always be >0 and thus the if above the
9210 switch should have matched. */
9211 gcc_unreachable ();
9212 break;
9214 default:
9215 gfc_conv_intrinsic_lib_function (se, expr);
9216 break;
9221 static gfc_ss *
9222 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
9224 gfc_ss *arg_ss, *tmp_ss;
9225 gfc_actual_arglist *arg;
9227 arg = expr->value.function.actual;
9229 gcc_assert (arg->expr);
9231 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
9232 gcc_assert (arg_ss != gfc_ss_terminator);
9234 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
9236 if (tmp_ss->info->type != GFC_SS_SCALAR
9237 && tmp_ss->info->type != GFC_SS_REFERENCE)
9239 gcc_assert (tmp_ss->dimen == 2);
9241 /* We just invert dimensions. */
9242 std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
9245 /* Stop when tmp_ss points to the last valid element of the chain... */
9246 if (tmp_ss->next == gfc_ss_terminator)
9247 break;
9250 /* ... so that we can attach the rest of the chain to it. */
9251 tmp_ss->next = ss;
9253 return arg_ss;
9257 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
9258 This has the side effect of reversing the nested list, so there is no
9259 need to call gfc_reverse_ss on it (the given list is assumed not to be
9260 reversed yet). */
9262 static gfc_ss *
9263 nest_loop_dimension (gfc_ss *ss, int dim)
9265 int ss_dim, i;
9266 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
9267 gfc_loopinfo *new_loop;
9269 gcc_assert (ss != gfc_ss_terminator);
9271 for (; ss != gfc_ss_terminator; ss = ss->next)
9273 new_ss = gfc_get_ss ();
9274 new_ss->next = prev_ss;
9275 new_ss->parent = ss;
9276 new_ss->info = ss->info;
9277 new_ss->info->refcount++;
9278 if (ss->dimen != 0)
9280 gcc_assert (ss->info->type != GFC_SS_SCALAR
9281 && ss->info->type != GFC_SS_REFERENCE);
9283 new_ss->dimen = 1;
9284 new_ss->dim[0] = ss->dim[dim];
9286 gcc_assert (dim < ss->dimen);
9288 ss_dim = --ss->dimen;
9289 for (i = dim; i < ss_dim; i++)
9290 ss->dim[i] = ss->dim[i + 1];
9292 ss->dim[ss_dim] = 0;
9294 prev_ss = new_ss;
9296 if (ss->nested_ss)
9298 ss->nested_ss->parent = new_ss;
9299 new_ss->nested_ss = ss->nested_ss;
9301 ss->nested_ss = new_ss;
9304 new_loop = gfc_get_loopinfo ();
9305 gfc_init_loopinfo (new_loop);
9307 gcc_assert (prev_ss != NULL);
9308 gcc_assert (prev_ss != gfc_ss_terminator);
9309 gfc_add_ss_to_loop (new_loop, prev_ss);
9310 return new_ss->parent;
9314 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
9315 is to be inlined. */
9317 static gfc_ss *
9318 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
9320 gfc_ss *tmp_ss, *tail, *array_ss;
9321 gfc_actual_arglist *arg1, *arg2, *arg3;
9322 int sum_dim;
9323 bool scalar_mask = false;
9325 /* The rank of the result will be determined later. */
9326 arg1 = expr->value.function.actual;
9327 arg2 = arg1->next;
9328 arg3 = arg2->next;
9329 gcc_assert (arg3 != NULL);
9331 if (expr->rank == 0)
9332 return ss;
9334 tmp_ss = gfc_ss_terminator;
9336 if (arg3->expr)
9338 gfc_ss *mask_ss;
9340 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
9341 if (mask_ss == tmp_ss)
9342 scalar_mask = 1;
9344 tmp_ss = mask_ss;
9347 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
9348 gcc_assert (array_ss != tmp_ss);
9350 /* Odd thing: If the mask is scalar, it is used by the frontend after
9351 the array (to make an if around the nested loop). Thus it shall
9352 be after array_ss once the gfc_ss list is reversed. */
9353 if (scalar_mask)
9354 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
9355 else
9356 tmp_ss = array_ss;
9358 /* "Hide" the dimension on which we will sum in the first arg's scalarization
9359 chain. */
9360 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
9361 tail = nest_loop_dimension (tmp_ss, sum_dim);
9362 tail->next = ss;
9364 return tmp_ss;
9368 static gfc_ss *
9369 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
9372 switch (expr->value.function.isym->id)
9374 case GFC_ISYM_PRODUCT:
9375 case GFC_ISYM_SUM:
9376 return walk_inline_intrinsic_arith (ss, expr);
9378 case GFC_ISYM_TRANSPOSE:
9379 return walk_inline_intrinsic_transpose (ss, expr);
9381 default:
9382 gcc_unreachable ();
9384 gcc_unreachable ();
9388 /* This generates code to execute before entering the scalarization loop.
9389 Currently does nothing. */
9391 void
9392 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
9394 switch (ss->info->expr->value.function.isym->id)
9396 case GFC_ISYM_UBOUND:
9397 case GFC_ISYM_LBOUND:
9398 case GFC_ISYM_UCOBOUND:
9399 case GFC_ISYM_LCOBOUND:
9400 case GFC_ISYM_THIS_IMAGE:
9401 break;
9403 default:
9404 gcc_unreachable ();
9409 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
9410 are expanded into code inside the scalarization loop. */
9412 static gfc_ss *
9413 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
9415 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
9416 gfc_add_class_array_ref (expr->value.function.actual->expr);
9418 /* The two argument version returns a scalar. */
9419 if (expr->value.function.actual->next->expr)
9420 return ss;
9422 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
9426 /* Walk an intrinsic array libcall. */
9428 static gfc_ss *
9429 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
9431 gcc_assert (expr->rank > 0);
9432 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
9436 /* Return whether the function call expression EXPR will be expanded
9437 inline by gfc_conv_intrinsic_function. */
9439 bool
9440 gfc_inline_intrinsic_function_p (gfc_expr *expr)
9442 gfc_actual_arglist *args;
9444 if (!expr->value.function.isym)
9445 return false;
9447 switch (expr->value.function.isym->id)
9449 case GFC_ISYM_PRODUCT:
9450 case GFC_ISYM_SUM:
9451 /* Disable inline expansion if code size matters. */
9452 if (optimize_size)
9453 return false;
9455 args = expr->value.function.actual;
9456 /* We need to be able to subset the SUM argument at compile-time. */
9457 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
9458 return false;
9460 return true;
9462 case GFC_ISYM_TRANSPOSE:
9463 return true;
9465 default:
9466 return false;
9471 /* Returns nonzero if the specified intrinsic function call maps directly to
9472 an external library call. Should only be used for functions that return
9473 arrays. */
9476 gfc_is_intrinsic_libcall (gfc_expr * expr)
9478 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
9479 gcc_assert (expr->rank > 0);
9481 if (gfc_inline_intrinsic_function_p (expr))
9482 return 0;
9484 switch (expr->value.function.isym->id)
9486 case GFC_ISYM_ALL:
9487 case GFC_ISYM_ANY:
9488 case GFC_ISYM_COUNT:
9489 case GFC_ISYM_JN2:
9490 case GFC_ISYM_IANY:
9491 case GFC_ISYM_IALL:
9492 case GFC_ISYM_IPARITY:
9493 case GFC_ISYM_MATMUL:
9494 case GFC_ISYM_MAXLOC:
9495 case GFC_ISYM_MAXVAL:
9496 case GFC_ISYM_MINLOC:
9497 case GFC_ISYM_MINVAL:
9498 case GFC_ISYM_NORM2:
9499 case GFC_ISYM_PARITY:
9500 case GFC_ISYM_PRODUCT:
9501 case GFC_ISYM_SUM:
9502 case GFC_ISYM_SHAPE:
9503 case GFC_ISYM_SPREAD:
9504 case GFC_ISYM_YN2:
9505 /* Ignore absent optional parameters. */
9506 return 1;
9508 case GFC_ISYM_CSHIFT:
9509 case GFC_ISYM_EOSHIFT:
9510 case GFC_ISYM_FAILED_IMAGES:
9511 case GFC_ISYM_STOPPED_IMAGES:
9512 case GFC_ISYM_PACK:
9513 case GFC_ISYM_RESHAPE:
9514 case GFC_ISYM_UNPACK:
9515 /* Pass absent optional parameters. */
9516 return 2;
9518 default:
9519 return 0;
9523 /* Walk an intrinsic function. */
9524 gfc_ss *
9525 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
9526 gfc_intrinsic_sym * isym)
9528 gcc_assert (isym);
9530 if (isym->elemental)
9531 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
9532 NULL, GFC_SS_SCALAR);
9534 if (expr->rank == 0)
9535 return ss;
9537 if (gfc_inline_intrinsic_function_p (expr))
9538 return walk_inline_intrinsic_function (ss, expr);
9540 if (gfc_is_intrinsic_libcall (expr))
9541 return gfc_walk_intrinsic_libfunc (ss, expr);
9543 /* Special cases. */
9544 switch (isym->id)
9546 case GFC_ISYM_LBOUND:
9547 case GFC_ISYM_LCOBOUND:
9548 case GFC_ISYM_UBOUND:
9549 case GFC_ISYM_UCOBOUND:
9550 case GFC_ISYM_THIS_IMAGE:
9551 return gfc_walk_intrinsic_bound (ss, expr);
9553 case GFC_ISYM_TRANSFER:
9554 case GFC_ISYM_CAF_GET:
9555 return gfc_walk_intrinsic_libfunc (ss, expr);
9557 default:
9558 /* This probably meant someone forgot to add an intrinsic to the above
9559 list(s) when they implemented it, or something's gone horribly
9560 wrong. */
9561 gcc_unreachable ();
9566 static tree
9567 conv_co_collective (gfc_code *code)
9569 gfc_se argse;
9570 stmtblock_t block, post_block;
9571 tree fndecl, array, strlen, image_index, stat, errmsg, errmsg_len;
9572 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
9574 gfc_start_block (&block);
9575 gfc_init_block (&post_block);
9577 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
9579 opr_expr = code->ext.actual->next->expr;
9580 image_idx_expr = code->ext.actual->next->next->expr;
9581 stat_expr = code->ext.actual->next->next->next->expr;
9582 errmsg_expr = code->ext.actual->next->next->next->next->expr;
9584 else
9586 opr_expr = NULL;
9587 image_idx_expr = code->ext.actual->next->expr;
9588 stat_expr = code->ext.actual->next->next->expr;
9589 errmsg_expr = code->ext.actual->next->next->next->expr;
9592 /* stat. */
9593 if (stat_expr)
9595 gfc_init_se (&argse, NULL);
9596 gfc_conv_expr (&argse, stat_expr);
9597 gfc_add_block_to_block (&block, &argse.pre);
9598 gfc_add_block_to_block (&post_block, &argse.post);
9599 stat = argse.expr;
9600 if (flag_coarray != GFC_FCOARRAY_SINGLE)
9601 stat = gfc_build_addr_expr (NULL_TREE, stat);
9603 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
9604 stat = NULL_TREE;
9605 else
9606 stat = null_pointer_node;
9608 /* Early exit for GFC_FCOARRAY_SINGLE. */
9609 if (flag_coarray == GFC_FCOARRAY_SINGLE)
9611 if (stat != NULL_TREE)
9612 gfc_add_modify (&block, stat,
9613 fold_convert (TREE_TYPE (stat), integer_zero_node));
9614 return gfc_finish_block (&block);
9617 /* Handle the array. */
9618 gfc_init_se (&argse, NULL);
9619 if (code->ext.actual->expr->rank == 0)
9621 symbol_attribute attr;
9622 gfc_clear_attr (&attr);
9623 gfc_init_se (&argse, NULL);
9624 gfc_conv_expr (&argse, code->ext.actual->expr);
9625 gfc_add_block_to_block (&block, &argse.pre);
9626 gfc_add_block_to_block (&post_block, &argse.post);
9627 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
9628 array = gfc_build_addr_expr (NULL_TREE, array);
9630 else
9632 argse.want_pointer = 1;
9633 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
9634 array = argse.expr;
9636 gfc_add_block_to_block (&block, &argse.pre);
9637 gfc_add_block_to_block (&post_block, &argse.post);
9639 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
9640 strlen = argse.string_length;
9641 else
9642 strlen = integer_zero_node;
9644 /* image_index. */
9645 if (image_idx_expr)
9647 gfc_init_se (&argse, NULL);
9648 gfc_conv_expr (&argse, image_idx_expr);
9649 gfc_add_block_to_block (&block, &argse.pre);
9650 gfc_add_block_to_block (&post_block, &argse.post);
9651 image_index = fold_convert (integer_type_node, argse.expr);
9653 else
9654 image_index = integer_zero_node;
9656 /* errmsg. */
9657 if (errmsg_expr)
9659 gfc_init_se (&argse, NULL);
9660 gfc_conv_expr (&argse, errmsg_expr);
9661 gfc_add_block_to_block (&block, &argse.pre);
9662 gfc_add_block_to_block (&post_block, &argse.post);
9663 errmsg = argse.expr;
9664 errmsg_len = fold_convert (integer_type_node, argse.string_length);
9666 else
9668 errmsg = null_pointer_node;
9669 errmsg_len = integer_zero_node;
9672 /* Generate the function call. */
9673 switch (code->resolved_isym->id)
9675 case GFC_ISYM_CO_BROADCAST:
9676 fndecl = gfor_fndecl_co_broadcast;
9677 break;
9678 case GFC_ISYM_CO_MAX:
9679 fndecl = gfor_fndecl_co_max;
9680 break;
9681 case GFC_ISYM_CO_MIN:
9682 fndecl = gfor_fndecl_co_min;
9683 break;
9684 case GFC_ISYM_CO_REDUCE:
9685 fndecl = gfor_fndecl_co_reduce;
9686 break;
9687 case GFC_ISYM_CO_SUM:
9688 fndecl = gfor_fndecl_co_sum;
9689 break;
9690 default:
9691 gcc_unreachable ();
9694 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
9695 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
9696 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
9697 image_index, stat, errmsg, errmsg_len);
9698 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
9699 fndecl = build_call_expr_loc (input_location, fndecl, 6, array, image_index,
9700 stat, errmsg, strlen, errmsg_len);
9701 else
9703 tree opr, opr_flags;
9705 // FIXME: Handle TS29113's bind(C) strings with descriptor.
9706 int opr_flag_int;
9707 if (gfc_is_proc_ptr_comp (opr_expr))
9709 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
9710 opr_flag_int = sym->attr.dimension
9711 || (sym->ts.type == BT_CHARACTER
9712 && !sym->attr.is_bind_c)
9713 ? GFC_CAF_BYREF : 0;
9714 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
9715 && !sym->attr.is_bind_c
9716 ? GFC_CAF_HIDDENLEN : 0;
9717 opr_flag_int |= sym->formal->sym->attr.value ? GFC_CAF_ARG_VALUE : 0;
9719 else
9721 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
9722 ? GFC_CAF_BYREF : 0;
9723 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
9724 && !opr_expr->symtree->n.sym->attr.is_bind_c
9725 ? GFC_CAF_HIDDENLEN : 0;
9726 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
9727 ? GFC_CAF_ARG_VALUE : 0;
9729 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
9730 gfc_conv_expr (&argse, opr_expr);
9731 opr = argse.expr;
9732 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr, opr_flags,
9733 image_index, stat, errmsg, strlen, errmsg_len);
9736 gfc_add_expr_to_block (&block, fndecl);
9737 gfc_add_block_to_block (&block, &post_block);
9739 return gfc_finish_block (&block);
9743 static tree
9744 conv_intrinsic_atomic_op (gfc_code *code)
9746 gfc_se argse;
9747 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
9748 stmtblock_t block, post_block;
9749 gfc_expr *atom_expr = code->ext.actual->expr;
9750 gfc_expr *stat_expr;
9751 built_in_function fn;
9753 if (atom_expr->expr_type == EXPR_FUNCTION
9754 && atom_expr->value.function.isym
9755 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
9756 atom_expr = atom_expr->value.function.actual->expr;
9758 gfc_start_block (&block);
9759 gfc_init_block (&post_block);
9761 gfc_init_se (&argse, NULL);
9762 argse.want_pointer = 1;
9763 gfc_conv_expr (&argse, atom_expr);
9764 gfc_add_block_to_block (&block, &argse.pre);
9765 gfc_add_block_to_block (&post_block, &argse.post);
9766 atom = argse.expr;
9768 gfc_init_se (&argse, NULL);
9769 if (flag_coarray == GFC_FCOARRAY_LIB
9770 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
9771 argse.want_pointer = 1;
9772 gfc_conv_expr (&argse, code->ext.actual->next->expr);
9773 gfc_add_block_to_block (&block, &argse.pre);
9774 gfc_add_block_to_block (&post_block, &argse.post);
9775 value = argse.expr;
9777 switch (code->resolved_isym->id)
9779 case GFC_ISYM_ATOMIC_ADD:
9780 case GFC_ISYM_ATOMIC_AND:
9781 case GFC_ISYM_ATOMIC_DEF:
9782 case GFC_ISYM_ATOMIC_OR:
9783 case GFC_ISYM_ATOMIC_XOR:
9784 stat_expr = code->ext.actual->next->next->expr;
9785 if (flag_coarray == GFC_FCOARRAY_LIB)
9786 old = null_pointer_node;
9787 break;
9788 default:
9789 gfc_init_se (&argse, NULL);
9790 if (flag_coarray == GFC_FCOARRAY_LIB)
9791 argse.want_pointer = 1;
9792 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
9793 gfc_add_block_to_block (&block, &argse.pre);
9794 gfc_add_block_to_block (&post_block, &argse.post);
9795 old = argse.expr;
9796 stat_expr = code->ext.actual->next->next->next->expr;
9799 /* STAT= */
9800 if (stat_expr != NULL)
9802 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
9803 gfc_init_se (&argse, NULL);
9804 if (flag_coarray == GFC_FCOARRAY_LIB)
9805 argse.want_pointer = 1;
9806 gfc_conv_expr_val (&argse, stat_expr);
9807 gfc_add_block_to_block (&block, &argse.pre);
9808 gfc_add_block_to_block (&post_block, &argse.post);
9809 stat = argse.expr;
9811 else if (flag_coarray == GFC_FCOARRAY_LIB)
9812 stat = null_pointer_node;
9814 if (flag_coarray == GFC_FCOARRAY_LIB)
9816 tree image_index, caf_decl, offset, token;
9817 int op;
9819 switch (code->resolved_isym->id)
9821 case GFC_ISYM_ATOMIC_ADD:
9822 case GFC_ISYM_ATOMIC_FETCH_ADD:
9823 op = (int) GFC_CAF_ATOMIC_ADD;
9824 break;
9825 case GFC_ISYM_ATOMIC_AND:
9826 case GFC_ISYM_ATOMIC_FETCH_AND:
9827 op = (int) GFC_CAF_ATOMIC_AND;
9828 break;
9829 case GFC_ISYM_ATOMIC_OR:
9830 case GFC_ISYM_ATOMIC_FETCH_OR:
9831 op = (int) GFC_CAF_ATOMIC_OR;
9832 break;
9833 case GFC_ISYM_ATOMIC_XOR:
9834 case GFC_ISYM_ATOMIC_FETCH_XOR:
9835 op = (int) GFC_CAF_ATOMIC_XOR;
9836 break;
9837 case GFC_ISYM_ATOMIC_DEF:
9838 op = 0; /* Unused. */
9839 break;
9840 default:
9841 gcc_unreachable ();
9844 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
9845 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
9846 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
9848 if (gfc_is_coindexed (atom_expr))
9849 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
9850 else
9851 image_index = integer_zero_node;
9853 if (!POINTER_TYPE_P (TREE_TYPE (value)))
9855 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
9856 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
9857 value = gfc_build_addr_expr (NULL_TREE, tmp);
9860 gfc_init_se (&argse, NULL);
9861 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
9862 atom_expr);
9864 gfc_add_block_to_block (&block, &argse.pre);
9865 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
9866 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
9867 token, offset, image_index, value, stat,
9868 build_int_cst (integer_type_node,
9869 (int) atom_expr->ts.type),
9870 build_int_cst (integer_type_node,
9871 (int) atom_expr->ts.kind));
9872 else
9873 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
9874 build_int_cst (integer_type_node, op),
9875 token, offset, image_index, value, old, stat,
9876 build_int_cst (integer_type_node,
9877 (int) atom_expr->ts.type),
9878 build_int_cst (integer_type_node,
9879 (int) atom_expr->ts.kind));
9881 gfc_add_expr_to_block (&block, tmp);
9882 gfc_add_block_to_block (&block, &argse.post);
9883 gfc_add_block_to_block (&block, &post_block);
9884 return gfc_finish_block (&block);
9888 switch (code->resolved_isym->id)
9890 case GFC_ISYM_ATOMIC_ADD:
9891 case GFC_ISYM_ATOMIC_FETCH_ADD:
9892 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
9893 break;
9894 case GFC_ISYM_ATOMIC_AND:
9895 case GFC_ISYM_ATOMIC_FETCH_AND:
9896 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
9897 break;
9898 case GFC_ISYM_ATOMIC_DEF:
9899 fn = BUILT_IN_ATOMIC_STORE_N;
9900 break;
9901 case GFC_ISYM_ATOMIC_OR:
9902 case GFC_ISYM_ATOMIC_FETCH_OR:
9903 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
9904 break;
9905 case GFC_ISYM_ATOMIC_XOR:
9906 case GFC_ISYM_ATOMIC_FETCH_XOR:
9907 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
9908 break;
9909 default:
9910 gcc_unreachable ();
9913 tmp = TREE_TYPE (TREE_TYPE (atom));
9914 fn = (built_in_function) ((int) fn
9915 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
9916 + 1);
9917 tmp = builtin_decl_explicit (fn);
9918 tree itype = TREE_TYPE (TREE_TYPE (atom));
9919 tmp = builtin_decl_explicit (fn);
9921 switch (code->resolved_isym->id)
9923 case GFC_ISYM_ATOMIC_ADD:
9924 case GFC_ISYM_ATOMIC_AND:
9925 case GFC_ISYM_ATOMIC_DEF:
9926 case GFC_ISYM_ATOMIC_OR:
9927 case GFC_ISYM_ATOMIC_XOR:
9928 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
9929 fold_convert (itype, value),
9930 build_int_cst (NULL, MEMMODEL_RELAXED));
9931 gfc_add_expr_to_block (&block, tmp);
9932 break;
9933 default:
9934 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
9935 fold_convert (itype, value),
9936 build_int_cst (NULL, MEMMODEL_RELAXED));
9937 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
9938 break;
9941 if (stat != NULL_TREE)
9942 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
9943 gfc_add_block_to_block (&block, &post_block);
9944 return gfc_finish_block (&block);
9948 static tree
9949 conv_intrinsic_atomic_ref (gfc_code *code)
9951 gfc_se argse;
9952 tree tmp, atom, value, stat = NULL_TREE;
9953 stmtblock_t block, post_block;
9954 built_in_function fn;
9955 gfc_expr *atom_expr = code->ext.actual->next->expr;
9957 if (atom_expr->expr_type == EXPR_FUNCTION
9958 && atom_expr->value.function.isym
9959 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
9960 atom_expr = atom_expr->value.function.actual->expr;
9962 gfc_start_block (&block);
9963 gfc_init_block (&post_block);
9964 gfc_init_se (&argse, NULL);
9965 argse.want_pointer = 1;
9966 gfc_conv_expr (&argse, atom_expr);
9967 gfc_add_block_to_block (&block, &argse.pre);
9968 gfc_add_block_to_block (&post_block, &argse.post);
9969 atom = argse.expr;
9971 gfc_init_se (&argse, NULL);
9972 if (flag_coarray == GFC_FCOARRAY_LIB
9973 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
9974 argse.want_pointer = 1;
9975 gfc_conv_expr (&argse, code->ext.actual->expr);
9976 gfc_add_block_to_block (&block, &argse.pre);
9977 gfc_add_block_to_block (&post_block, &argse.post);
9978 value = argse.expr;
9980 /* STAT= */
9981 if (code->ext.actual->next->next->expr != NULL)
9983 gcc_assert (code->ext.actual->next->next->expr->expr_type
9984 == EXPR_VARIABLE);
9985 gfc_init_se (&argse, NULL);
9986 if (flag_coarray == GFC_FCOARRAY_LIB)
9987 argse.want_pointer = 1;
9988 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
9989 gfc_add_block_to_block (&block, &argse.pre);
9990 gfc_add_block_to_block (&post_block, &argse.post);
9991 stat = argse.expr;
9993 else if (flag_coarray == GFC_FCOARRAY_LIB)
9994 stat = null_pointer_node;
9996 if (flag_coarray == GFC_FCOARRAY_LIB)
9998 tree image_index, caf_decl, offset, token;
9999 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
10001 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10002 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10003 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10005 if (gfc_is_coindexed (atom_expr))
10006 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10007 else
10008 image_index = integer_zero_node;
10010 gfc_init_se (&argse, NULL);
10011 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10012 atom_expr);
10013 gfc_add_block_to_block (&block, &argse.pre);
10015 /* Different type, need type conversion. */
10016 if (!POINTER_TYPE_P (TREE_TYPE (value)))
10018 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
10019 orig_value = value;
10020 value = gfc_build_addr_expr (NULL_TREE, vardecl);
10023 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
10024 token, offset, image_index, value, stat,
10025 build_int_cst (integer_type_node,
10026 (int) atom_expr->ts.type),
10027 build_int_cst (integer_type_node,
10028 (int) atom_expr->ts.kind));
10029 gfc_add_expr_to_block (&block, tmp);
10030 if (vardecl != NULL_TREE)
10031 gfc_add_modify (&block, orig_value,
10032 fold_convert (TREE_TYPE (orig_value), vardecl));
10033 gfc_add_block_to_block (&block, &argse.post);
10034 gfc_add_block_to_block (&block, &post_block);
10035 return gfc_finish_block (&block);
10038 tmp = TREE_TYPE (TREE_TYPE (atom));
10039 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
10040 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10041 + 1);
10042 tmp = builtin_decl_explicit (fn);
10043 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
10044 build_int_cst (integer_type_node,
10045 MEMMODEL_RELAXED));
10046 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
10048 if (stat != NULL_TREE)
10049 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10050 gfc_add_block_to_block (&block, &post_block);
10051 return gfc_finish_block (&block);
10055 static tree
10056 conv_intrinsic_atomic_cas (gfc_code *code)
10058 gfc_se argse;
10059 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
10060 stmtblock_t block, post_block;
10061 built_in_function fn;
10062 gfc_expr *atom_expr = code->ext.actual->expr;
10064 if (atom_expr->expr_type == EXPR_FUNCTION
10065 && atom_expr->value.function.isym
10066 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10067 atom_expr = atom_expr->value.function.actual->expr;
10069 gfc_init_block (&block);
10070 gfc_init_block (&post_block);
10071 gfc_init_se (&argse, NULL);
10072 argse.want_pointer = 1;
10073 gfc_conv_expr (&argse, atom_expr);
10074 atom = argse.expr;
10076 gfc_init_se (&argse, NULL);
10077 if (flag_coarray == GFC_FCOARRAY_LIB)
10078 argse.want_pointer = 1;
10079 gfc_conv_expr (&argse, code->ext.actual->next->expr);
10080 gfc_add_block_to_block (&block, &argse.pre);
10081 gfc_add_block_to_block (&post_block, &argse.post);
10082 old = argse.expr;
10084 gfc_init_se (&argse, NULL);
10085 if (flag_coarray == GFC_FCOARRAY_LIB)
10086 argse.want_pointer = 1;
10087 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
10088 gfc_add_block_to_block (&block, &argse.pre);
10089 gfc_add_block_to_block (&post_block, &argse.post);
10090 comp = argse.expr;
10092 gfc_init_se (&argse, NULL);
10093 if (flag_coarray == GFC_FCOARRAY_LIB
10094 && code->ext.actual->next->next->next->expr->ts.kind
10095 == atom_expr->ts.kind)
10096 argse.want_pointer = 1;
10097 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
10098 gfc_add_block_to_block (&block, &argse.pre);
10099 gfc_add_block_to_block (&post_block, &argse.post);
10100 new_val = argse.expr;
10102 /* STAT= */
10103 if (code->ext.actual->next->next->next->next->expr != NULL)
10105 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
10106 == EXPR_VARIABLE);
10107 gfc_init_se (&argse, NULL);
10108 if (flag_coarray == GFC_FCOARRAY_LIB)
10109 argse.want_pointer = 1;
10110 gfc_conv_expr_val (&argse,
10111 code->ext.actual->next->next->next->next->expr);
10112 gfc_add_block_to_block (&block, &argse.pre);
10113 gfc_add_block_to_block (&post_block, &argse.post);
10114 stat = argse.expr;
10116 else if (flag_coarray == GFC_FCOARRAY_LIB)
10117 stat = null_pointer_node;
10119 if (flag_coarray == GFC_FCOARRAY_LIB)
10121 tree image_index, caf_decl, offset, token;
10123 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
10124 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
10125 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
10127 if (gfc_is_coindexed (atom_expr))
10128 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
10129 else
10130 image_index = integer_zero_node;
10132 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
10134 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
10135 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
10136 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
10139 /* Convert a constant to a pointer. */
10140 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
10142 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
10143 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
10144 comp = gfc_build_addr_expr (NULL_TREE, tmp);
10147 gfc_init_se (&argse, NULL);
10148 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
10149 atom_expr);
10150 gfc_add_block_to_block (&block, &argse.pre);
10152 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
10153 token, offset, image_index, old, comp, new_val,
10154 stat, build_int_cst (integer_type_node,
10155 (int) atom_expr->ts.type),
10156 build_int_cst (integer_type_node,
10157 (int) atom_expr->ts.kind));
10158 gfc_add_expr_to_block (&block, tmp);
10159 gfc_add_block_to_block (&block, &argse.post);
10160 gfc_add_block_to_block (&block, &post_block);
10161 return gfc_finish_block (&block);
10164 tmp = TREE_TYPE (TREE_TYPE (atom));
10165 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
10166 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
10167 + 1);
10168 tmp = builtin_decl_explicit (fn);
10170 gfc_add_modify (&block, old, comp);
10171 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
10172 gfc_build_addr_expr (NULL, old),
10173 fold_convert (TREE_TYPE (old), new_val),
10174 boolean_false_node,
10175 build_int_cst (NULL, MEMMODEL_RELAXED),
10176 build_int_cst (NULL, MEMMODEL_RELAXED));
10177 gfc_add_expr_to_block (&block, tmp);
10179 if (stat != NULL_TREE)
10180 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
10181 gfc_add_block_to_block (&block, &post_block);
10182 return gfc_finish_block (&block);
10185 static tree
10186 conv_intrinsic_event_query (gfc_code *code)
10188 gfc_se se, argse;
10189 tree stat = NULL_TREE, stat2 = NULL_TREE;
10190 tree count = NULL_TREE, count2 = NULL_TREE;
10192 gfc_expr *event_expr = code->ext.actual->expr;
10194 if (code->ext.actual->next->next->expr)
10196 gcc_assert (code->ext.actual->next->next->expr->expr_type
10197 == EXPR_VARIABLE);
10198 gfc_init_se (&argse, NULL);
10199 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
10200 stat = argse.expr;
10202 else if (flag_coarray == GFC_FCOARRAY_LIB)
10203 stat = null_pointer_node;
10205 if (code->ext.actual->next->expr)
10207 gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
10208 gfc_init_se (&argse, NULL);
10209 gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
10210 count = argse.expr;
10213 gfc_start_block (&se.pre);
10214 if (flag_coarray == GFC_FCOARRAY_LIB)
10216 tree tmp, token, image_index;
10217 tree index = size_zero_node;
10219 if (event_expr->expr_type == EXPR_FUNCTION
10220 && event_expr->value.function.isym
10221 && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
10222 event_expr = event_expr->value.function.actual->expr;
10224 tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
10226 if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
10227 || event_expr->symtree->n.sym->ts.u.derived->from_intmod
10228 != INTMOD_ISO_FORTRAN_ENV
10229 || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
10230 != ISOFORTRAN_EVENT_TYPE)
10232 gfc_error ("Sorry, the event component of derived type at %L is not "
10233 "yet supported", &event_expr->where);
10234 return NULL_TREE;
10237 if (gfc_is_coindexed (event_expr))
10239 gfc_error ("The event variable at %L shall not be coindexed",
10240 &event_expr->where);
10241 return NULL_TREE;
10244 image_index = integer_zero_node;
10246 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
10247 event_expr);
10249 /* For arrays, obtain the array index. */
10250 if (gfc_expr_attr (event_expr).dimension)
10252 tree desc, tmp, extent, lbound, ubound;
10253 gfc_array_ref *ar, ar2;
10254 int i;
10256 /* TODO: Extend this, once DT components are supported. */
10257 ar = &event_expr->ref->u.ar;
10258 ar2 = *ar;
10259 memset (ar, '\0', sizeof (*ar));
10260 ar->as = ar2.as;
10261 ar->type = AR_FULL;
10263 gfc_init_se (&argse, NULL);
10264 argse.descriptor_only = 1;
10265 gfc_conv_expr_descriptor (&argse, event_expr);
10266 gfc_add_block_to_block (&se.pre, &argse.pre);
10267 desc = argse.expr;
10268 *ar = ar2;
10270 extent = integer_one_node;
10271 for (i = 0; i < ar->dimen; i++)
10273 gfc_init_se (&argse, NULL);
10274 gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
10275 gfc_add_block_to_block (&argse.pre, &argse.pre);
10276 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
10277 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10278 integer_type_node, argse.expr,
10279 fold_convert(integer_type_node, lbound));
10280 tmp = fold_build2_loc (input_location, MULT_EXPR,
10281 integer_type_node, extent, tmp);
10282 index = fold_build2_loc (input_location, PLUS_EXPR,
10283 integer_type_node, index, tmp);
10284 if (i < ar->dimen - 1)
10286 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
10287 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
10288 tmp = fold_convert (integer_type_node, tmp);
10289 extent = fold_build2_loc (input_location, MULT_EXPR,
10290 integer_type_node, extent, tmp);
10295 if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
10297 count2 = count;
10298 count = gfc_create_var (integer_type_node, "count");
10301 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
10303 stat2 = stat;
10304 stat = gfc_create_var (integer_type_node, "stat");
10307 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
10308 token, index, image_index, count
10309 ? gfc_build_addr_expr (NULL, count) : count,
10310 stat != null_pointer_node
10311 ? gfc_build_addr_expr (NULL, stat) : stat);
10312 gfc_add_expr_to_block (&se.pre, tmp);
10314 if (count2 != NULL_TREE)
10315 gfc_add_modify (&se.pre, count2,
10316 fold_convert (TREE_TYPE (count2), count));
10318 if (stat2 != NULL_TREE)
10319 gfc_add_modify (&se.pre, stat2,
10320 fold_convert (TREE_TYPE (stat2), stat));
10322 return gfc_finish_block (&se.pre);
10325 gfc_init_se (&argse, NULL);
10326 gfc_conv_expr_val (&argse, code->ext.actual->expr);
10327 gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
10329 if (stat != NULL_TREE)
10330 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
10332 return gfc_finish_block (&se.pre);
10335 static tree
10336 conv_intrinsic_move_alloc (gfc_code *code)
10338 stmtblock_t block;
10339 gfc_expr *from_expr, *to_expr;
10340 gfc_expr *to_expr2, *from_expr2 = NULL;
10341 gfc_se from_se, to_se;
10342 tree tmp;
10343 bool coarray;
10345 gfc_start_block (&block);
10347 from_expr = code->ext.actual->expr;
10348 to_expr = code->ext.actual->next->expr;
10350 gfc_init_se (&from_se, NULL);
10351 gfc_init_se (&to_se, NULL);
10353 gcc_assert (from_expr->ts.type != BT_CLASS
10354 || to_expr->ts.type == BT_CLASS);
10355 coarray = gfc_get_corank (from_expr) != 0;
10357 if (from_expr->rank == 0 && !coarray)
10359 if (from_expr->ts.type != BT_CLASS)
10360 from_expr2 = from_expr;
10361 else
10363 from_expr2 = gfc_copy_expr (from_expr);
10364 gfc_add_data_component (from_expr2);
10367 if (to_expr->ts.type != BT_CLASS)
10368 to_expr2 = to_expr;
10369 else
10371 to_expr2 = gfc_copy_expr (to_expr);
10372 gfc_add_data_component (to_expr2);
10375 from_se.want_pointer = 1;
10376 to_se.want_pointer = 1;
10377 gfc_conv_expr (&from_se, from_expr2);
10378 gfc_conv_expr (&to_se, to_expr2);
10379 gfc_add_block_to_block (&block, &from_se.pre);
10380 gfc_add_block_to_block (&block, &to_se.pre);
10382 /* Deallocate "to". */
10383 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10384 true, to_expr, to_expr->ts);
10385 gfc_add_expr_to_block (&block, tmp);
10387 /* Assign (_data) pointers. */
10388 gfc_add_modify_loc (input_location, &block, to_se.expr,
10389 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
10391 /* Set "from" to NULL. */
10392 gfc_add_modify_loc (input_location, &block, from_se.expr,
10393 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
10395 gfc_add_block_to_block (&block, &from_se.post);
10396 gfc_add_block_to_block (&block, &to_se.post);
10398 /* Set _vptr. */
10399 if (to_expr->ts.type == BT_CLASS)
10401 gfc_symbol *vtab;
10403 gfc_free_expr (to_expr2);
10404 gfc_init_se (&to_se, NULL);
10405 to_se.want_pointer = 1;
10406 gfc_add_vptr_component (to_expr);
10407 gfc_conv_expr (&to_se, to_expr);
10409 if (from_expr->ts.type == BT_CLASS)
10411 if (UNLIMITED_POLY (from_expr))
10412 vtab = NULL;
10413 else
10415 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10416 gcc_assert (vtab);
10419 gfc_free_expr (from_expr2);
10420 gfc_init_se (&from_se, NULL);
10421 from_se.want_pointer = 1;
10422 gfc_add_vptr_component (from_expr);
10423 gfc_conv_expr (&from_se, from_expr);
10424 gfc_add_modify_loc (input_location, &block, to_se.expr,
10425 fold_convert (TREE_TYPE (to_se.expr),
10426 from_se.expr));
10428 /* Reset _vptr component to declared type. */
10429 if (vtab == NULL)
10430 /* Unlimited polymorphic. */
10431 gfc_add_modify_loc (input_location, &block, from_se.expr,
10432 fold_convert (TREE_TYPE (from_se.expr),
10433 null_pointer_node));
10434 else
10436 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10437 gfc_add_modify_loc (input_location, &block, from_se.expr,
10438 fold_convert (TREE_TYPE (from_se.expr), tmp));
10441 else
10443 vtab = gfc_find_vtab (&from_expr->ts);
10444 gcc_assert (vtab);
10445 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10446 gfc_add_modify_loc (input_location, &block, to_se.expr,
10447 fold_convert (TREE_TYPE (to_se.expr), tmp));
10451 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
10453 gfc_add_modify_loc (input_location, &block, to_se.string_length,
10454 fold_convert (TREE_TYPE (to_se.string_length),
10455 from_se.string_length));
10456 if (from_expr->ts.deferred)
10457 gfc_add_modify_loc (input_location, &block, from_se.string_length,
10458 build_int_cst (TREE_TYPE (from_se.string_length), 0));
10461 return gfc_finish_block (&block);
10464 /* Update _vptr component. */
10465 if (to_expr->ts.type == BT_CLASS)
10467 gfc_symbol *vtab;
10469 to_se.want_pointer = 1;
10470 to_expr2 = gfc_copy_expr (to_expr);
10471 gfc_add_vptr_component (to_expr2);
10472 gfc_conv_expr (&to_se, to_expr2);
10474 if (from_expr->ts.type == BT_CLASS)
10476 if (UNLIMITED_POLY (from_expr))
10477 vtab = NULL;
10478 else
10480 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
10481 gcc_assert (vtab);
10484 from_se.want_pointer = 1;
10485 from_expr2 = gfc_copy_expr (from_expr);
10486 gfc_add_vptr_component (from_expr2);
10487 gfc_conv_expr (&from_se, from_expr2);
10488 gfc_add_modify_loc (input_location, &block, to_se.expr,
10489 fold_convert (TREE_TYPE (to_se.expr),
10490 from_se.expr));
10492 /* Reset _vptr component to declared type. */
10493 if (vtab == NULL)
10494 /* Unlimited polymorphic. */
10495 gfc_add_modify_loc (input_location, &block, from_se.expr,
10496 fold_convert (TREE_TYPE (from_se.expr),
10497 null_pointer_node));
10498 else
10500 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10501 gfc_add_modify_loc (input_location, &block, from_se.expr,
10502 fold_convert (TREE_TYPE (from_se.expr), tmp));
10505 else
10507 vtab = gfc_find_vtab (&from_expr->ts);
10508 gcc_assert (vtab);
10509 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
10510 gfc_add_modify_loc (input_location, &block, to_se.expr,
10511 fold_convert (TREE_TYPE (to_se.expr), tmp));
10514 gfc_free_expr (to_expr2);
10515 gfc_init_se (&to_se, NULL);
10517 if (from_expr->ts.type == BT_CLASS)
10519 gfc_free_expr (from_expr2);
10520 gfc_init_se (&from_se, NULL);
10525 /* Deallocate "to". */
10526 if (from_expr->rank == 0)
10528 to_se.want_coarray = 1;
10529 from_se.want_coarray = 1;
10531 gfc_conv_expr_descriptor (&to_se, to_expr);
10532 gfc_conv_expr_descriptor (&from_se, from_expr);
10534 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
10535 is an image control "statement", cf. IR F08/0040 in 12-006A. */
10536 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
10538 tree cond;
10540 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
10541 NULL_TREE, NULL_TREE, true, to_expr,
10542 GFC_CAF_COARRAY_DEALLOCATE_ONLY);
10543 gfc_add_expr_to_block (&block, tmp);
10545 tmp = gfc_conv_descriptor_data_get (to_se.expr);
10546 cond = fold_build2_loc (input_location, EQ_EXPR,
10547 boolean_type_node, tmp,
10548 fold_convert (TREE_TYPE (tmp),
10549 null_pointer_node));
10550 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
10551 3, null_pointer_node, null_pointer_node,
10552 build_int_cst (integer_type_node, 0));
10554 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
10555 tmp, build_empty_stmt (input_location));
10556 gfc_add_expr_to_block (&block, tmp);
10558 else
10560 if (to_expr->ts.type == BT_DERIVED
10561 && to_expr->ts.u.derived->attr.alloc_comp)
10563 tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
10564 to_se.expr, to_expr->rank);
10565 gfc_add_expr_to_block (&block, tmp);
10568 tmp = gfc_conv_descriptor_data_get (to_se.expr);
10569 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
10570 NULL_TREE, true, to_expr,
10571 GFC_CAF_COARRAY_NOCOARRAY);
10572 gfc_add_expr_to_block (&block, tmp);
10575 /* Move the pointer and update the array descriptor data. */
10576 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
10578 /* Set "from" to NULL. */
10579 tmp = gfc_conv_descriptor_data_get (from_se.expr);
10580 gfc_add_modify_loc (input_location, &block, tmp,
10581 fold_convert (TREE_TYPE (tmp), null_pointer_node));
10584 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
10586 gfc_add_modify_loc (input_location, &block, to_se.string_length,
10587 fold_convert (TREE_TYPE (to_se.string_length),
10588 from_se.string_length));
10589 if (from_expr->ts.deferred)
10590 gfc_add_modify_loc (input_location, &block, from_se.string_length,
10591 build_int_cst (TREE_TYPE (from_se.string_length), 0));
10594 return gfc_finish_block (&block);
10598 tree
10599 gfc_conv_intrinsic_subroutine (gfc_code *code)
10601 tree res;
10603 gcc_assert (code->resolved_isym);
10605 switch (code->resolved_isym->id)
10607 case GFC_ISYM_MOVE_ALLOC:
10608 res = conv_intrinsic_move_alloc (code);
10609 break;
10611 case GFC_ISYM_ATOMIC_CAS:
10612 res = conv_intrinsic_atomic_cas (code);
10613 break;
10615 case GFC_ISYM_ATOMIC_ADD:
10616 case GFC_ISYM_ATOMIC_AND:
10617 case GFC_ISYM_ATOMIC_DEF:
10618 case GFC_ISYM_ATOMIC_OR:
10619 case GFC_ISYM_ATOMIC_XOR:
10620 case GFC_ISYM_ATOMIC_FETCH_ADD:
10621 case GFC_ISYM_ATOMIC_FETCH_AND:
10622 case GFC_ISYM_ATOMIC_FETCH_OR:
10623 case GFC_ISYM_ATOMIC_FETCH_XOR:
10624 res = conv_intrinsic_atomic_op (code);
10625 break;
10627 case GFC_ISYM_ATOMIC_REF:
10628 res = conv_intrinsic_atomic_ref (code);
10629 break;
10631 case GFC_ISYM_EVENT_QUERY:
10632 res = conv_intrinsic_event_query (code);
10633 break;
10635 case GFC_ISYM_C_F_POINTER:
10636 case GFC_ISYM_C_F_PROCPOINTER:
10637 res = conv_isocbinding_subroutine (code);
10638 break;
10640 case GFC_ISYM_CAF_SEND:
10641 res = conv_caf_send (code);
10642 break;
10644 case GFC_ISYM_CO_BROADCAST:
10645 case GFC_ISYM_CO_MIN:
10646 case GFC_ISYM_CO_MAX:
10647 case GFC_ISYM_CO_REDUCE:
10648 case GFC_ISYM_CO_SUM:
10649 res = conv_co_collective (code);
10650 break;
10652 case GFC_ISYM_FREE:
10653 res = conv_intrinsic_free (code);
10654 break;
10656 case GFC_ISYM_SYSTEM_CLOCK:
10657 res = conv_intrinsic_system_clock (code);
10658 break;
10660 default:
10661 res = NULL_TREE;
10662 break;
10665 return res;
10668 #include "gt-fortran-trans-intrinsic.h"