Merged revisions 208012,208018-208019,208021,208023-208030,208033,208037,208040-20804...
[official-gcc.git] / main / gcc / fortran / trans-intrinsic.c
blob070b64ed97503f2a00ae7ea3e0c9bd0ff1628c2a
1 /* Intrinsic translation
2 Copyright (C) 2002-2014 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* trans-intrinsic.c-- generate GENERIC trees for calls to intrinsics. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h" /* For UNITS_PER_WORD. */
28 #include "tree.h"
29 #include "stringpool.h"
30 #include "tree-nested.h"
31 #include "stor-layout.h"
32 #include "ggc.h"
33 #include "diagnostic-core.h" /* For internal_error. */
34 #include "toplev.h" /* For rest_of_decl_compilation. */
35 #include "flags.h"
36 #include "gfortran.h"
37 #include "arith.h"
38 #include "intrinsic.h"
39 #include "trans.h"
40 #include "trans-const.h"
41 #include "trans-types.h"
42 #include "trans-array.h"
43 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
44 #include "trans-stmt.h"
45 #include "tree-nested.h"
47 /* This maps Fortran intrinsic math functions to external library or GCC
48 builtin functions. */
49 typedef struct GTY(()) gfc_intrinsic_map_t {
50 /* The explicit enum is required to work around inadequacies in the
51 garbage collection/gengtype parsing mechanism. */
52 enum gfc_isym_id id;
54 /* Enum value from the "language-independent", aka C-centric, part
55 of gcc, or END_BUILTINS of no such value set. */
56 enum built_in_function float_built_in;
57 enum built_in_function double_built_in;
58 enum built_in_function long_double_built_in;
59 enum built_in_function complex_float_built_in;
60 enum built_in_function complex_double_built_in;
61 enum built_in_function complex_long_double_built_in;
63 /* True if the naming pattern is to prepend "c" for complex and
64 append "f" for kind=4. False if the naming pattern is to
65 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
66 bool libm_name;
68 /* True if a complex version of the function exists. */
69 bool complex_available;
71 /* True if the function should be marked const. */
72 bool is_constant;
74 /* The base library name of this function. */
75 const char *name;
77 /* Cache decls created for the various operand types. */
78 tree real4_decl;
79 tree real8_decl;
80 tree real10_decl;
81 tree real16_decl;
82 tree complex4_decl;
83 tree complex8_decl;
84 tree complex10_decl;
85 tree complex16_decl;
87 gfc_intrinsic_map_t;
89 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
90 defines complex variants of all of the entries in mathbuiltins.def
91 except for atan2. */
92 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
93 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
94 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
95 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
96 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
98 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
99 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
100 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
101 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
102 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
104 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
105 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
106 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
107 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
108 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
110 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
111 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
112 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
113 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
114 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
116 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
118 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
119 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
120 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
121 #include "mathbuiltins.def"
123 /* Functions in libgfortran. */
124 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
126 /* End the list. */
127 LIB_FUNCTION (NONE, NULL, false)
130 #undef OTHER_BUILTIN
131 #undef LIB_FUNCTION
132 #undef DEFINE_MATH_BUILTIN
133 #undef DEFINE_MATH_BUILTIN_C
136 enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
139 /* Find the correct variant of a given builtin from its argument. */
140 static tree
141 builtin_decl_for_precision (enum built_in_function base_built_in,
142 int precision)
144 enum built_in_function i = END_BUILTINS;
146 gfc_intrinsic_map_t *m;
147 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
150 if (precision == TYPE_PRECISION (float_type_node))
151 i = m->float_built_in;
152 else if (precision == TYPE_PRECISION (double_type_node))
153 i = m->double_built_in;
154 else if (precision == TYPE_PRECISION (long_double_type_node))
155 i = m->long_double_built_in;
156 else if (precision == TYPE_PRECISION (float128_type_node))
158 /* Special treatment, because it is not exactly a built-in, but
159 a library function. */
160 return m->real16_decl;
163 return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
167 tree
168 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
169 int kind)
171 int i = gfc_validate_kind (BT_REAL, kind, false);
173 if (gfc_real_kinds[i].c_float128)
175 /* For __float128, the story is a bit different, because we return
176 a decl to a library function rather than a built-in. */
177 gfc_intrinsic_map_t *m;
178 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
181 return m->real16_decl;
184 return builtin_decl_for_precision (double_built_in,
185 gfc_real_kinds[i].mode_precision);
189 /* Evaluate the arguments to an intrinsic function. The value
190 of NARGS may be less than the actual number of arguments in EXPR
191 to allow optional "KIND" arguments that are not included in the
192 generated code to be ignored. */
194 static void
195 gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
196 tree *argarray, int nargs)
198 gfc_actual_arglist *actual;
199 gfc_expr *e;
200 gfc_intrinsic_arg *formal;
201 gfc_se argse;
202 int curr_arg;
204 formal = expr->value.function.isym->formal;
205 actual = expr->value.function.actual;
207 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
208 actual = actual->next,
209 formal = formal ? formal->next : NULL)
211 gcc_assert (actual);
212 e = actual->expr;
213 /* Skip omitted optional arguments. */
214 if (!e)
216 --curr_arg;
217 continue;
220 /* Evaluate the parameter. This will substitute scalarized
221 references automatically. */
222 gfc_init_se (&argse, se);
224 if (e->ts.type == BT_CHARACTER)
226 gfc_conv_expr (&argse, e);
227 gfc_conv_string_parameter (&argse);
228 argarray[curr_arg++] = argse.string_length;
229 gcc_assert (curr_arg < nargs);
231 else
232 gfc_conv_expr_val (&argse, e);
234 /* If an optional argument is itself an optional dummy argument,
235 check its presence and substitute a null if absent. */
236 if (e->expr_type == EXPR_VARIABLE
237 && e->symtree->n.sym->attr.optional
238 && formal
239 && formal->optional)
240 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
242 gfc_add_block_to_block (&se->pre, &argse.pre);
243 gfc_add_block_to_block (&se->post, &argse.post);
244 argarray[curr_arg] = argse.expr;
248 /* Count the number of actual arguments to the intrinsic function EXPR
249 including any "hidden" string length arguments. */
251 static unsigned int
252 gfc_intrinsic_argument_list_length (gfc_expr *expr)
254 int n = 0;
255 gfc_actual_arglist *actual;
257 for (actual = expr->value.function.actual; actual; actual = actual->next)
259 if (!actual->expr)
260 continue;
262 if (actual->expr->ts.type == BT_CHARACTER)
263 n += 2;
264 else
265 n++;
268 return n;
272 /* Conversions between different types are output by the frontend as
273 intrinsic functions. We implement these directly with inline code. */
275 static void
276 gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
278 tree type;
279 tree *args;
280 int nargs;
282 nargs = gfc_intrinsic_argument_list_length (expr);
283 args = XALLOCAVEC (tree, nargs);
285 /* Evaluate all the arguments passed. Whilst we're only interested in the
286 first one here, there are other parts of the front-end that assume this
287 and will trigger an ICE if it's not the case. */
288 type = gfc_typenode_for_spec (&expr->ts);
289 gcc_assert (expr->value.function.actual->expr);
290 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
292 /* Conversion between character kinds involves a call to a library
293 function. */
294 if (expr->ts.type == BT_CHARACTER)
296 tree fndecl, var, addr, tmp;
298 if (expr->ts.kind == 1
299 && expr->value.function.actual->expr->ts.kind == 4)
300 fndecl = gfor_fndecl_convert_char4_to_char1;
301 else if (expr->ts.kind == 4
302 && expr->value.function.actual->expr->ts.kind == 1)
303 fndecl = gfor_fndecl_convert_char1_to_char4;
304 else
305 gcc_unreachable ();
307 /* Create the variable storing the converted value. */
308 type = gfc_get_pchar_type (expr->ts.kind);
309 var = gfc_create_var (type, "str");
310 addr = gfc_build_addr_expr (build_pointer_type (type), var);
312 /* Call the library function that will perform the conversion. */
313 gcc_assert (nargs >= 2);
314 tmp = build_call_expr_loc (input_location,
315 fndecl, 3, addr, args[0], args[1]);
316 gfc_add_expr_to_block (&se->pre, tmp);
318 /* Free the temporary afterwards. */
319 tmp = gfc_call_free (var);
320 gfc_add_expr_to_block (&se->post, tmp);
322 se->expr = var;
323 se->string_length = args[0];
325 return;
328 /* Conversion from complex to non-complex involves taking the real
329 component of the value. */
330 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
331 && expr->ts.type != BT_COMPLEX)
333 tree artype;
335 artype = TREE_TYPE (TREE_TYPE (args[0]));
336 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
337 args[0]);
340 se->expr = convert (type, args[0]);
343 /* This is needed because the gcc backend only implements
344 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
345 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
346 Similarly for CEILING. */
348 static tree
349 build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
351 tree tmp;
352 tree cond;
353 tree argtype;
354 tree intval;
356 argtype = TREE_TYPE (arg);
357 arg = gfc_evaluate_now (arg, pblock);
359 intval = convert (type, arg);
360 intval = gfc_evaluate_now (intval, pblock);
362 tmp = convert (argtype, intval);
363 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
364 boolean_type_node, tmp, arg);
366 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
367 intval, build_int_cst (type, 1));
368 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
369 return tmp;
373 /* Round to nearest integer, away from zero. */
375 static tree
376 build_round_expr (tree arg, tree restype)
378 tree argtype;
379 tree fn;
380 int argprec, resprec;
382 argtype = TREE_TYPE (arg);
383 argprec = TYPE_PRECISION (argtype);
384 resprec = TYPE_PRECISION (restype);
386 /* Depending on the type of the result, choose the int intrinsic
387 (iround, available only as a builtin, therefore cannot use it for
388 __float128), long int intrinsic (lround family) or long long
389 intrinsic (llround). We might also need to convert the result
390 afterwards. */
391 if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
392 fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
393 else if (resprec <= LONG_TYPE_SIZE)
394 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
395 else if (resprec <= LONG_LONG_TYPE_SIZE)
396 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
397 else
398 gcc_unreachable ();
400 return fold_convert (restype, build_call_expr_loc (input_location,
401 fn, 1, arg));
405 /* Convert a real to an integer using a specific rounding mode.
406 Ideally we would just build the corresponding GENERIC node,
407 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
409 static tree
410 build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
411 enum rounding_mode op)
413 switch (op)
415 case RND_FLOOR:
416 return build_fixbound_expr (pblock, arg, type, 0);
417 break;
419 case RND_CEIL:
420 return build_fixbound_expr (pblock, arg, type, 1);
421 break;
423 case RND_ROUND:
424 return build_round_expr (arg, type);
425 break;
427 case RND_TRUNC:
428 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
429 break;
431 default:
432 gcc_unreachable ();
437 /* Round a real value using the specified rounding mode.
438 We use a temporary integer of that same kind size as the result.
439 Values larger than those that can be represented by this kind are
440 unchanged, as they will not be accurate enough to represent the
441 rounding.
442 huge = HUGE (KIND (a))
443 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
446 static void
447 gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
449 tree type;
450 tree itype;
451 tree arg[2];
452 tree tmp;
453 tree cond;
454 tree decl;
455 mpfr_t huge;
456 int n, nargs;
457 int kind;
459 kind = expr->ts.kind;
460 nargs = gfc_intrinsic_argument_list_length (expr);
462 decl = NULL_TREE;
463 /* We have builtin functions for some cases. */
464 switch (op)
466 case RND_ROUND:
467 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
468 break;
470 case RND_TRUNC:
471 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
472 break;
474 default:
475 gcc_unreachable ();
478 /* Evaluate the argument. */
479 gcc_assert (expr->value.function.actual->expr);
480 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
482 /* Use a builtin function if one exists. */
483 if (decl != NULL_TREE)
485 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
486 return;
489 /* This code is probably redundant, but we'll keep it lying around just
490 in case. */
491 type = gfc_typenode_for_spec (&expr->ts);
492 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
494 /* Test if the value is too large to handle sensibly. */
495 gfc_set_model_kind (kind);
496 mpfr_init (huge);
497 n = gfc_validate_kind (BT_INTEGER, kind, false);
498 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
499 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
500 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, arg[0],
501 tmp);
503 mpfr_neg (huge, huge, GFC_RND_MODE);
504 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
505 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, arg[0],
506 tmp);
507 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
508 cond, tmp);
509 itype = gfc_get_int_type (kind);
511 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
512 tmp = convert (type, tmp);
513 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
514 arg[0]);
515 mpfr_clear (huge);
519 /* Convert to an integer using the specified rounding mode. */
521 static void
522 gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
524 tree type;
525 tree *args;
526 int nargs;
528 nargs = gfc_intrinsic_argument_list_length (expr);
529 args = XALLOCAVEC (tree, nargs);
531 /* Evaluate the argument, we process all arguments even though we only
532 use the first one for code generation purposes. */
533 type = gfc_typenode_for_spec (&expr->ts);
534 gcc_assert (expr->value.function.actual->expr);
535 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
537 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
539 /* Conversion to a different integer kind. */
540 se->expr = convert (type, args[0]);
542 else
544 /* Conversion from complex to non-complex involves taking the real
545 component of the value. */
546 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
547 && expr->ts.type != BT_COMPLEX)
549 tree artype;
551 artype = TREE_TYPE (TREE_TYPE (args[0]));
552 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
553 args[0]);
556 se->expr = build_fix_expr (&se->pre, args[0], type, op);
561 /* Get the imaginary component of a value. */
563 static void
564 gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
566 tree arg;
568 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
569 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
570 TREE_TYPE (TREE_TYPE (arg)), arg);
574 /* Get the complex conjugate of a value. */
576 static void
577 gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
579 tree arg;
581 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
582 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
587 static tree
588 define_quad_builtin (const char *name, tree type, bool is_const)
590 tree fndecl;
591 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
592 type);
594 /* Mark the decl as external. */
595 DECL_EXTERNAL (fndecl) = 1;
596 TREE_PUBLIC (fndecl) = 1;
598 /* Mark it __attribute__((const)). */
599 TREE_READONLY (fndecl) = is_const;
601 rest_of_decl_compilation (fndecl, 1, 0);
603 return fndecl;
608 /* Initialize function decls for library functions. The external functions
609 are created as required. Builtin functions are added here. */
611 void
612 gfc_build_intrinsic_lib_fndecls (void)
614 gfc_intrinsic_map_t *m;
615 tree quad_decls[END_BUILTINS + 1];
617 if (gfc_real16_is_float128)
619 /* If we have soft-float types, we create the decls for their
620 C99-like library functions. For now, we only handle __float128
621 q-suffixed functions. */
623 tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
624 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
626 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
628 type = float128_type_node;
629 complex_type = complex_float128_type_node;
630 /* type (*) (type) */
631 func_1 = build_function_type_list (type, type, NULL_TREE);
632 /* int (*) (type) */
633 func_iround = build_function_type_list (integer_type_node,
634 type, NULL_TREE);
635 /* long (*) (type) */
636 func_lround = build_function_type_list (long_integer_type_node,
637 type, NULL_TREE);
638 /* long long (*) (type) */
639 func_llround = build_function_type_list (long_long_integer_type_node,
640 type, NULL_TREE);
641 /* type (*) (type, type) */
642 func_2 = build_function_type_list (type, type, type, NULL_TREE);
643 /* type (*) (type, &int) */
644 func_frexp
645 = build_function_type_list (type,
646 type,
647 build_pointer_type (integer_type_node),
648 NULL_TREE);
649 /* type (*) (type, int) */
650 func_scalbn = build_function_type_list (type,
651 type, integer_type_node, NULL_TREE);
652 /* type (*) (complex type) */
653 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
654 /* complex type (*) (complex type, complex type) */
655 func_cpow
656 = build_function_type_list (complex_type,
657 complex_type, complex_type, NULL_TREE);
659 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
660 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
661 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
663 /* Only these built-ins are actually needed here. These are used directly
664 from the code, when calling builtin_decl_for_precision() or
665 builtin_decl_for_float_type(). The others are all constructed by
666 gfc_get_intrinsic_lib_fndecl(). */
667 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
668 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
670 #include "mathbuiltins.def"
672 #undef OTHER_BUILTIN
673 #undef LIB_FUNCTION
674 #undef DEFINE_MATH_BUILTIN
675 #undef DEFINE_MATH_BUILTIN_C
679 /* Add GCC builtin functions. */
680 for (m = gfc_intrinsic_map;
681 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
683 if (m->float_built_in != END_BUILTINS)
684 m->real4_decl = builtin_decl_explicit (m->float_built_in);
685 if (m->complex_float_built_in != END_BUILTINS)
686 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
687 if (m->double_built_in != END_BUILTINS)
688 m->real8_decl = builtin_decl_explicit (m->double_built_in);
689 if (m->complex_double_built_in != END_BUILTINS)
690 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
692 /* If real(kind=10) exists, it is always long double. */
693 if (m->long_double_built_in != END_BUILTINS)
694 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
695 if (m->complex_long_double_built_in != END_BUILTINS)
696 m->complex10_decl
697 = builtin_decl_explicit (m->complex_long_double_built_in);
699 if (!gfc_real16_is_float128)
701 if (m->long_double_built_in != END_BUILTINS)
702 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
703 if (m->complex_long_double_built_in != END_BUILTINS)
704 m->complex16_decl
705 = builtin_decl_explicit (m->complex_long_double_built_in);
707 else if (quad_decls[m->double_built_in] != NULL_TREE)
709 /* Quad-precision function calls are constructed when first
710 needed by builtin_decl_for_precision(), except for those
711 that will be used directly (define by OTHER_BUILTIN). */
712 m->real16_decl = quad_decls[m->double_built_in];
714 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
716 /* Same thing for the complex ones. */
717 m->complex16_decl = quad_decls[m->double_built_in];
723 /* Create a fndecl for a simple intrinsic library function. */
725 static tree
726 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
728 tree type;
729 vec<tree, va_gc> *argtypes;
730 tree fndecl;
731 gfc_actual_arglist *actual;
732 tree *pdecl;
733 gfc_typespec *ts;
734 char name[GFC_MAX_SYMBOL_LEN + 3];
736 ts = &expr->ts;
737 if (ts->type == BT_REAL)
739 switch (ts->kind)
741 case 4:
742 pdecl = &m->real4_decl;
743 break;
744 case 8:
745 pdecl = &m->real8_decl;
746 break;
747 case 10:
748 pdecl = &m->real10_decl;
749 break;
750 case 16:
751 pdecl = &m->real16_decl;
752 break;
753 default:
754 gcc_unreachable ();
757 else if (ts->type == BT_COMPLEX)
759 gcc_assert (m->complex_available);
761 switch (ts->kind)
763 case 4:
764 pdecl = &m->complex4_decl;
765 break;
766 case 8:
767 pdecl = &m->complex8_decl;
768 break;
769 case 10:
770 pdecl = &m->complex10_decl;
771 break;
772 case 16:
773 pdecl = &m->complex16_decl;
774 break;
775 default:
776 gcc_unreachable ();
779 else
780 gcc_unreachable ();
782 if (*pdecl)
783 return *pdecl;
785 if (m->libm_name)
787 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
788 if (gfc_real_kinds[n].c_float)
789 snprintf (name, sizeof (name), "%s%s%s",
790 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
791 else if (gfc_real_kinds[n].c_double)
792 snprintf (name, sizeof (name), "%s%s",
793 ts->type == BT_COMPLEX ? "c" : "", m->name);
794 else if (gfc_real_kinds[n].c_long_double)
795 snprintf (name, sizeof (name), "%s%s%s",
796 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
797 else if (gfc_real_kinds[n].c_float128)
798 snprintf (name, sizeof (name), "%s%s%s",
799 ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
800 else
801 gcc_unreachable ();
803 else
805 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
806 ts->type == BT_COMPLEX ? 'c' : 'r',
807 ts->kind);
810 argtypes = NULL;
811 for (actual = expr->value.function.actual; actual; actual = actual->next)
813 type = gfc_typenode_for_spec (&actual->expr->ts);
814 vec_safe_push (argtypes, type);
816 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
817 fndecl = build_decl (input_location,
818 FUNCTION_DECL, get_identifier (name), type);
820 /* Mark the decl as external. */
821 DECL_EXTERNAL (fndecl) = 1;
822 TREE_PUBLIC (fndecl) = 1;
824 /* Mark it __attribute__((const)), if possible. */
825 TREE_READONLY (fndecl) = m->is_constant;
827 rest_of_decl_compilation (fndecl, 1, 0);
829 (*pdecl) = fndecl;
830 return fndecl;
834 /* Convert an intrinsic function into an external or builtin call. */
836 static void
837 gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
839 gfc_intrinsic_map_t *m;
840 tree fndecl;
841 tree rettype;
842 tree *args;
843 unsigned int num_args;
844 gfc_isym_id id;
846 id = expr->value.function.isym->id;
847 /* Find the entry for this function. */
848 for (m = gfc_intrinsic_map;
849 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
851 if (id == m->id)
852 break;
855 if (m->id == GFC_ISYM_NONE)
857 internal_error ("Intrinsic function %s(%d) not recognized",
858 expr->value.function.name, id);
861 /* Get the decl and generate the call. */
862 num_args = gfc_intrinsic_argument_list_length (expr);
863 args = XALLOCAVEC (tree, num_args);
865 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
866 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
867 rettype = TREE_TYPE (TREE_TYPE (fndecl));
869 fndecl = build_addr (fndecl, current_function_decl);
870 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
874 /* If bounds-checking is enabled, create code to verify at runtime that the
875 string lengths for both expressions are the same (needed for e.g. MERGE).
876 If bounds-checking is not enabled, does nothing. */
878 void
879 gfc_trans_same_strlen_check (const char* intr_name, locus* where,
880 tree a, tree b, stmtblock_t* target)
882 tree cond;
883 tree name;
885 /* If bounds-checking is disabled, do nothing. */
886 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
887 return;
889 /* Compare the two string lengths. */
890 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, a, b);
892 /* Output the runtime-check. */
893 name = gfc_build_cstring_const (intr_name);
894 name = gfc_build_addr_expr (pchar_type_node, name);
895 gfc_trans_runtime_check (true, false, cond, target, where,
896 "Unequal character lengths (%ld/%ld) in %s",
897 fold_convert (long_integer_type_node, a),
898 fold_convert (long_integer_type_node, b), name);
902 /* The EXPONENT(s) intrinsic function is translated into
903 int ret;
904 frexp (s, &ret);
905 return ret;
908 static void
909 gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
911 tree arg, type, res, tmp, frexp;
913 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
914 expr->value.function.actual->expr->ts.kind);
916 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
918 res = gfc_create_var (integer_type_node, NULL);
919 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
920 gfc_build_addr_expr (NULL_TREE, res));
921 gfc_add_expr_to_block (&se->pre, tmp);
923 type = gfc_typenode_for_spec (&expr->ts);
924 se->expr = fold_convert (type, res);
928 static void
929 trans_this_image (gfc_se * se, gfc_expr *expr)
931 stmtblock_t loop;
932 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
933 lbound, ubound, extent, ml;
934 gfc_se argse;
935 int rank, corank;
937 /* The case -fcoarray=single is handled elsewhere. */
938 gcc_assert (gfc_option.coarray != GFC_FCOARRAY_SINGLE);
940 gfc_init_coarray_decl (false);
942 /* Argument-free version: THIS_IMAGE(). */
943 if (expr->value.function.actual->expr == NULL)
945 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
946 gfort_gvar_caf_this_image);
947 return;
950 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
952 type = gfc_get_int_type (gfc_default_integer_kind);
953 corank = gfc_get_corank (expr->value.function.actual->expr);
954 rank = expr->value.function.actual->expr->rank;
956 /* Obtain the descriptor of the COARRAY. */
957 gfc_init_se (&argse, NULL);
958 argse.want_coarray = 1;
959 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
960 gfc_add_block_to_block (&se->pre, &argse.pre);
961 gfc_add_block_to_block (&se->post, &argse.post);
962 desc = argse.expr;
964 if (se->ss)
966 /* Create an implicit second parameter from the loop variable. */
967 gcc_assert (!expr->value.function.actual->next->expr);
968 gcc_assert (corank > 0);
969 gcc_assert (se->loop->dimen == 1);
970 gcc_assert (se->ss->info->expr == expr);
972 dim_arg = se->loop->loopvar[0];
973 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
974 gfc_array_index_type, dim_arg,
975 build_int_cst (TREE_TYPE (dim_arg), 1));
976 gfc_advance_se_ss_chain (se);
978 else
980 /* Use the passed DIM= argument. */
981 gcc_assert (expr->value.function.actual->next->expr);
982 gfc_init_se (&argse, NULL);
983 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
984 gfc_array_index_type);
985 gfc_add_block_to_block (&se->pre, &argse.pre);
986 dim_arg = argse.expr;
988 if (INTEGER_CST_P (dim_arg))
990 int hi, co_dim;
992 hi = TREE_INT_CST_HIGH (dim_arg);
993 co_dim = TREE_INT_CST_LOW (dim_arg);
994 if (hi || co_dim < 1
995 || co_dim > GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc)))
996 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
997 "dimension index", expr->value.function.isym->name,
998 &expr->where);
1000 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1002 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
1003 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1004 dim_arg,
1005 build_int_cst (TREE_TYPE (dim_arg), 1));
1006 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
1007 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1008 dim_arg, tmp);
1009 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1010 boolean_type_node, cond, tmp);
1011 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1012 gfc_msg_fault);
1016 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
1017 one always has a dim_arg argument.
1019 m = this_image() - 1
1020 if (corank == 1)
1022 sub(1) = m + lcobound(corank)
1023 return;
1025 i = rank
1026 min_var = min (rank + corank - 2, rank + dim_arg - 1)
1027 for (;;)
1029 extent = gfc_extent(i)
1030 ml = m
1031 m = m/extent
1032 if (i >= min_var)
1033 goto exit_label
1036 exit_label:
1037 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
1038 : m + lcobound(corank)
1041 /* this_image () - 1. */
1042 tmp = fold_convert (type, gfort_gvar_caf_this_image);
1043 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, tmp,
1044 build_int_cst (type, 1));
1045 if (corank == 1)
1047 /* sub(1) = m + lcobound(corank). */
1048 lbound = gfc_conv_descriptor_lbound_get (desc,
1049 build_int_cst (TREE_TYPE (gfc_array_index_type),
1050 corank+rank-1));
1051 lbound = fold_convert (type, lbound);
1052 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
1054 se->expr = tmp;
1055 return;
1058 m = gfc_create_var (type, NULL);
1059 ml = gfc_create_var (type, NULL);
1060 loop_var = gfc_create_var (integer_type_node, NULL);
1061 min_var = gfc_create_var (integer_type_node, NULL);
1063 /* m = this_image () - 1. */
1064 gfc_add_modify (&se->pre, m, tmp);
1066 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
1067 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
1068 fold_convert (integer_type_node, dim_arg),
1069 build_int_cst (integer_type_node, rank - 1));
1070 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
1071 build_int_cst (integer_type_node, rank + corank - 2),
1072 tmp);
1073 gfc_add_modify (&se->pre, min_var, tmp);
1075 /* i = rank. */
1076 tmp = build_int_cst (integer_type_node, rank);
1077 gfc_add_modify (&se->pre, loop_var, tmp);
1079 exit_label = gfc_build_label_decl (NULL_TREE);
1080 TREE_USED (exit_label) = 1;
1082 /* Loop body. */
1083 gfc_init_block (&loop);
1085 /* ml = m. */
1086 gfc_add_modify (&loop, ml, m);
1088 /* extent = ... */
1089 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
1090 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
1091 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1092 extent = fold_convert (type, extent);
1094 /* m = m/extent. */
1095 gfc_add_modify (&loop, m,
1096 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
1097 m, extent));
1099 /* Exit condition: if (i >= min_var) goto exit_label. */
1100 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, loop_var,
1101 min_var);
1102 tmp = build1_v (GOTO_EXPR, exit_label);
1103 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
1104 build_empty_stmt (input_location));
1105 gfc_add_expr_to_block (&loop, tmp);
1107 /* Increment loop variable: i++. */
1108 gfc_add_modify (&loop, loop_var,
1109 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
1110 loop_var,
1111 build_int_cst (integer_type_node, 1)));
1113 /* Making the loop... actually loop! */
1114 tmp = gfc_finish_block (&loop);
1115 tmp = build1_v (LOOP_EXPR, tmp);
1116 gfc_add_expr_to_block (&se->pre, tmp);
1118 /* The exit label. */
1119 tmp = build1_v (LABEL_EXPR, exit_label);
1120 gfc_add_expr_to_block (&se->pre, tmp);
1122 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
1123 : m + lcobound(corank) */
1125 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, dim_arg,
1126 build_int_cst (TREE_TYPE (dim_arg), corank));
1128 lbound = gfc_conv_descriptor_lbound_get (desc,
1129 fold_build2_loc (input_location, PLUS_EXPR,
1130 gfc_array_index_type, dim_arg,
1131 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
1132 lbound = fold_convert (type, lbound);
1134 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
1135 fold_build2_loc (input_location, MULT_EXPR, type,
1136 m, extent));
1137 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
1139 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
1140 fold_build2_loc (input_location, PLUS_EXPR, type,
1141 m, lbound));
1145 static void
1146 trans_image_index (gfc_se * se, gfc_expr *expr)
1148 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
1149 tmp, invalid_bound;
1150 gfc_se argse, subse;
1151 int rank, corank, codim;
1153 type = gfc_get_int_type (gfc_default_integer_kind);
1154 corank = gfc_get_corank (expr->value.function.actual->expr);
1155 rank = expr->value.function.actual->expr->rank;
1157 /* Obtain the descriptor of the COARRAY. */
1158 gfc_init_se (&argse, NULL);
1159 argse.want_coarray = 1;
1160 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
1161 gfc_add_block_to_block (&se->pre, &argse.pre);
1162 gfc_add_block_to_block (&se->post, &argse.post);
1163 desc = argse.expr;
1165 /* Obtain a handle to the SUB argument. */
1166 gfc_init_se (&subse, NULL);
1167 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
1168 gfc_add_block_to_block (&se->pre, &subse.pre);
1169 gfc_add_block_to_block (&se->post, &subse.post);
1170 subdesc = build_fold_indirect_ref_loc (input_location,
1171 gfc_conv_descriptor_data_get (subse.expr));
1173 /* Fortran 2008 does not require that the values remain in the cobounds,
1174 thus we need explicitly check this - and return 0 if they are exceeded. */
1176 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
1177 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
1178 invalid_bound = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1179 fold_convert (gfc_array_index_type, tmp),
1180 lbound);
1182 for (codim = corank + rank - 2; codim >= rank; codim--)
1184 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1185 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
1186 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
1187 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1188 fold_convert (gfc_array_index_type, tmp),
1189 lbound);
1190 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1191 boolean_type_node, invalid_bound, cond);
1192 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1193 fold_convert (gfc_array_index_type, tmp),
1194 ubound);
1195 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1196 boolean_type_node, invalid_bound, cond);
1199 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
1201 /* See Fortran 2008, C.10 for the following algorithm. */
1203 /* coindex = sub(corank) - lcobound(n). */
1204 coindex = fold_convert (gfc_array_index_type,
1205 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
1206 NULL));
1207 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
1208 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1209 fold_convert (gfc_array_index_type, coindex),
1210 lbound);
1212 for (codim = corank + rank - 2; codim >= rank; codim--)
1214 tree extent, ubound;
1216 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
1217 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1218 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
1219 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1221 /* coindex *= extent. */
1222 coindex = fold_build2_loc (input_location, MULT_EXPR,
1223 gfc_array_index_type, coindex, extent);
1225 /* coindex += sub(codim). */
1226 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
1227 coindex = fold_build2_loc (input_location, PLUS_EXPR,
1228 gfc_array_index_type, coindex,
1229 fold_convert (gfc_array_index_type, tmp));
1231 /* coindex -= lbound(codim). */
1232 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1233 coindex = fold_build2_loc (input_location, MINUS_EXPR,
1234 gfc_array_index_type, coindex, lbound);
1237 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
1238 fold_convert(type, coindex),
1239 build_int_cst (type, 1));
1241 /* Return 0 if "coindex" exceeds num_images(). */
1243 if (gfc_option.coarray == GFC_FCOARRAY_SINGLE)
1244 num_images = build_int_cst (type, 1);
1245 else
1247 gfc_init_coarray_decl (false);
1248 num_images = fold_convert (type, gfort_gvar_caf_num_images);
1251 tmp = gfc_create_var (type, NULL);
1252 gfc_add_modify (&se->pre, tmp, coindex);
1254 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, tmp,
1255 num_images);
1256 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
1257 cond,
1258 fold_convert (boolean_type_node, invalid_bound));
1259 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
1260 build_int_cst (type, 0), tmp);
1264 static void
1265 trans_num_images (gfc_se * se)
1267 gfc_init_coarray_decl (false);
1268 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
1269 gfort_gvar_caf_num_images);
1273 static void
1274 gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
1276 gfc_se argse;
1278 gfc_init_se (&argse, NULL);
1279 argse.data_not_needed = 1;
1280 argse.descriptor_only = 1;
1282 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
1283 gfc_add_block_to_block (&se->pre, &argse.pre);
1284 gfc_add_block_to_block (&se->post, &argse.post);
1286 se->expr = gfc_conv_descriptor_rank (argse.expr);
1290 /* Evaluate a single upper or lower bound. */
1291 /* TODO: bound intrinsic generates way too much unnecessary code. */
1293 static void
1294 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
1296 gfc_actual_arglist *arg;
1297 gfc_actual_arglist *arg2;
1298 tree desc;
1299 tree type;
1300 tree bound;
1301 tree tmp;
1302 tree cond, cond1, cond3, cond4, size;
1303 tree ubound;
1304 tree lbound;
1305 gfc_se argse;
1306 gfc_array_spec * as;
1307 bool assumed_rank_lb_one;
1309 arg = expr->value.function.actual;
1310 arg2 = arg->next;
1312 if (se->ss)
1314 /* Create an implicit second parameter from the loop variable. */
1315 gcc_assert (!arg2->expr);
1316 gcc_assert (se->loop->dimen == 1);
1317 gcc_assert (se->ss->info->expr == expr);
1318 gfc_advance_se_ss_chain (se);
1319 bound = se->loop->loopvar[0];
1320 bound = fold_build2_loc (input_location, MINUS_EXPR,
1321 gfc_array_index_type, bound,
1322 se->loop->from[0]);
1324 else
1326 /* use the passed argument. */
1327 gcc_assert (arg2->expr);
1328 gfc_init_se (&argse, NULL);
1329 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
1330 gfc_add_block_to_block (&se->pre, &argse.pre);
1331 bound = argse.expr;
1332 /* Convert from one based to zero based. */
1333 bound = fold_build2_loc (input_location, MINUS_EXPR,
1334 gfc_array_index_type, bound,
1335 gfc_index_one_node);
1338 /* TODO: don't re-evaluate the descriptor on each iteration. */
1339 /* Get a descriptor for the first parameter. */
1340 gfc_init_se (&argse, NULL);
1341 gfc_conv_expr_descriptor (&argse, arg->expr);
1342 gfc_add_block_to_block (&se->pre, &argse.pre);
1343 gfc_add_block_to_block (&se->post, &argse.post);
1345 desc = argse.expr;
1347 as = gfc_get_full_arrayspec_from_expr (arg->expr);
1349 if (INTEGER_CST_P (bound))
1351 int hi, low;
1353 hi = TREE_INT_CST_HIGH (bound);
1354 low = TREE_INT_CST_LOW (bound);
1355 if (hi || low < 0
1356 || ((!as || as->type != AS_ASSUMED_RANK)
1357 && low >= GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)))
1358 || low > GFC_MAX_DIMENSIONS)
1359 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
1360 "dimension index", upper ? "UBOUND" : "LBOUND",
1361 &expr->where);
1364 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
1366 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1368 bound = gfc_evaluate_now (bound, &se->pre);
1369 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1370 bound, build_int_cst (TREE_TYPE (bound), 0));
1371 if (as && as->type == AS_ASSUMED_RANK)
1372 tmp = gfc_conv_descriptor_rank (desc);
1373 else
1374 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
1375 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1376 bound, fold_convert(TREE_TYPE (bound), tmp));
1377 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1378 boolean_type_node, cond, tmp);
1379 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1380 gfc_msg_fault);
1384 /* Take care of the lbound shift for assumed-rank arrays, which are
1385 nonallocatable and nonpointers. Those has a lbound of 1. */
1386 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
1387 && ((arg->expr->ts.type != BT_CLASS
1388 && !arg->expr->symtree->n.sym->attr.allocatable
1389 && !arg->expr->symtree->n.sym->attr.pointer)
1390 || (arg->expr->ts.type == BT_CLASS
1391 && !CLASS_DATA (arg->expr)->attr.allocatable
1392 && !CLASS_DATA (arg->expr)->attr.class_pointer));
1394 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
1395 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
1397 /* 13.14.53: Result value for LBOUND
1399 Case (i): For an array section or for an array expression other than a
1400 whole array or array structure component, LBOUND(ARRAY, DIM)
1401 has the value 1. For a whole array or array structure
1402 component, LBOUND(ARRAY, DIM) has the value:
1403 (a) equal to the lower bound for subscript DIM of ARRAY if
1404 dimension DIM of ARRAY does not have extent zero
1405 or if ARRAY is an assumed-size array of rank DIM,
1406 or (b) 1 otherwise.
1408 13.14.113: Result value for UBOUND
1410 Case (i): For an array section or for an array expression other than a
1411 whole array or array structure component, UBOUND(ARRAY, DIM)
1412 has the value equal to the number of elements in the given
1413 dimension; otherwise, it has a value equal to the upper bound
1414 for subscript DIM of ARRAY if dimension DIM of ARRAY does
1415 not have size zero and has value zero if dimension DIM has
1416 size zero. */
1418 if (!upper && assumed_rank_lb_one)
1419 se->expr = gfc_index_one_node;
1420 else if (as)
1422 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
1424 cond1 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1425 ubound, lbound);
1426 cond3 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1427 stride, gfc_index_zero_node);
1428 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1429 boolean_type_node, cond3, cond1);
1430 cond4 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1431 stride, gfc_index_zero_node);
1433 if (upper)
1435 tree cond5;
1436 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1437 boolean_type_node, cond3, cond4);
1438 cond5 = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1439 gfc_index_one_node, lbound);
1440 cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1441 boolean_type_node, cond4, cond5);
1443 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1444 boolean_type_node, cond, cond5);
1446 if (assumed_rank_lb_one)
1448 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1449 gfc_array_index_type, ubound, lbound);
1450 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1451 gfc_array_index_type, tmp, gfc_index_one_node);
1453 else
1454 tmp = ubound;
1456 se->expr = fold_build3_loc (input_location, COND_EXPR,
1457 gfc_array_index_type, cond,
1458 tmp, gfc_index_zero_node);
1460 else
1462 if (as->type == AS_ASSUMED_SIZE)
1463 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1464 bound, build_int_cst (TREE_TYPE (bound),
1465 arg->expr->rank - 1));
1466 else
1467 cond = boolean_false_node;
1469 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1470 boolean_type_node, cond3, cond4);
1471 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1472 boolean_type_node, cond, cond1);
1474 se->expr = fold_build3_loc (input_location, COND_EXPR,
1475 gfc_array_index_type, cond,
1476 lbound, gfc_index_one_node);
1479 else
1481 if (upper)
1483 size = fold_build2_loc (input_location, MINUS_EXPR,
1484 gfc_array_index_type, ubound, lbound);
1485 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
1486 gfc_array_index_type, size,
1487 gfc_index_one_node);
1488 se->expr = fold_build2_loc (input_location, MAX_EXPR,
1489 gfc_array_index_type, se->expr,
1490 gfc_index_zero_node);
1492 else
1493 se->expr = gfc_index_one_node;
1496 type = gfc_typenode_for_spec (&expr->ts);
1497 se->expr = convert (type, se->expr);
1501 static void
1502 conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
1504 gfc_actual_arglist *arg;
1505 gfc_actual_arglist *arg2;
1506 gfc_se argse;
1507 tree bound, resbound, resbound2, desc, cond, tmp;
1508 tree type;
1509 int corank;
1511 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
1512 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
1513 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
1515 arg = expr->value.function.actual;
1516 arg2 = arg->next;
1518 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
1519 corank = gfc_get_corank (arg->expr);
1521 gfc_init_se (&argse, NULL);
1522 argse.want_coarray = 1;
1524 gfc_conv_expr_descriptor (&argse, arg->expr);
1525 gfc_add_block_to_block (&se->pre, &argse.pre);
1526 gfc_add_block_to_block (&se->post, &argse.post);
1527 desc = argse.expr;
1529 if (se->ss)
1531 /* Create an implicit second parameter from the loop variable. */
1532 gcc_assert (!arg2->expr);
1533 gcc_assert (corank > 0);
1534 gcc_assert (se->loop->dimen == 1);
1535 gcc_assert (se->ss->info->expr == expr);
1537 bound = se->loop->loopvar[0];
1538 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1539 bound, gfc_rank_cst[arg->expr->rank]);
1540 gfc_advance_se_ss_chain (se);
1542 else
1544 /* use the passed argument. */
1545 gcc_assert (arg2->expr);
1546 gfc_init_se (&argse, NULL);
1547 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
1548 gfc_add_block_to_block (&se->pre, &argse.pre);
1549 bound = argse.expr;
1551 if (INTEGER_CST_P (bound))
1553 int hi, low;
1555 hi = TREE_INT_CST_HIGH (bound);
1556 low = TREE_INT_CST_LOW (bound);
1557 if (hi || low < 1 || low > GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc)))
1558 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
1559 "dimension index", expr->value.function.isym->name,
1560 &expr->where);
1562 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1564 bound = gfc_evaluate_now (bound, &se->pre);
1565 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1566 bound, build_int_cst (TREE_TYPE (bound), 1));
1567 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
1568 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1569 bound, tmp);
1570 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1571 boolean_type_node, cond, tmp);
1572 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1573 gfc_msg_fault);
1577 /* Subtract 1 to get to zero based and add dimensions. */
1578 switch (arg->expr->rank)
1580 case 0:
1581 bound = fold_build2_loc (input_location, MINUS_EXPR,
1582 gfc_array_index_type, bound,
1583 gfc_index_one_node);
1584 case 1:
1585 break;
1586 default:
1587 bound = fold_build2_loc (input_location, PLUS_EXPR,
1588 gfc_array_index_type, bound,
1589 gfc_rank_cst[arg->expr->rank - 1]);
1593 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
1595 /* Handle UCOBOUND with special handling of the last codimension. */
1596 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
1598 /* Last codimension: For -fcoarray=single just return
1599 the lcobound - otherwise add
1600 ceiling (real (num_images ()) / real (size)) - 1
1601 = (num_images () + size - 1) / size - 1
1602 = (num_images - 1) / size(),
1603 where size is the product of the extent of all but the last
1604 codimension. */
1606 if (gfc_option.coarray != GFC_FCOARRAY_SINGLE && corank > 1)
1608 tree cosize;
1610 gfc_init_coarray_decl (false);
1611 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
1613 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1614 gfc_array_index_type,
1615 fold_convert (gfc_array_index_type,
1616 gfort_gvar_caf_num_images),
1617 build_int_cst (gfc_array_index_type, 1));
1618 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1619 gfc_array_index_type, tmp,
1620 fold_convert (gfc_array_index_type, cosize));
1621 resbound = fold_build2_loc (input_location, PLUS_EXPR,
1622 gfc_array_index_type, resbound, tmp);
1624 else if (gfc_option.coarray != GFC_FCOARRAY_SINGLE)
1626 /* ubound = lbound + num_images() - 1. */
1627 gfc_init_coarray_decl (false);
1628 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1629 gfc_array_index_type,
1630 fold_convert (gfc_array_index_type,
1631 gfort_gvar_caf_num_images),
1632 build_int_cst (gfc_array_index_type, 1));
1633 resbound = fold_build2_loc (input_location, PLUS_EXPR,
1634 gfc_array_index_type, resbound, tmp);
1637 if (corank > 1)
1639 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1640 bound,
1641 build_int_cst (TREE_TYPE (bound),
1642 arg->expr->rank + corank - 1));
1644 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
1645 se->expr = fold_build3_loc (input_location, COND_EXPR,
1646 gfc_array_index_type, cond,
1647 resbound, resbound2);
1649 else
1650 se->expr = resbound;
1652 else
1653 se->expr = resbound;
1655 type = gfc_typenode_for_spec (&expr->ts);
1656 se->expr = convert (type, se->expr);
1660 static void
1661 conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
1663 gfc_actual_arglist *array_arg;
1664 gfc_actual_arglist *dim_arg;
1665 gfc_se argse;
1666 tree desc, tmp;
1668 array_arg = expr->value.function.actual;
1669 dim_arg = array_arg->next;
1671 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
1673 gfc_init_se (&argse, NULL);
1674 gfc_conv_expr_descriptor (&argse, array_arg->expr);
1675 gfc_add_block_to_block (&se->pre, &argse.pre);
1676 gfc_add_block_to_block (&se->post, &argse.post);
1677 desc = argse.expr;
1679 gcc_assert (dim_arg->expr);
1680 gfc_init_se (&argse, NULL);
1681 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
1682 gfc_add_block_to_block (&se->pre, &argse.pre);
1683 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1684 argse.expr, gfc_index_one_node);
1685 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
1689 static void
1690 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
1692 tree arg, cabs;
1694 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
1696 switch (expr->value.function.actual->expr->ts.type)
1698 case BT_INTEGER:
1699 case BT_REAL:
1700 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
1701 arg);
1702 break;
1704 case BT_COMPLEX:
1705 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
1706 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
1707 break;
1709 default:
1710 gcc_unreachable ();
1715 /* Create a complex value from one or two real components. */
1717 static void
1718 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
1720 tree real;
1721 tree imag;
1722 tree type;
1723 tree *args;
1724 unsigned int num_args;
1726 num_args = gfc_intrinsic_argument_list_length (expr);
1727 args = XALLOCAVEC (tree, num_args);
1729 type = gfc_typenode_for_spec (&expr->ts);
1730 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
1731 real = convert (TREE_TYPE (type), args[0]);
1732 if (both)
1733 imag = convert (TREE_TYPE (type), args[1]);
1734 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
1736 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
1737 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
1738 imag = convert (TREE_TYPE (type), imag);
1740 else
1741 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
1743 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
1747 /* Remainder function MOD(A, P) = A - INT(A / P) * P
1748 MODULO(A, P) = A - FLOOR (A / P) * P
1750 The obvious algorithms above are numerically instable for large
1751 arguments, hence these intrinsics are instead implemented via calls
1752 to the fmod family of functions. It is the responsibility of the
1753 user to ensure that the second argument is non-zero. */
1755 static void
1756 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
1758 tree type;
1759 tree tmp;
1760 tree test;
1761 tree test2;
1762 tree fmod;
1763 tree zero;
1764 tree args[2];
1766 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1768 switch (expr->ts.type)
1770 case BT_INTEGER:
1771 /* Integer case is easy, we've got a builtin op. */
1772 type = TREE_TYPE (args[0]);
1774 if (modulo)
1775 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
1776 args[0], args[1]);
1777 else
1778 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
1779 args[0], args[1]);
1780 break;
1782 case BT_REAL:
1783 fmod = NULL_TREE;
1784 /* Check if we have a builtin fmod. */
1785 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
1787 /* The builtin should always be available. */
1788 gcc_assert (fmod != NULL_TREE);
1790 tmp = build_addr (fmod, current_function_decl);
1791 se->expr = build_call_array_loc (input_location,
1792 TREE_TYPE (TREE_TYPE (fmod)),
1793 tmp, 2, args);
1794 if (modulo == 0)
1795 return;
1797 type = TREE_TYPE (args[0]);
1799 args[0] = gfc_evaluate_now (args[0], &se->pre);
1800 args[1] = gfc_evaluate_now (args[1], &se->pre);
1802 /* Definition:
1803 modulo = arg - floor (arg/arg2) * arg2
1805 In order to calculate the result accurately, we use the fmod
1806 function as follows.
1808 res = fmod (arg, arg2);
1809 if (res)
1811 if ((arg < 0) xor (arg2 < 0))
1812 res += arg2;
1814 else
1815 res = copysign (0., arg2);
1817 => As two nested ternary exprs:
1819 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
1820 : copysign (0., arg2);
1824 zero = gfc_build_const (type, integer_zero_node);
1825 tmp = gfc_evaluate_now (se->expr, &se->pre);
1826 if (!flag_signed_zeros)
1828 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1829 args[0], zero);
1830 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1831 args[1], zero);
1832 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
1833 boolean_type_node, test, test2);
1834 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1835 tmp, zero);
1836 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1837 boolean_type_node, test, test2);
1838 test = gfc_evaluate_now (test, &se->pre);
1839 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
1840 fold_build2_loc (input_location,
1841 PLUS_EXPR,
1842 type, tmp, args[1]),
1843 tmp);
1845 else
1847 tree expr1, copysign, cscall;
1848 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
1849 expr->ts.kind);
1850 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1851 args[0], zero);
1852 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1853 args[1], zero);
1854 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
1855 boolean_type_node, test, test2);
1856 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
1857 fold_build2_loc (input_location,
1858 PLUS_EXPR,
1859 type, tmp, args[1]),
1860 tmp);
1861 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1862 tmp, zero);
1863 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
1864 args[1]);
1865 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
1866 expr1, cscall);
1868 return;
1870 default:
1871 gcc_unreachable ();
1875 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
1876 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
1877 where the right shifts are logical (i.e. 0's are shifted in).
1878 Because SHIFT_EXPR's want shifts strictly smaller than the integral
1879 type width, we have to special-case both S == 0 and S == BITSIZE(J):
1880 DSHIFTL(I,J,0) = I
1881 DSHIFTL(I,J,BITSIZE) = J
1882 DSHIFTR(I,J,0) = J
1883 DSHIFTR(I,J,BITSIZE) = I. */
1885 static void
1886 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
1888 tree type, utype, stype, arg1, arg2, shift, res, left, right;
1889 tree args[3], cond, tmp;
1890 int bitsize;
1892 gfc_conv_intrinsic_function_args (se, expr, args, 3);
1894 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
1895 type = TREE_TYPE (args[0]);
1896 bitsize = TYPE_PRECISION (type);
1897 utype = unsigned_type_for (type);
1898 stype = TREE_TYPE (args[2]);
1900 arg1 = gfc_evaluate_now (args[0], &se->pre);
1901 arg2 = gfc_evaluate_now (args[1], &se->pre);
1902 shift = gfc_evaluate_now (args[2], &se->pre);
1904 /* The generic case. */
1905 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
1906 build_int_cst (stype, bitsize), shift);
1907 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
1908 arg1, dshiftl ? shift : tmp);
1910 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
1911 fold_convert (utype, arg2), dshiftl ? tmp : shift);
1912 right = fold_convert (type, right);
1914 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
1916 /* Special cases. */
1917 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
1918 build_int_cst (stype, 0));
1919 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
1920 dshiftl ? arg1 : arg2, res);
1922 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
1923 build_int_cst (stype, bitsize));
1924 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
1925 dshiftl ? arg2 : arg1, res);
1927 se->expr = res;
1931 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
1933 static void
1934 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
1936 tree val;
1937 tree tmp;
1938 tree type;
1939 tree zero;
1940 tree args[2];
1942 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1943 type = TREE_TYPE (args[0]);
1945 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
1946 val = gfc_evaluate_now (val, &se->pre);
1948 zero = gfc_build_const (type, integer_zero_node);
1949 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, val, zero);
1950 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
1954 /* SIGN(A, B) is absolute value of A times sign of B.
1955 The real value versions use library functions to ensure the correct
1956 handling of negative zero. Integer case implemented as:
1957 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
1960 static void
1961 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
1963 tree tmp;
1964 tree type;
1965 tree args[2];
1967 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1968 if (expr->ts.type == BT_REAL)
1970 tree abs;
1972 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
1973 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
1975 /* We explicitly have to ignore the minus sign. We do so by using
1976 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
1977 if (!gfc_option.flag_sign_zero
1978 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
1980 tree cond, zero;
1981 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
1982 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1983 args[1], zero);
1984 se->expr = fold_build3_loc (input_location, COND_EXPR,
1985 TREE_TYPE (args[0]), cond,
1986 build_call_expr_loc (input_location, abs, 1,
1987 args[0]),
1988 build_call_expr_loc (input_location, tmp, 2,
1989 args[0], args[1]));
1991 else
1992 se->expr = build_call_expr_loc (input_location, tmp, 2,
1993 args[0], args[1]);
1994 return;
1997 /* Having excluded floating point types, we know we are now dealing
1998 with signed integer types. */
1999 type = TREE_TYPE (args[0]);
2001 /* Args[0] is used multiple times below. */
2002 args[0] = gfc_evaluate_now (args[0], &se->pre);
2004 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
2005 the signs of A and B are the same, and of all ones if they differ. */
2006 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
2007 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
2008 build_int_cst (type, TYPE_PRECISION (type) - 1));
2009 tmp = gfc_evaluate_now (tmp, &se->pre);
2011 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
2012 is all ones (i.e. -1). */
2013 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
2014 fold_build2_loc (input_location, PLUS_EXPR,
2015 type, args[0], tmp), tmp);
2019 /* Test for the presence of an optional argument. */
2021 static void
2022 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
2024 gfc_expr *arg;
2026 arg = expr->value.function.actual->expr;
2027 gcc_assert (arg->expr_type == EXPR_VARIABLE);
2028 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
2029 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
2033 /* Calculate the double precision product of two single precision values. */
2035 static void
2036 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
2038 tree type;
2039 tree args[2];
2041 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2043 /* Convert the args to double precision before multiplying. */
2044 type = gfc_typenode_for_spec (&expr->ts);
2045 args[0] = convert (type, args[0]);
2046 args[1] = convert (type, args[1]);
2047 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
2048 args[1]);
2052 /* Return a length one character string containing an ascii character. */
2054 static void
2055 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
2057 tree arg[2];
2058 tree var;
2059 tree type;
2060 unsigned int num_args;
2062 num_args = gfc_intrinsic_argument_list_length (expr);
2063 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
2065 type = gfc_get_char_type (expr->ts.kind);
2066 var = gfc_create_var (type, "char");
2068 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
2069 gfc_add_modify (&se->pre, var, arg[0]);
2070 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
2071 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
2075 static void
2076 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
2078 tree var;
2079 tree len;
2080 tree tmp;
2081 tree cond;
2082 tree fndecl;
2083 tree *args;
2084 unsigned int num_args;
2086 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2087 args = XALLOCAVEC (tree, num_args);
2089 var = gfc_create_var (pchar_type_node, "pstr");
2090 len = gfc_create_var (gfc_charlen_type_node, "len");
2092 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2093 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2094 args[1] = gfc_build_addr_expr (NULL_TREE, len);
2096 fndecl = build_addr (gfor_fndecl_ctime, current_function_decl);
2097 tmp = build_call_array_loc (input_location,
2098 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
2099 fndecl, num_args, args);
2100 gfc_add_expr_to_block (&se->pre, tmp);
2102 /* Free the temporary afterwards, if necessary. */
2103 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2104 len, build_int_cst (TREE_TYPE (len), 0));
2105 tmp = gfc_call_free (var);
2106 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2107 gfc_add_expr_to_block (&se->post, tmp);
2109 se->expr = var;
2110 se->string_length = len;
2114 static void
2115 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
2117 tree var;
2118 tree len;
2119 tree tmp;
2120 tree cond;
2121 tree fndecl;
2122 tree *args;
2123 unsigned int num_args;
2125 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2126 args = XALLOCAVEC (tree, num_args);
2128 var = gfc_create_var (pchar_type_node, "pstr");
2129 len = gfc_create_var (gfc_charlen_type_node, "len");
2131 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2132 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2133 args[1] = gfc_build_addr_expr (NULL_TREE, len);
2135 fndecl = build_addr (gfor_fndecl_fdate, current_function_decl);
2136 tmp = build_call_array_loc (input_location,
2137 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
2138 fndecl, num_args, args);
2139 gfc_add_expr_to_block (&se->pre, tmp);
2141 /* Free the temporary afterwards, if necessary. */
2142 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2143 len, build_int_cst (TREE_TYPE (len), 0));
2144 tmp = gfc_call_free (var);
2145 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2146 gfc_add_expr_to_block (&se->post, tmp);
2148 se->expr = var;
2149 se->string_length = len;
2153 /* Return a character string containing the tty name. */
2155 static void
2156 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
2158 tree var;
2159 tree len;
2160 tree tmp;
2161 tree cond;
2162 tree fndecl;
2163 tree *args;
2164 unsigned int num_args;
2166 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2167 args = XALLOCAVEC (tree, num_args);
2169 var = gfc_create_var (pchar_type_node, "pstr");
2170 len = gfc_create_var (gfc_charlen_type_node, "len");
2172 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2173 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2174 args[1] = gfc_build_addr_expr (NULL_TREE, len);
2176 fndecl = build_addr (gfor_fndecl_ttynam, current_function_decl);
2177 tmp = build_call_array_loc (input_location,
2178 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
2179 fndecl, num_args, args);
2180 gfc_add_expr_to_block (&se->pre, tmp);
2182 /* Free the temporary afterwards, if necessary. */
2183 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2184 len, build_int_cst (TREE_TYPE (len), 0));
2185 tmp = gfc_call_free (var);
2186 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2187 gfc_add_expr_to_block (&se->post, tmp);
2189 se->expr = var;
2190 se->string_length = len;
2194 /* Get the minimum/maximum value of all the parameters.
2195 minmax (a1, a2, a3, ...)
2197 mvar = a1;
2198 if (a2 .op. mvar || isnan (mvar))
2199 mvar = a2;
2200 if (a3 .op. mvar || isnan (mvar))
2201 mvar = a3;
2203 return mvar
2207 /* TODO: Mismatching types can occur when specific names are used.
2208 These should be handled during resolution. */
2209 static void
2210 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
2212 tree tmp;
2213 tree mvar;
2214 tree val;
2215 tree thencase;
2216 tree *args;
2217 tree type;
2218 gfc_actual_arglist *argexpr;
2219 unsigned int i, nargs;
2221 nargs = gfc_intrinsic_argument_list_length (expr);
2222 args = XALLOCAVEC (tree, nargs);
2224 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
2225 type = gfc_typenode_for_spec (&expr->ts);
2227 argexpr = expr->value.function.actual;
2228 if (TREE_TYPE (args[0]) != type)
2229 args[0] = convert (type, args[0]);
2230 /* Only evaluate the argument once. */
2231 if (TREE_CODE (args[0]) != VAR_DECL && !TREE_CONSTANT (args[0]))
2232 args[0] = gfc_evaluate_now (args[0], &se->pre);
2234 mvar = gfc_create_var (type, "M");
2235 gfc_add_modify (&se->pre, mvar, args[0]);
2236 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
2238 tree cond, isnan;
2240 val = args[i];
2242 /* Handle absent optional arguments by ignoring the comparison. */
2243 if (argexpr->expr->expr_type == EXPR_VARIABLE
2244 && argexpr->expr->symtree->n.sym->attr.optional
2245 && TREE_CODE (val) == INDIRECT_REF)
2246 cond = fold_build2_loc (input_location,
2247 NE_EXPR, boolean_type_node,
2248 TREE_OPERAND (val, 0),
2249 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
2250 else
2252 cond = NULL_TREE;
2254 /* Only evaluate the argument once. */
2255 if (TREE_CODE (val) != VAR_DECL && !TREE_CONSTANT (val))
2256 val = gfc_evaluate_now (val, &se->pre);
2259 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
2261 tmp = fold_build2_loc (input_location, op, boolean_type_node,
2262 convert (type, val), mvar);
2264 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
2265 __builtin_isnan might be made dependent on that module being loaded,
2266 to help performance of programs that don't rely on IEEE semantics. */
2267 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
2269 isnan = build_call_expr_loc (input_location,
2270 builtin_decl_explicit (BUILT_IN_ISNAN),
2271 1, mvar);
2272 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2273 boolean_type_node, tmp,
2274 fold_convert (boolean_type_node, isnan));
2276 tmp = build3_v (COND_EXPR, tmp, thencase,
2277 build_empty_stmt (input_location));
2279 if (cond != NULL_TREE)
2280 tmp = build3_v (COND_EXPR, cond, tmp,
2281 build_empty_stmt (input_location));
2283 gfc_add_expr_to_block (&se->pre, tmp);
2284 argexpr = argexpr->next;
2286 se->expr = mvar;
2290 /* Generate library calls for MIN and MAX intrinsics for character
2291 variables. */
2292 static void
2293 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
2295 tree *args;
2296 tree var, len, fndecl, tmp, cond, function;
2297 unsigned int nargs;
2299 nargs = gfc_intrinsic_argument_list_length (expr);
2300 args = XALLOCAVEC (tree, nargs + 4);
2301 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
2303 /* Create the result variables. */
2304 len = gfc_create_var (gfc_charlen_type_node, "len");
2305 args[0] = gfc_build_addr_expr (NULL_TREE, len);
2306 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
2307 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
2308 args[2] = build_int_cst (integer_type_node, op);
2309 args[3] = build_int_cst (integer_type_node, nargs / 2);
2311 if (expr->ts.kind == 1)
2312 function = gfor_fndecl_string_minmax;
2313 else if (expr->ts.kind == 4)
2314 function = gfor_fndecl_string_minmax_char4;
2315 else
2316 gcc_unreachable ();
2318 /* Make the function call. */
2319 fndecl = build_addr (function, current_function_decl);
2320 tmp = build_call_array_loc (input_location,
2321 TREE_TYPE (TREE_TYPE (function)), fndecl,
2322 nargs + 4, args);
2323 gfc_add_expr_to_block (&se->pre, tmp);
2325 /* Free the temporary afterwards, if necessary. */
2326 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2327 len, build_int_cst (TREE_TYPE (len), 0));
2328 tmp = gfc_call_free (var);
2329 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2330 gfc_add_expr_to_block (&se->post, tmp);
2332 se->expr = var;
2333 se->string_length = len;
2337 /* Create a symbol node for this intrinsic. The symbol from the frontend
2338 has the generic name. */
2340 static gfc_symbol *
2341 gfc_get_symbol_for_expr (gfc_expr * expr)
2343 gfc_symbol *sym;
2345 /* TODO: Add symbols for intrinsic function to the global namespace. */
2346 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
2347 sym = gfc_new_symbol (expr->value.function.name, NULL);
2349 sym->ts = expr->ts;
2350 sym->attr.external = 1;
2351 sym->attr.function = 1;
2352 sym->attr.always_explicit = 1;
2353 sym->attr.proc = PROC_INTRINSIC;
2354 sym->attr.flavor = FL_PROCEDURE;
2355 sym->result = sym;
2356 if (expr->rank > 0)
2358 sym->attr.dimension = 1;
2359 sym->as = gfc_get_array_spec ();
2360 sym->as->type = AS_ASSUMED_SHAPE;
2361 sym->as->rank = expr->rank;
2364 gfc_copy_formal_args_intr (sym, expr->value.function.isym);
2366 return sym;
2369 /* Generate a call to an external intrinsic function. */
2370 static void
2371 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
2373 gfc_symbol *sym;
2374 vec<tree, va_gc> *append_args;
2376 gcc_assert (!se->ss || se->ss->info->expr == expr);
2378 if (se->ss)
2379 gcc_assert (expr->rank > 0);
2380 else
2381 gcc_assert (expr->rank == 0);
2383 sym = gfc_get_symbol_for_expr (expr);
2385 /* Calls to libgfortran_matmul need to be appended special arguments,
2386 to be able to call the BLAS ?gemm functions if required and possible. */
2387 append_args = NULL;
2388 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
2389 && sym->ts.type != BT_LOGICAL)
2391 tree cint = gfc_get_int_type (gfc_c_int_kind);
2393 if (gfc_option.flag_external_blas
2394 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
2395 && (sym->ts.kind == 4 || sym->ts.kind == 8))
2397 tree gemm_fndecl;
2399 if (sym->ts.type == BT_REAL)
2401 if (sym->ts.kind == 4)
2402 gemm_fndecl = gfor_fndecl_sgemm;
2403 else
2404 gemm_fndecl = gfor_fndecl_dgemm;
2406 else
2408 if (sym->ts.kind == 4)
2409 gemm_fndecl = gfor_fndecl_cgemm;
2410 else
2411 gemm_fndecl = gfor_fndecl_zgemm;
2414 vec_alloc (append_args, 3);
2415 append_args->quick_push (build_int_cst (cint, 1));
2416 append_args->quick_push (build_int_cst (cint,
2417 gfc_option.blas_matmul_limit));
2418 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
2419 gemm_fndecl));
2421 else
2423 vec_alloc (append_args, 3);
2424 append_args->quick_push (build_int_cst (cint, 0));
2425 append_args->quick_push (build_int_cst (cint, 0));
2426 append_args->quick_push (null_pointer_node);
2430 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
2431 append_args);
2432 gfc_free_symbol (sym);
2435 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
2436 Implemented as
2437 any(a)
2439 forall (i=...)
2440 if (a[i] != 0)
2441 return 1
2442 end forall
2443 return 0
2445 all(a)
2447 forall (i=...)
2448 if (a[i] == 0)
2449 return 0
2450 end forall
2451 return 1
2454 static void
2455 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
2457 tree resvar;
2458 stmtblock_t block;
2459 stmtblock_t body;
2460 tree type;
2461 tree tmp;
2462 tree found;
2463 gfc_loopinfo loop;
2464 gfc_actual_arglist *actual;
2465 gfc_ss *arrayss;
2466 gfc_se arrayse;
2467 tree exit_label;
2469 if (se->ss)
2471 gfc_conv_intrinsic_funcall (se, expr);
2472 return;
2475 actual = expr->value.function.actual;
2476 type = gfc_typenode_for_spec (&expr->ts);
2477 /* Initialize the result. */
2478 resvar = gfc_create_var (type, "test");
2479 if (op == EQ_EXPR)
2480 tmp = convert (type, boolean_true_node);
2481 else
2482 tmp = convert (type, boolean_false_node);
2483 gfc_add_modify (&se->pre, resvar, tmp);
2485 /* Walk the arguments. */
2486 arrayss = gfc_walk_expr (actual->expr);
2487 gcc_assert (arrayss != gfc_ss_terminator);
2489 /* Initialize the scalarizer. */
2490 gfc_init_loopinfo (&loop);
2491 exit_label = gfc_build_label_decl (NULL_TREE);
2492 TREE_USED (exit_label) = 1;
2493 gfc_add_ss_to_loop (&loop, arrayss);
2495 /* Initialize the loop. */
2496 gfc_conv_ss_startstride (&loop);
2497 gfc_conv_loop_setup (&loop, &expr->where);
2499 gfc_mark_ss_chain_used (arrayss, 1);
2500 /* Generate the loop body. */
2501 gfc_start_scalarized_body (&loop, &body);
2503 /* If the condition matches then set the return value. */
2504 gfc_start_block (&block);
2505 if (op == EQ_EXPR)
2506 tmp = convert (type, boolean_false_node);
2507 else
2508 tmp = convert (type, boolean_true_node);
2509 gfc_add_modify (&block, resvar, tmp);
2511 /* And break out of the loop. */
2512 tmp = build1_v (GOTO_EXPR, exit_label);
2513 gfc_add_expr_to_block (&block, tmp);
2515 found = gfc_finish_block (&block);
2517 /* Check this element. */
2518 gfc_init_se (&arrayse, NULL);
2519 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2520 arrayse.ss = arrayss;
2521 gfc_conv_expr_val (&arrayse, actual->expr);
2523 gfc_add_block_to_block (&body, &arrayse.pre);
2524 tmp = fold_build2_loc (input_location, op, boolean_type_node, arrayse.expr,
2525 build_int_cst (TREE_TYPE (arrayse.expr), 0));
2526 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
2527 gfc_add_expr_to_block (&body, tmp);
2528 gfc_add_block_to_block (&body, &arrayse.post);
2530 gfc_trans_scalarizing_loops (&loop, &body);
2532 /* Add the exit label. */
2533 tmp = build1_v (LABEL_EXPR, exit_label);
2534 gfc_add_expr_to_block (&loop.pre, tmp);
2536 gfc_add_block_to_block (&se->pre, &loop.pre);
2537 gfc_add_block_to_block (&se->pre, &loop.post);
2538 gfc_cleanup_loop (&loop);
2540 se->expr = resvar;
2543 /* COUNT(A) = Number of true elements in A. */
2544 static void
2545 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
2547 tree resvar;
2548 tree type;
2549 stmtblock_t body;
2550 tree tmp;
2551 gfc_loopinfo loop;
2552 gfc_actual_arglist *actual;
2553 gfc_ss *arrayss;
2554 gfc_se arrayse;
2556 if (se->ss)
2558 gfc_conv_intrinsic_funcall (se, expr);
2559 return;
2562 actual = expr->value.function.actual;
2564 type = gfc_typenode_for_spec (&expr->ts);
2565 /* Initialize the result. */
2566 resvar = gfc_create_var (type, "count");
2567 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
2569 /* Walk the arguments. */
2570 arrayss = gfc_walk_expr (actual->expr);
2571 gcc_assert (arrayss != gfc_ss_terminator);
2573 /* Initialize the scalarizer. */
2574 gfc_init_loopinfo (&loop);
2575 gfc_add_ss_to_loop (&loop, arrayss);
2577 /* Initialize the loop. */
2578 gfc_conv_ss_startstride (&loop);
2579 gfc_conv_loop_setup (&loop, &expr->where);
2581 gfc_mark_ss_chain_used (arrayss, 1);
2582 /* Generate the loop body. */
2583 gfc_start_scalarized_body (&loop, &body);
2585 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
2586 resvar, build_int_cst (TREE_TYPE (resvar), 1));
2587 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
2589 gfc_init_se (&arrayse, NULL);
2590 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2591 arrayse.ss = arrayss;
2592 gfc_conv_expr_val (&arrayse, actual->expr);
2593 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
2594 build_empty_stmt (input_location));
2596 gfc_add_block_to_block (&body, &arrayse.pre);
2597 gfc_add_expr_to_block (&body, tmp);
2598 gfc_add_block_to_block (&body, &arrayse.post);
2600 gfc_trans_scalarizing_loops (&loop, &body);
2602 gfc_add_block_to_block (&se->pre, &loop.pre);
2603 gfc_add_block_to_block (&se->pre, &loop.post);
2604 gfc_cleanup_loop (&loop);
2606 se->expr = resvar;
2610 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
2611 struct and return the corresponding loopinfo. */
2613 static gfc_loopinfo *
2614 enter_nested_loop (gfc_se *se)
2616 se->ss = se->ss->nested_ss;
2617 gcc_assert (se->ss == se->ss->loop->ss);
2619 return se->ss->loop;
2623 /* Inline implementation of the sum and product intrinsics. */
2624 static void
2625 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
2626 bool norm2)
2628 tree resvar;
2629 tree scale = NULL_TREE;
2630 tree type;
2631 stmtblock_t body;
2632 stmtblock_t block;
2633 tree tmp;
2634 gfc_loopinfo loop, *ploop;
2635 gfc_actual_arglist *arg_array, *arg_mask;
2636 gfc_ss *arrayss = NULL;
2637 gfc_ss *maskss = NULL;
2638 gfc_se arrayse;
2639 gfc_se maskse;
2640 gfc_se *parent_se;
2641 gfc_expr *arrayexpr;
2642 gfc_expr *maskexpr;
2644 if (expr->rank > 0)
2646 gcc_assert (gfc_inline_intrinsic_function_p (expr));
2647 parent_se = se;
2649 else
2650 parent_se = NULL;
2652 type = gfc_typenode_for_spec (&expr->ts);
2653 /* Initialize the result. */
2654 resvar = gfc_create_var (type, "val");
2655 if (norm2)
2657 /* result = 0.0;
2658 scale = 1.0. */
2659 scale = gfc_create_var (type, "scale");
2660 gfc_add_modify (&se->pre, scale,
2661 gfc_build_const (type, integer_one_node));
2662 tmp = gfc_build_const (type, integer_zero_node);
2664 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
2665 tmp = gfc_build_const (type, integer_zero_node);
2666 else if (op == NE_EXPR)
2667 /* PARITY. */
2668 tmp = convert (type, boolean_false_node);
2669 else if (op == BIT_AND_EXPR)
2670 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
2671 type, integer_one_node));
2672 else
2673 tmp = gfc_build_const (type, integer_one_node);
2675 gfc_add_modify (&se->pre, resvar, tmp);
2677 arg_array = expr->value.function.actual;
2679 arrayexpr = arg_array->expr;
2681 if (op == NE_EXPR || norm2)
2682 /* PARITY and NORM2. */
2683 maskexpr = NULL;
2684 else
2686 arg_mask = arg_array->next->next;
2687 gcc_assert (arg_mask != NULL);
2688 maskexpr = arg_mask->expr;
2691 if (expr->rank == 0)
2693 /* Walk the arguments. */
2694 arrayss = gfc_walk_expr (arrayexpr);
2695 gcc_assert (arrayss != gfc_ss_terminator);
2697 if (maskexpr && maskexpr->rank > 0)
2699 maskss = gfc_walk_expr (maskexpr);
2700 gcc_assert (maskss != gfc_ss_terminator);
2702 else
2703 maskss = NULL;
2705 /* Initialize the scalarizer. */
2706 gfc_init_loopinfo (&loop);
2707 gfc_add_ss_to_loop (&loop, arrayss);
2708 if (maskexpr && maskexpr->rank > 0)
2709 gfc_add_ss_to_loop (&loop, maskss);
2711 /* Initialize the loop. */
2712 gfc_conv_ss_startstride (&loop);
2713 gfc_conv_loop_setup (&loop, &expr->where);
2715 gfc_mark_ss_chain_used (arrayss, 1);
2716 if (maskexpr && maskexpr->rank > 0)
2717 gfc_mark_ss_chain_used (maskss, 1);
2719 ploop = &loop;
2721 else
2722 /* All the work has been done in the parent loops. */
2723 ploop = enter_nested_loop (se);
2725 gcc_assert (ploop);
2727 /* Generate the loop body. */
2728 gfc_start_scalarized_body (ploop, &body);
2730 /* If we have a mask, only add this element if the mask is set. */
2731 if (maskexpr && maskexpr->rank > 0)
2733 gfc_init_se (&maskse, parent_se);
2734 gfc_copy_loopinfo_to_se (&maskse, ploop);
2735 if (expr->rank == 0)
2736 maskse.ss = maskss;
2737 gfc_conv_expr_val (&maskse, maskexpr);
2738 gfc_add_block_to_block (&body, &maskse.pre);
2740 gfc_start_block (&block);
2742 else
2743 gfc_init_block (&block);
2745 /* Do the actual summation/product. */
2746 gfc_init_se (&arrayse, parent_se);
2747 gfc_copy_loopinfo_to_se (&arrayse, ploop);
2748 if (expr->rank == 0)
2749 arrayse.ss = arrayss;
2750 gfc_conv_expr_val (&arrayse, arrayexpr);
2751 gfc_add_block_to_block (&block, &arrayse.pre);
2753 if (norm2)
2755 /* if (x (i) != 0.0)
2757 absX = abs(x(i))
2758 if (absX > scale)
2760 val = scale/absX;
2761 result = 1.0 + result * val * val;
2762 scale = absX;
2764 else
2766 val = absX/scale;
2767 result += val * val;
2769 } */
2770 tree res1, res2, cond, absX, val;
2771 stmtblock_t ifblock1, ifblock2, ifblock3;
2773 gfc_init_block (&ifblock1);
2775 absX = gfc_create_var (type, "absX");
2776 gfc_add_modify (&ifblock1, absX,
2777 fold_build1_loc (input_location, ABS_EXPR, type,
2778 arrayse.expr));
2779 val = gfc_create_var (type, "val");
2780 gfc_add_expr_to_block (&ifblock1, val);
2782 gfc_init_block (&ifblock2);
2783 gfc_add_modify (&ifblock2, val,
2784 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
2785 absX));
2786 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
2787 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
2788 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
2789 gfc_build_const (type, integer_one_node));
2790 gfc_add_modify (&ifblock2, resvar, res1);
2791 gfc_add_modify (&ifblock2, scale, absX);
2792 res1 = gfc_finish_block (&ifblock2);
2794 gfc_init_block (&ifblock3);
2795 gfc_add_modify (&ifblock3, val,
2796 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
2797 scale));
2798 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
2799 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
2800 gfc_add_modify (&ifblock3, resvar, res2);
2801 res2 = gfc_finish_block (&ifblock3);
2803 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2804 absX, scale);
2805 tmp = build3_v (COND_EXPR, cond, res1, res2);
2806 gfc_add_expr_to_block (&ifblock1, tmp);
2807 tmp = gfc_finish_block (&ifblock1);
2809 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
2810 arrayse.expr,
2811 gfc_build_const (type, integer_zero_node));
2813 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2814 gfc_add_expr_to_block (&block, tmp);
2816 else
2818 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
2819 gfc_add_modify (&block, resvar, tmp);
2822 gfc_add_block_to_block (&block, &arrayse.post);
2824 if (maskexpr && maskexpr->rank > 0)
2826 /* We enclose the above in if (mask) {...} . */
2828 tmp = gfc_finish_block (&block);
2829 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2830 build_empty_stmt (input_location));
2832 else
2833 tmp = gfc_finish_block (&block);
2834 gfc_add_expr_to_block (&body, tmp);
2836 gfc_trans_scalarizing_loops (ploop, &body);
2838 /* For a scalar mask, enclose the loop in an if statement. */
2839 if (maskexpr && maskexpr->rank == 0)
2841 gfc_init_block (&block);
2842 gfc_add_block_to_block (&block, &ploop->pre);
2843 gfc_add_block_to_block (&block, &ploop->post);
2844 tmp = gfc_finish_block (&block);
2846 if (expr->rank > 0)
2848 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
2849 build_empty_stmt (input_location));
2850 gfc_advance_se_ss_chain (se);
2852 else
2854 gcc_assert (expr->rank == 0);
2855 gfc_init_se (&maskse, NULL);
2856 gfc_conv_expr_val (&maskse, maskexpr);
2857 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2858 build_empty_stmt (input_location));
2861 gfc_add_expr_to_block (&block, tmp);
2862 gfc_add_block_to_block (&se->pre, &block);
2863 gcc_assert (se->post.head == NULL);
2865 else
2867 gfc_add_block_to_block (&se->pre, &ploop->pre);
2868 gfc_add_block_to_block (&se->pre, &ploop->post);
2871 if (expr->rank == 0)
2872 gfc_cleanup_loop (ploop);
2874 if (norm2)
2876 /* result = scale * sqrt(result). */
2877 tree sqrt;
2878 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
2879 resvar = build_call_expr_loc (input_location,
2880 sqrt, 1, resvar);
2881 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
2884 se->expr = resvar;
2888 /* Inline implementation of the dot_product intrinsic. This function
2889 is based on gfc_conv_intrinsic_arith (the previous function). */
2890 static void
2891 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
2893 tree resvar;
2894 tree type;
2895 stmtblock_t body;
2896 stmtblock_t block;
2897 tree tmp;
2898 gfc_loopinfo loop;
2899 gfc_actual_arglist *actual;
2900 gfc_ss *arrayss1, *arrayss2;
2901 gfc_se arrayse1, arrayse2;
2902 gfc_expr *arrayexpr1, *arrayexpr2;
2904 type = gfc_typenode_for_spec (&expr->ts);
2906 /* Initialize the result. */
2907 resvar = gfc_create_var (type, "val");
2908 if (expr->ts.type == BT_LOGICAL)
2909 tmp = build_int_cst (type, 0);
2910 else
2911 tmp = gfc_build_const (type, integer_zero_node);
2913 gfc_add_modify (&se->pre, resvar, tmp);
2915 /* Walk argument #1. */
2916 actual = expr->value.function.actual;
2917 arrayexpr1 = actual->expr;
2918 arrayss1 = gfc_walk_expr (arrayexpr1);
2919 gcc_assert (arrayss1 != gfc_ss_terminator);
2921 /* Walk argument #2. */
2922 actual = actual->next;
2923 arrayexpr2 = actual->expr;
2924 arrayss2 = gfc_walk_expr (arrayexpr2);
2925 gcc_assert (arrayss2 != gfc_ss_terminator);
2927 /* Initialize the scalarizer. */
2928 gfc_init_loopinfo (&loop);
2929 gfc_add_ss_to_loop (&loop, arrayss1);
2930 gfc_add_ss_to_loop (&loop, arrayss2);
2932 /* Initialize the loop. */
2933 gfc_conv_ss_startstride (&loop);
2934 gfc_conv_loop_setup (&loop, &expr->where);
2936 gfc_mark_ss_chain_used (arrayss1, 1);
2937 gfc_mark_ss_chain_used (arrayss2, 1);
2939 /* Generate the loop body. */
2940 gfc_start_scalarized_body (&loop, &body);
2941 gfc_init_block (&block);
2943 /* Make the tree expression for [conjg(]array1[)]. */
2944 gfc_init_se (&arrayse1, NULL);
2945 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
2946 arrayse1.ss = arrayss1;
2947 gfc_conv_expr_val (&arrayse1, arrayexpr1);
2948 if (expr->ts.type == BT_COMPLEX)
2949 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
2950 arrayse1.expr);
2951 gfc_add_block_to_block (&block, &arrayse1.pre);
2953 /* Make the tree expression for array2. */
2954 gfc_init_se (&arrayse2, NULL);
2955 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
2956 arrayse2.ss = arrayss2;
2957 gfc_conv_expr_val (&arrayse2, arrayexpr2);
2958 gfc_add_block_to_block (&block, &arrayse2.pre);
2960 /* Do the actual product and sum. */
2961 if (expr->ts.type == BT_LOGICAL)
2963 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
2964 arrayse1.expr, arrayse2.expr);
2965 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
2967 else
2969 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
2970 arrayse2.expr);
2971 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
2973 gfc_add_modify (&block, resvar, tmp);
2975 /* Finish up the loop block and the loop. */
2976 tmp = gfc_finish_block (&block);
2977 gfc_add_expr_to_block (&body, tmp);
2979 gfc_trans_scalarizing_loops (&loop, &body);
2980 gfc_add_block_to_block (&se->pre, &loop.pre);
2981 gfc_add_block_to_block (&se->pre, &loop.post);
2982 gfc_cleanup_loop (&loop);
2984 se->expr = resvar;
2988 /* Emit code for minloc or maxloc intrinsic. There are many different cases
2989 we need to handle. For performance reasons we sometimes create two
2990 loops instead of one, where the second one is much simpler.
2991 Examples for minloc intrinsic:
2992 1) Result is an array, a call is generated
2993 2) Array mask is used and NaNs need to be supported:
2994 limit = Infinity;
2995 pos = 0;
2996 S = from;
2997 while (S <= to) {
2998 if (mask[S]) {
2999 if (pos == 0) pos = S + (1 - from);
3000 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3002 S++;
3004 goto lab2;
3005 lab1:;
3006 while (S <= to) {
3007 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3008 S++;
3010 lab2:;
3011 3) NaNs need to be supported, but it is known at compile time or cheaply
3012 at runtime whether array is nonempty or not:
3013 limit = Infinity;
3014 pos = 0;
3015 S = from;
3016 while (S <= to) {
3017 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3018 S++;
3020 if (from <= to) pos = 1;
3021 goto lab2;
3022 lab1:;
3023 while (S <= to) {
3024 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3025 S++;
3027 lab2:;
3028 4) NaNs aren't supported, array mask is used:
3029 limit = infinities_supported ? Infinity : huge (limit);
3030 pos = 0;
3031 S = from;
3032 while (S <= to) {
3033 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3034 S++;
3036 goto lab2;
3037 lab1:;
3038 while (S <= to) {
3039 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3040 S++;
3042 lab2:;
3043 5) Same without array mask:
3044 limit = infinities_supported ? Infinity : huge (limit);
3045 pos = (from <= to) ? 1 : 0;
3046 S = from;
3047 while (S <= to) {
3048 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3049 S++;
3051 For 3) and 5), if mask is scalar, this all goes into a conditional,
3052 setting pos = 0; in the else branch. */
3054 static void
3055 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
3057 stmtblock_t body;
3058 stmtblock_t block;
3059 stmtblock_t ifblock;
3060 stmtblock_t elseblock;
3061 tree limit;
3062 tree type;
3063 tree tmp;
3064 tree cond;
3065 tree elsetmp;
3066 tree ifbody;
3067 tree offset;
3068 tree nonempty;
3069 tree lab1, lab2;
3070 gfc_loopinfo loop;
3071 gfc_actual_arglist *actual;
3072 gfc_ss *arrayss;
3073 gfc_ss *maskss;
3074 gfc_se arrayse;
3075 gfc_se maskse;
3076 gfc_expr *arrayexpr;
3077 gfc_expr *maskexpr;
3078 tree pos;
3079 int n;
3081 if (se->ss)
3083 gfc_conv_intrinsic_funcall (se, expr);
3084 return;
3087 /* Initialize the result. */
3088 pos = gfc_create_var (gfc_array_index_type, "pos");
3089 offset = gfc_create_var (gfc_array_index_type, "offset");
3090 type = gfc_typenode_for_spec (&expr->ts);
3092 /* Walk the arguments. */
3093 actual = expr->value.function.actual;
3094 arrayexpr = actual->expr;
3095 arrayss = gfc_walk_expr (arrayexpr);
3096 gcc_assert (arrayss != gfc_ss_terminator);
3098 actual = actual->next->next;
3099 gcc_assert (actual);
3100 maskexpr = actual->expr;
3101 nonempty = NULL;
3102 if (maskexpr && maskexpr->rank != 0)
3104 maskss = gfc_walk_expr (maskexpr);
3105 gcc_assert (maskss != gfc_ss_terminator);
3107 else
3109 mpz_t asize;
3110 if (gfc_array_size (arrayexpr, &asize))
3112 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
3113 mpz_clear (asize);
3114 nonempty = fold_build2_loc (input_location, GT_EXPR,
3115 boolean_type_node, nonempty,
3116 gfc_index_zero_node);
3118 maskss = NULL;
3121 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
3122 switch (arrayexpr->ts.type)
3124 case BT_REAL:
3125 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
3126 break;
3128 case BT_INTEGER:
3129 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
3130 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
3131 arrayexpr->ts.kind);
3132 break;
3134 default:
3135 gcc_unreachable ();
3138 /* We start with the most negative possible value for MAXLOC, and the most
3139 positive possible value for MINLOC. The most negative possible value is
3140 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
3141 possible value is HUGE in both cases. */
3142 if (op == GT_EXPR)
3143 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
3144 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
3145 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
3146 build_int_cst (type, 1));
3148 gfc_add_modify (&se->pre, limit, tmp);
3150 /* Initialize the scalarizer. */
3151 gfc_init_loopinfo (&loop);
3152 gfc_add_ss_to_loop (&loop, arrayss);
3153 if (maskss)
3154 gfc_add_ss_to_loop (&loop, maskss);
3156 /* Initialize the loop. */
3157 gfc_conv_ss_startstride (&loop);
3159 /* The code generated can have more than one loop in sequence (see the
3160 comment at the function header). This doesn't work well with the
3161 scalarizer, which changes arrays' offset when the scalarization loops
3162 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
3163 are currently inlined in the scalar case only (for which loop is of rank
3164 one). As there is no dependency to care about in that case, there is no
3165 temporary, so that we can use the scalarizer temporary code to handle
3166 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
3167 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
3168 to restore offset.
3169 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
3170 should eventually go away. We could either create two loops properly,
3171 or find another way to save/restore the array offsets between the two
3172 loops (without conflicting with temporary management), or use a single
3173 loop minmaxloc implementation. See PR 31067. */
3174 loop.temp_dim = loop.dimen;
3175 gfc_conv_loop_setup (&loop, &expr->where);
3177 gcc_assert (loop.dimen == 1);
3178 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
3179 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3180 loop.from[0], loop.to[0]);
3182 lab1 = NULL;
3183 lab2 = NULL;
3184 /* Initialize the position to zero, following Fortran 2003. We are free
3185 to do this because Fortran 95 allows the result of an entirely false
3186 mask to be processor dependent. If we know at compile time the array
3187 is non-empty and no MASK is used, we can initialize to 1 to simplify
3188 the inner loop. */
3189 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
3190 gfc_add_modify (&loop.pre, pos,
3191 fold_build3_loc (input_location, COND_EXPR,
3192 gfc_array_index_type,
3193 nonempty, gfc_index_one_node,
3194 gfc_index_zero_node));
3195 else
3197 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
3198 lab1 = gfc_build_label_decl (NULL_TREE);
3199 TREE_USED (lab1) = 1;
3200 lab2 = gfc_build_label_decl (NULL_TREE);
3201 TREE_USED (lab2) = 1;
3204 /* An offset must be added to the loop
3205 counter to obtain the required position. */
3206 gcc_assert (loop.from[0]);
3208 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3209 gfc_index_one_node, loop.from[0]);
3210 gfc_add_modify (&loop.pre, offset, tmp);
3212 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
3213 if (maskss)
3214 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
3215 /* Generate the loop body. */
3216 gfc_start_scalarized_body (&loop, &body);
3218 /* If we have a mask, only check this element if the mask is set. */
3219 if (maskss)
3221 gfc_init_se (&maskse, NULL);
3222 gfc_copy_loopinfo_to_se (&maskse, &loop);
3223 maskse.ss = maskss;
3224 gfc_conv_expr_val (&maskse, maskexpr);
3225 gfc_add_block_to_block (&body, &maskse.pre);
3227 gfc_start_block (&block);
3229 else
3230 gfc_init_block (&block);
3232 /* Compare with the current limit. */
3233 gfc_init_se (&arrayse, NULL);
3234 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3235 arrayse.ss = arrayss;
3236 gfc_conv_expr_val (&arrayse, arrayexpr);
3237 gfc_add_block_to_block (&block, &arrayse.pre);
3239 /* We do the following if this is a more extreme value. */
3240 gfc_start_block (&ifblock);
3242 /* Assign the value to the limit... */
3243 gfc_add_modify (&ifblock, limit, arrayse.expr);
3245 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
3247 stmtblock_t ifblock2;
3248 tree ifbody2;
3250 gfc_start_block (&ifblock2);
3251 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3252 loop.loopvar[0], offset);
3253 gfc_add_modify (&ifblock2, pos, tmp);
3254 ifbody2 = gfc_finish_block (&ifblock2);
3255 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, pos,
3256 gfc_index_zero_node);
3257 tmp = build3_v (COND_EXPR, cond, ifbody2,
3258 build_empty_stmt (input_location));
3259 gfc_add_expr_to_block (&block, tmp);
3262 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3263 loop.loopvar[0], offset);
3264 gfc_add_modify (&ifblock, pos, tmp);
3266 if (lab1)
3267 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
3269 ifbody = gfc_finish_block (&ifblock);
3271 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
3273 if (lab1)
3274 cond = fold_build2_loc (input_location,
3275 op == GT_EXPR ? GE_EXPR : LE_EXPR,
3276 boolean_type_node, arrayse.expr, limit);
3277 else
3278 cond = fold_build2_loc (input_location, op, boolean_type_node,
3279 arrayse.expr, limit);
3281 ifbody = build3_v (COND_EXPR, cond, ifbody,
3282 build_empty_stmt (input_location));
3284 gfc_add_expr_to_block (&block, ifbody);
3286 if (maskss)
3288 /* We enclose the above in if (mask) {...}. */
3289 tmp = gfc_finish_block (&block);
3291 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3292 build_empty_stmt (input_location));
3294 else
3295 tmp = gfc_finish_block (&block);
3296 gfc_add_expr_to_block (&body, tmp);
3298 if (lab1)
3300 gfc_trans_scalarized_loop_boundary (&loop, &body);
3302 if (HONOR_NANS (DECL_MODE (limit)))
3304 if (nonempty != NULL)
3306 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
3307 tmp = build3_v (COND_EXPR, nonempty, ifbody,
3308 build_empty_stmt (input_location));
3309 gfc_add_expr_to_block (&loop.code[0], tmp);
3313 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
3314 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
3316 /* If we have a mask, only check this element if the mask is set. */
3317 if (maskss)
3319 gfc_init_se (&maskse, NULL);
3320 gfc_copy_loopinfo_to_se (&maskse, &loop);
3321 maskse.ss = maskss;
3322 gfc_conv_expr_val (&maskse, maskexpr);
3323 gfc_add_block_to_block (&body, &maskse.pre);
3325 gfc_start_block (&block);
3327 else
3328 gfc_init_block (&block);
3330 /* Compare with the current limit. */
3331 gfc_init_se (&arrayse, NULL);
3332 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3333 arrayse.ss = arrayss;
3334 gfc_conv_expr_val (&arrayse, arrayexpr);
3335 gfc_add_block_to_block (&block, &arrayse.pre);
3337 /* We do the following if this is a more extreme value. */
3338 gfc_start_block (&ifblock);
3340 /* Assign the value to the limit... */
3341 gfc_add_modify (&ifblock, limit, arrayse.expr);
3343 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3344 loop.loopvar[0], offset);
3345 gfc_add_modify (&ifblock, pos, tmp);
3347 ifbody = gfc_finish_block (&ifblock);
3349 cond = fold_build2_loc (input_location, op, boolean_type_node,
3350 arrayse.expr, limit);
3352 tmp = build3_v (COND_EXPR, cond, ifbody,
3353 build_empty_stmt (input_location));
3354 gfc_add_expr_to_block (&block, tmp);
3356 if (maskss)
3358 /* We enclose the above in if (mask) {...}. */
3359 tmp = gfc_finish_block (&block);
3361 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3362 build_empty_stmt (input_location));
3364 else
3365 tmp = gfc_finish_block (&block);
3366 gfc_add_expr_to_block (&body, tmp);
3367 /* Avoid initializing loopvar[0] again, it should be left where
3368 it finished by the first loop. */
3369 loop.from[0] = loop.loopvar[0];
3372 gfc_trans_scalarizing_loops (&loop, &body);
3374 if (lab2)
3375 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
3377 /* For a scalar mask, enclose the loop in an if statement. */
3378 if (maskexpr && maskss == NULL)
3380 gfc_init_se (&maskse, NULL);
3381 gfc_conv_expr_val (&maskse, maskexpr);
3382 gfc_init_block (&block);
3383 gfc_add_block_to_block (&block, &loop.pre);
3384 gfc_add_block_to_block (&block, &loop.post);
3385 tmp = gfc_finish_block (&block);
3387 /* For the else part of the scalar mask, just initialize
3388 the pos variable the same way as above. */
3390 gfc_init_block (&elseblock);
3391 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
3392 elsetmp = gfc_finish_block (&elseblock);
3394 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
3395 gfc_add_expr_to_block (&block, tmp);
3396 gfc_add_block_to_block (&se->pre, &block);
3398 else
3400 gfc_add_block_to_block (&se->pre, &loop.pre);
3401 gfc_add_block_to_block (&se->pre, &loop.post);
3403 gfc_cleanup_loop (&loop);
3405 se->expr = convert (type, pos);
3408 /* Emit code for minval or maxval intrinsic. There are many different cases
3409 we need to handle. For performance reasons we sometimes create two
3410 loops instead of one, where the second one is much simpler.
3411 Examples for minval intrinsic:
3412 1) Result is an array, a call is generated
3413 2) Array mask is used and NaNs need to be supported, rank 1:
3414 limit = Infinity;
3415 nonempty = false;
3416 S = from;
3417 while (S <= to) {
3418 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
3419 S++;
3421 limit = nonempty ? NaN : huge (limit);
3422 lab:
3423 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
3424 3) NaNs need to be supported, but it is known at compile time or cheaply
3425 at runtime whether array is nonempty or not, rank 1:
3426 limit = Infinity;
3427 S = from;
3428 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
3429 limit = (from <= to) ? NaN : huge (limit);
3430 lab:
3431 while (S <= to) { limit = min (a[S], limit); S++; }
3432 4) Array mask is used and NaNs need to be supported, rank > 1:
3433 limit = Infinity;
3434 nonempty = false;
3435 fast = false;
3436 S1 = from1;
3437 while (S1 <= to1) {
3438 S2 = from2;
3439 while (S2 <= to2) {
3440 if (mask[S1][S2]) {
3441 if (fast) limit = min (a[S1][S2], limit);
3442 else {
3443 nonempty = true;
3444 if (a[S1][S2] <= limit) {
3445 limit = a[S1][S2];
3446 fast = true;
3450 S2++;
3452 S1++;
3454 if (!fast)
3455 limit = nonempty ? NaN : huge (limit);
3456 5) NaNs need to be supported, but it is known at compile time or cheaply
3457 at runtime whether array is nonempty or not, rank > 1:
3458 limit = Infinity;
3459 fast = false;
3460 S1 = from1;
3461 while (S1 <= to1) {
3462 S2 = from2;
3463 while (S2 <= to2) {
3464 if (fast) limit = min (a[S1][S2], limit);
3465 else {
3466 if (a[S1][S2] <= limit) {
3467 limit = a[S1][S2];
3468 fast = true;
3471 S2++;
3473 S1++;
3475 if (!fast)
3476 limit = (nonempty_array) ? NaN : huge (limit);
3477 6) NaNs aren't supported, but infinities are. Array mask is used:
3478 limit = Infinity;
3479 nonempty = false;
3480 S = from;
3481 while (S <= to) {
3482 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
3483 S++;
3485 limit = nonempty ? limit : huge (limit);
3486 7) Same without array mask:
3487 limit = Infinity;
3488 S = from;
3489 while (S <= to) { limit = min (a[S], limit); S++; }
3490 limit = (from <= to) ? limit : huge (limit);
3491 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
3492 limit = huge (limit);
3493 S = from;
3494 while (S <= to) { limit = min (a[S], limit); S++); }
3496 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
3497 with array mask instead).
3498 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
3499 setting limit = huge (limit); in the else branch. */
3501 static void
3502 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
3504 tree limit;
3505 tree type;
3506 tree tmp;
3507 tree ifbody;
3508 tree nonempty;
3509 tree nonempty_var;
3510 tree lab;
3511 tree fast;
3512 tree huge_cst = NULL, nan_cst = NULL;
3513 stmtblock_t body;
3514 stmtblock_t block, block2;
3515 gfc_loopinfo loop;
3516 gfc_actual_arglist *actual;
3517 gfc_ss *arrayss;
3518 gfc_ss *maskss;
3519 gfc_se arrayse;
3520 gfc_se maskse;
3521 gfc_expr *arrayexpr;
3522 gfc_expr *maskexpr;
3523 int n;
3525 if (se->ss)
3527 gfc_conv_intrinsic_funcall (se, expr);
3528 return;
3531 type = gfc_typenode_for_spec (&expr->ts);
3532 /* Initialize the result. */
3533 limit = gfc_create_var (type, "limit");
3534 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
3535 switch (expr->ts.type)
3537 case BT_REAL:
3538 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
3539 expr->ts.kind, 0);
3540 if (HONOR_INFINITIES (DECL_MODE (limit)))
3542 REAL_VALUE_TYPE real;
3543 real_inf (&real);
3544 tmp = build_real (type, real);
3546 else
3547 tmp = huge_cst;
3548 if (HONOR_NANS (DECL_MODE (limit)))
3550 REAL_VALUE_TYPE real;
3551 real_nan (&real, "", 1, DECL_MODE (limit));
3552 nan_cst = build_real (type, real);
3554 break;
3556 case BT_INTEGER:
3557 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
3558 break;
3560 default:
3561 gcc_unreachable ();
3564 /* We start with the most negative possible value for MAXVAL, and the most
3565 positive possible value for MINVAL. The most negative possible value is
3566 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
3567 possible value is HUGE in both cases. */
3568 if (op == GT_EXPR)
3570 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
3571 if (huge_cst)
3572 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
3573 TREE_TYPE (huge_cst), huge_cst);
3576 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
3577 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
3578 tmp, build_int_cst (type, 1));
3580 gfc_add_modify (&se->pre, limit, tmp);
3582 /* Walk the arguments. */
3583 actual = expr->value.function.actual;
3584 arrayexpr = actual->expr;
3585 arrayss = gfc_walk_expr (arrayexpr);
3586 gcc_assert (arrayss != gfc_ss_terminator);
3588 actual = actual->next->next;
3589 gcc_assert (actual);
3590 maskexpr = actual->expr;
3591 nonempty = NULL;
3592 if (maskexpr && maskexpr->rank != 0)
3594 maskss = gfc_walk_expr (maskexpr);
3595 gcc_assert (maskss != gfc_ss_terminator);
3597 else
3599 mpz_t asize;
3600 if (gfc_array_size (arrayexpr, &asize))
3602 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
3603 mpz_clear (asize);
3604 nonempty = fold_build2_loc (input_location, GT_EXPR,
3605 boolean_type_node, nonempty,
3606 gfc_index_zero_node);
3608 maskss = NULL;
3611 /* Initialize the scalarizer. */
3612 gfc_init_loopinfo (&loop);
3613 gfc_add_ss_to_loop (&loop, arrayss);
3614 if (maskss)
3615 gfc_add_ss_to_loop (&loop, maskss);
3617 /* Initialize the loop. */
3618 gfc_conv_ss_startstride (&loop);
3620 /* The code generated can have more than one loop in sequence (see the
3621 comment at the function header). This doesn't work well with the
3622 scalarizer, which changes arrays' offset when the scalarization loops
3623 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
3624 are currently inlined in the scalar case only. As there is no dependency
3625 to care about in that case, there is no temporary, so that we can use the
3626 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
3627 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
3628 gfc_trans_scalarized_loop_boundary even later to restore offset.
3629 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
3630 should eventually go away. We could either create two loops properly,
3631 or find another way to save/restore the array offsets between the two
3632 loops (without conflicting with temporary management), or use a single
3633 loop minmaxval implementation. See PR 31067. */
3634 loop.temp_dim = loop.dimen;
3635 gfc_conv_loop_setup (&loop, &expr->where);
3637 if (nonempty == NULL && maskss == NULL
3638 && loop.dimen == 1 && loop.from[0] && loop.to[0])
3639 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3640 loop.from[0], loop.to[0]);
3641 nonempty_var = NULL;
3642 if (nonempty == NULL
3643 && (HONOR_INFINITIES (DECL_MODE (limit))
3644 || HONOR_NANS (DECL_MODE (limit))))
3646 nonempty_var = gfc_create_var (boolean_type_node, "nonempty");
3647 gfc_add_modify (&se->pre, nonempty_var, boolean_false_node);
3648 nonempty = nonempty_var;
3650 lab = NULL;
3651 fast = NULL;
3652 if (HONOR_NANS (DECL_MODE (limit)))
3654 if (loop.dimen == 1)
3656 lab = gfc_build_label_decl (NULL_TREE);
3657 TREE_USED (lab) = 1;
3659 else
3661 fast = gfc_create_var (boolean_type_node, "fast");
3662 gfc_add_modify (&se->pre, fast, boolean_false_node);
3666 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
3667 if (maskss)
3668 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
3669 /* Generate the loop body. */
3670 gfc_start_scalarized_body (&loop, &body);
3672 /* If we have a mask, only add this element if the mask is set. */
3673 if (maskss)
3675 gfc_init_se (&maskse, NULL);
3676 gfc_copy_loopinfo_to_se (&maskse, &loop);
3677 maskse.ss = maskss;
3678 gfc_conv_expr_val (&maskse, maskexpr);
3679 gfc_add_block_to_block (&body, &maskse.pre);
3681 gfc_start_block (&block);
3683 else
3684 gfc_init_block (&block);
3686 /* Compare with the current limit. */
3687 gfc_init_se (&arrayse, NULL);
3688 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3689 arrayse.ss = arrayss;
3690 gfc_conv_expr_val (&arrayse, arrayexpr);
3691 gfc_add_block_to_block (&block, &arrayse.pre);
3693 gfc_init_block (&block2);
3695 if (nonempty_var)
3696 gfc_add_modify (&block2, nonempty_var, boolean_true_node);
3698 if (HONOR_NANS (DECL_MODE (limit)))
3700 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
3701 boolean_type_node, arrayse.expr, limit);
3702 if (lab)
3703 ifbody = build1_v (GOTO_EXPR, lab);
3704 else
3706 stmtblock_t ifblock;
3708 gfc_init_block (&ifblock);
3709 gfc_add_modify (&ifblock, limit, arrayse.expr);
3710 gfc_add_modify (&ifblock, fast, boolean_true_node);
3711 ifbody = gfc_finish_block (&ifblock);
3713 tmp = build3_v (COND_EXPR, tmp, ifbody,
3714 build_empty_stmt (input_location));
3715 gfc_add_expr_to_block (&block2, tmp);
3717 else
3719 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3720 signed zeros. */
3721 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3723 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3724 arrayse.expr, limit);
3725 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3726 tmp = build3_v (COND_EXPR, tmp, ifbody,
3727 build_empty_stmt (input_location));
3728 gfc_add_expr_to_block (&block2, tmp);
3730 else
3732 tmp = fold_build2_loc (input_location,
3733 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3734 type, arrayse.expr, limit);
3735 gfc_add_modify (&block2, limit, tmp);
3739 if (fast)
3741 tree elsebody = gfc_finish_block (&block2);
3743 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3744 signed zeros. */
3745 if (HONOR_NANS (DECL_MODE (limit))
3746 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3748 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3749 arrayse.expr, limit);
3750 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3751 ifbody = build3_v (COND_EXPR, tmp, ifbody,
3752 build_empty_stmt (input_location));
3754 else
3756 tmp = fold_build2_loc (input_location,
3757 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3758 type, arrayse.expr, limit);
3759 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
3761 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
3762 gfc_add_expr_to_block (&block, tmp);
3764 else
3765 gfc_add_block_to_block (&block, &block2);
3767 gfc_add_block_to_block (&block, &arrayse.post);
3769 tmp = gfc_finish_block (&block);
3770 if (maskss)
3771 /* We enclose the above in if (mask) {...}. */
3772 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3773 build_empty_stmt (input_location));
3774 gfc_add_expr_to_block (&body, tmp);
3776 if (lab)
3778 gfc_trans_scalarized_loop_boundary (&loop, &body);
3780 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
3781 nan_cst, huge_cst);
3782 gfc_add_modify (&loop.code[0], limit, tmp);
3783 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
3785 /* If we have a mask, only add this element if the mask is set. */
3786 if (maskss)
3788 gfc_init_se (&maskse, NULL);
3789 gfc_copy_loopinfo_to_se (&maskse, &loop);
3790 maskse.ss = maskss;
3791 gfc_conv_expr_val (&maskse, maskexpr);
3792 gfc_add_block_to_block (&body, &maskse.pre);
3794 gfc_start_block (&block);
3796 else
3797 gfc_init_block (&block);
3799 /* Compare with the current limit. */
3800 gfc_init_se (&arrayse, NULL);
3801 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3802 arrayse.ss = arrayss;
3803 gfc_conv_expr_val (&arrayse, arrayexpr);
3804 gfc_add_block_to_block (&block, &arrayse.pre);
3806 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3807 signed zeros. */
3808 if (HONOR_NANS (DECL_MODE (limit))
3809 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3811 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3812 arrayse.expr, limit);
3813 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3814 tmp = build3_v (COND_EXPR, tmp, ifbody,
3815 build_empty_stmt (input_location));
3816 gfc_add_expr_to_block (&block, tmp);
3818 else
3820 tmp = fold_build2_loc (input_location,
3821 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3822 type, arrayse.expr, limit);
3823 gfc_add_modify (&block, limit, tmp);
3826 gfc_add_block_to_block (&block, &arrayse.post);
3828 tmp = gfc_finish_block (&block);
3829 if (maskss)
3830 /* We enclose the above in if (mask) {...}. */
3831 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3832 build_empty_stmt (input_location));
3833 gfc_add_expr_to_block (&body, tmp);
3834 /* Avoid initializing loopvar[0] again, it should be left where
3835 it finished by the first loop. */
3836 loop.from[0] = loop.loopvar[0];
3838 gfc_trans_scalarizing_loops (&loop, &body);
3840 if (fast)
3842 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
3843 nan_cst, huge_cst);
3844 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
3845 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
3846 ifbody);
3847 gfc_add_expr_to_block (&loop.pre, tmp);
3849 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
3851 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
3852 huge_cst);
3853 gfc_add_modify (&loop.pre, limit, tmp);
3856 /* For a scalar mask, enclose the loop in an if statement. */
3857 if (maskexpr && maskss == NULL)
3859 tree else_stmt;
3861 gfc_init_se (&maskse, NULL);
3862 gfc_conv_expr_val (&maskse, maskexpr);
3863 gfc_init_block (&block);
3864 gfc_add_block_to_block (&block, &loop.pre);
3865 gfc_add_block_to_block (&block, &loop.post);
3866 tmp = gfc_finish_block (&block);
3868 if (HONOR_INFINITIES (DECL_MODE (limit)))
3869 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
3870 else
3871 else_stmt = build_empty_stmt (input_location);
3872 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
3873 gfc_add_expr_to_block (&block, tmp);
3874 gfc_add_block_to_block (&se->pre, &block);
3876 else
3878 gfc_add_block_to_block (&se->pre, &loop.pre);
3879 gfc_add_block_to_block (&se->pre, &loop.post);
3882 gfc_cleanup_loop (&loop);
3884 se->expr = limit;
3887 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
3888 static void
3889 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
3891 tree args[2];
3892 tree type;
3893 tree tmp;
3895 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3896 type = TREE_TYPE (args[0]);
3898 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3899 build_int_cst (type, 1), args[1]);
3900 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
3901 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
3902 build_int_cst (type, 0));
3903 type = gfc_typenode_for_spec (&expr->ts);
3904 se->expr = convert (type, tmp);
3908 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
3909 static void
3910 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
3912 tree args[2];
3914 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3916 /* Convert both arguments to the unsigned type of the same size. */
3917 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
3918 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
3920 /* If they have unequal type size, convert to the larger one. */
3921 if (TYPE_PRECISION (TREE_TYPE (args[0]))
3922 > TYPE_PRECISION (TREE_TYPE (args[1])))
3923 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
3924 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
3925 > TYPE_PRECISION (TREE_TYPE (args[0])))
3926 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
3928 /* Now, we compare them. */
3929 se->expr = fold_build2_loc (input_location, op, boolean_type_node,
3930 args[0], args[1]);
3934 /* Generate code to perform the specified operation. */
3935 static void
3936 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
3938 tree args[2];
3940 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3941 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
3942 args[0], args[1]);
3945 /* Bitwise not. */
3946 static void
3947 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
3949 tree arg;
3951 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3952 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
3953 TREE_TYPE (arg), arg);
3956 /* Set or clear a single bit. */
3957 static void
3958 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
3960 tree args[2];
3961 tree type;
3962 tree tmp;
3963 enum tree_code op;
3965 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3966 type = TREE_TYPE (args[0]);
3968 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3969 build_int_cst (type, 1), args[1]);
3970 if (set)
3971 op = BIT_IOR_EXPR;
3972 else
3974 op = BIT_AND_EXPR;
3975 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
3977 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
3980 /* Extract a sequence of bits.
3981 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
3982 static void
3983 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
3985 tree args[3];
3986 tree type;
3987 tree tmp;
3988 tree mask;
3990 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3991 type = TREE_TYPE (args[0]);
3993 mask = build_int_cst (type, -1);
3994 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
3995 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
3997 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
3999 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
4002 static void
4003 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
4004 bool arithmetic)
4006 tree args[2], type, num_bits, cond;
4008 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4010 args[0] = gfc_evaluate_now (args[0], &se->pre);
4011 args[1] = gfc_evaluate_now (args[1], &se->pre);
4012 type = TREE_TYPE (args[0]);
4014 if (!arithmetic)
4015 args[0] = fold_convert (unsigned_type_for (type), args[0]);
4016 else
4017 gcc_assert (right_shift);
4019 se->expr = fold_build2_loc (input_location,
4020 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
4021 TREE_TYPE (args[0]), args[0], args[1]);
4023 if (!arithmetic)
4024 se->expr = fold_convert (type, se->expr);
4026 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4027 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4028 special case. */
4029 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
4030 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
4031 args[1], num_bits);
4033 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
4034 build_int_cst (type, 0), se->expr);
4037 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
4039 : ((shift >= 0) ? i << shift : i >> -shift)
4040 where all shifts are logical shifts. */
4041 static void
4042 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
4044 tree args[2];
4045 tree type;
4046 tree utype;
4047 tree tmp;
4048 tree width;
4049 tree num_bits;
4050 tree cond;
4051 tree lshift;
4052 tree rshift;
4054 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4056 args[0] = gfc_evaluate_now (args[0], &se->pre);
4057 args[1] = gfc_evaluate_now (args[1], &se->pre);
4059 type = TREE_TYPE (args[0]);
4060 utype = unsigned_type_for (type);
4062 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
4063 args[1]);
4065 /* Left shift if positive. */
4066 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
4068 /* Right shift if negative.
4069 We convert to an unsigned type because we want a logical shift.
4070 The standard doesn't define the case of shifting negative
4071 numbers, and we try to be compatible with other compilers, most
4072 notably g77, here. */
4073 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
4074 utype, convert (utype, args[0]), width));
4076 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, args[1],
4077 build_int_cst (TREE_TYPE (args[1]), 0));
4078 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
4080 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4081 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4082 special case. */
4083 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
4084 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, width,
4085 num_bits);
4086 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
4087 build_int_cst (type, 0), tmp);
4091 /* Circular shift. AKA rotate or barrel shift. */
4093 static void
4094 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
4096 tree *args;
4097 tree type;
4098 tree tmp;
4099 tree lrot;
4100 tree rrot;
4101 tree zero;
4102 unsigned int num_args;
4104 num_args = gfc_intrinsic_argument_list_length (expr);
4105 args = XALLOCAVEC (tree, num_args);
4107 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4109 if (num_args == 3)
4111 /* Use a library function for the 3 parameter version. */
4112 tree int4type = gfc_get_int_type (4);
4114 type = TREE_TYPE (args[0]);
4115 /* We convert the first argument to at least 4 bytes, and
4116 convert back afterwards. This removes the need for library
4117 functions for all argument sizes, and function will be
4118 aligned to at least 32 bits, so there's no loss. */
4119 if (expr->ts.kind < 4)
4120 args[0] = convert (int4type, args[0]);
4122 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
4123 need loads of library functions. They cannot have values >
4124 BIT_SIZE (I) so the conversion is safe. */
4125 args[1] = convert (int4type, args[1]);
4126 args[2] = convert (int4type, args[2]);
4128 switch (expr->ts.kind)
4130 case 1:
4131 case 2:
4132 case 4:
4133 tmp = gfor_fndecl_math_ishftc4;
4134 break;
4135 case 8:
4136 tmp = gfor_fndecl_math_ishftc8;
4137 break;
4138 case 16:
4139 tmp = gfor_fndecl_math_ishftc16;
4140 break;
4141 default:
4142 gcc_unreachable ();
4144 se->expr = build_call_expr_loc (input_location,
4145 tmp, 3, args[0], args[1], args[2]);
4146 /* Convert the result back to the original type, if we extended
4147 the first argument's width above. */
4148 if (expr->ts.kind < 4)
4149 se->expr = convert (type, se->expr);
4151 return;
4153 type = TREE_TYPE (args[0]);
4155 /* Evaluate arguments only once. */
4156 args[0] = gfc_evaluate_now (args[0], &se->pre);
4157 args[1] = gfc_evaluate_now (args[1], &se->pre);
4159 /* Rotate left if positive. */
4160 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
4162 /* Rotate right if negative. */
4163 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
4164 args[1]);
4165 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
4167 zero = build_int_cst (TREE_TYPE (args[1]), 0);
4168 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, args[1],
4169 zero);
4170 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
4172 /* Do nothing if shift == 0. */
4173 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, args[1],
4174 zero);
4175 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
4176 rrot);
4180 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
4181 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
4183 The conditional expression is necessary because the result of LEADZ(0)
4184 is defined, but the result of __builtin_clz(0) is undefined for most
4185 targets.
4187 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
4188 difference in bit size between the argument of LEADZ and the C int. */
4190 static void
4191 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
4193 tree arg;
4194 tree arg_type;
4195 tree cond;
4196 tree result_type;
4197 tree leadz;
4198 tree bit_size;
4199 tree tmp;
4200 tree func;
4201 int s, argsize;
4203 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4204 argsize = TYPE_PRECISION (TREE_TYPE (arg));
4206 /* Which variant of __builtin_clz* should we call? */
4207 if (argsize <= INT_TYPE_SIZE)
4209 arg_type = unsigned_type_node;
4210 func = builtin_decl_explicit (BUILT_IN_CLZ);
4212 else if (argsize <= LONG_TYPE_SIZE)
4214 arg_type = long_unsigned_type_node;
4215 func = builtin_decl_explicit (BUILT_IN_CLZL);
4217 else if (argsize <= LONG_LONG_TYPE_SIZE)
4219 arg_type = long_long_unsigned_type_node;
4220 func = builtin_decl_explicit (BUILT_IN_CLZLL);
4222 else
4224 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4225 arg_type = gfc_build_uint_type (argsize);
4226 func = NULL_TREE;
4229 /* Convert the actual argument twice: first, to the unsigned type of the
4230 same size; then, to the proper argument type for the built-in
4231 function. But the return type is of the default INTEGER kind. */
4232 arg = fold_convert (gfc_build_uint_type (argsize), arg);
4233 arg = fold_convert (arg_type, arg);
4234 arg = gfc_evaluate_now (arg, &se->pre);
4235 result_type = gfc_get_int_type (gfc_default_integer_kind);
4237 /* Compute LEADZ for the case i .ne. 0. */
4238 if (func)
4240 s = TYPE_PRECISION (arg_type) - argsize;
4241 tmp = fold_convert (result_type,
4242 build_call_expr_loc (input_location, func,
4243 1, arg));
4244 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
4245 tmp, build_int_cst (result_type, s));
4247 else
4249 /* We end up here if the argument type is larger than 'long long'.
4250 We generate this code:
4252 if (x & (ULL_MAX << ULL_SIZE) != 0)
4253 return clzll ((unsigned long long) (x >> ULLSIZE));
4254 else
4255 return ULL_SIZE + clzll ((unsigned long long) x);
4256 where ULL_MAX is the largest value that a ULL_MAX can hold
4257 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
4258 is the bit-size of the long long type (64 in this example). */
4259 tree ullsize, ullmax, tmp1, tmp2, btmp;
4261 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
4262 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
4263 long_long_unsigned_type_node,
4264 build_int_cst (long_long_unsigned_type_node,
4265 0));
4267 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
4268 fold_convert (arg_type, ullmax), ullsize);
4269 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
4270 arg, cond);
4271 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
4272 cond, build_int_cst (arg_type, 0));
4274 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
4275 arg, ullsize);
4276 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
4277 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4278 tmp1 = fold_convert (result_type,
4279 build_call_expr_loc (input_location, btmp, 1, tmp1));
4281 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
4282 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4283 tmp2 = fold_convert (result_type,
4284 build_call_expr_loc (input_location, btmp, 1, tmp2));
4285 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4286 tmp2, ullsize);
4288 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
4289 cond, tmp1, tmp2);
4292 /* Build BIT_SIZE. */
4293 bit_size = build_int_cst (result_type, argsize);
4295 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4296 arg, build_int_cst (arg_type, 0));
4297 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
4298 bit_size, leadz);
4302 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
4304 The conditional expression is necessary because the result of TRAILZ(0)
4305 is defined, but the result of __builtin_ctz(0) is undefined for most
4306 targets. */
4308 static void
4309 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
4311 tree arg;
4312 tree arg_type;
4313 tree cond;
4314 tree result_type;
4315 tree trailz;
4316 tree bit_size;
4317 tree func;
4318 int argsize;
4320 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4321 argsize = TYPE_PRECISION (TREE_TYPE (arg));
4323 /* Which variant of __builtin_ctz* should we call? */
4324 if (argsize <= INT_TYPE_SIZE)
4326 arg_type = unsigned_type_node;
4327 func = builtin_decl_explicit (BUILT_IN_CTZ);
4329 else if (argsize <= LONG_TYPE_SIZE)
4331 arg_type = long_unsigned_type_node;
4332 func = builtin_decl_explicit (BUILT_IN_CTZL);
4334 else if (argsize <= LONG_LONG_TYPE_SIZE)
4336 arg_type = long_long_unsigned_type_node;
4337 func = builtin_decl_explicit (BUILT_IN_CTZLL);
4339 else
4341 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4342 arg_type = gfc_build_uint_type (argsize);
4343 func = NULL_TREE;
4346 /* Convert the actual argument twice: first, to the unsigned type of the
4347 same size; then, to the proper argument type for the built-in
4348 function. But the return type is of the default INTEGER kind. */
4349 arg = fold_convert (gfc_build_uint_type (argsize), arg);
4350 arg = fold_convert (arg_type, arg);
4351 arg = gfc_evaluate_now (arg, &se->pre);
4352 result_type = gfc_get_int_type (gfc_default_integer_kind);
4354 /* Compute TRAILZ for the case i .ne. 0. */
4355 if (func)
4356 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
4357 func, 1, arg));
4358 else
4360 /* We end up here if the argument type is larger than 'long long'.
4361 We generate this code:
4363 if ((x & ULL_MAX) == 0)
4364 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
4365 else
4366 return ctzll ((unsigned long long) x);
4368 where ULL_MAX is the largest value that a ULL_MAX can hold
4369 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
4370 is the bit-size of the long long type (64 in this example). */
4371 tree ullsize, ullmax, tmp1, tmp2, btmp;
4373 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
4374 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
4375 long_long_unsigned_type_node,
4376 build_int_cst (long_long_unsigned_type_node, 0));
4378 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
4379 fold_convert (arg_type, ullmax));
4380 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, cond,
4381 build_int_cst (arg_type, 0));
4383 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
4384 arg, ullsize);
4385 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
4386 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
4387 tmp1 = fold_convert (result_type,
4388 build_call_expr_loc (input_location, btmp, 1, tmp1));
4389 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4390 tmp1, ullsize);
4392 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
4393 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
4394 tmp2 = fold_convert (result_type,
4395 build_call_expr_loc (input_location, btmp, 1, tmp2));
4397 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
4398 cond, tmp1, tmp2);
4401 /* Build BIT_SIZE. */
4402 bit_size = build_int_cst (result_type, argsize);
4404 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4405 arg, build_int_cst (arg_type, 0));
4406 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
4407 bit_size, trailz);
4410 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
4411 for types larger than "long long", we call the long long built-in for
4412 the lower and higher bits and combine the result. */
4414 static void
4415 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
4417 tree arg;
4418 tree arg_type;
4419 tree result_type;
4420 tree func;
4421 int argsize;
4423 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4424 argsize = TYPE_PRECISION (TREE_TYPE (arg));
4425 result_type = gfc_get_int_type (gfc_default_integer_kind);
4427 /* Which variant of the builtin should we call? */
4428 if (argsize <= INT_TYPE_SIZE)
4430 arg_type = unsigned_type_node;
4431 func = builtin_decl_explicit (parity
4432 ? BUILT_IN_PARITY
4433 : BUILT_IN_POPCOUNT);
4435 else if (argsize <= LONG_TYPE_SIZE)
4437 arg_type = long_unsigned_type_node;
4438 func = builtin_decl_explicit (parity
4439 ? BUILT_IN_PARITYL
4440 : BUILT_IN_POPCOUNTL);
4442 else if (argsize <= LONG_LONG_TYPE_SIZE)
4444 arg_type = long_long_unsigned_type_node;
4445 func = builtin_decl_explicit (parity
4446 ? BUILT_IN_PARITYLL
4447 : BUILT_IN_POPCOUNTLL);
4449 else
4451 /* Our argument type is larger than 'long long', which mean none
4452 of the POPCOUNT builtins covers it. We thus call the 'long long'
4453 variant multiple times, and add the results. */
4454 tree utype, arg2, call1, call2;
4456 /* For now, we only cover the case where argsize is twice as large
4457 as 'long long'. */
4458 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4460 func = builtin_decl_explicit (parity
4461 ? BUILT_IN_PARITYLL
4462 : BUILT_IN_POPCOUNTLL);
4464 /* Convert it to an integer, and store into a variable. */
4465 utype = gfc_build_uint_type (argsize);
4466 arg = fold_convert (utype, arg);
4467 arg = gfc_evaluate_now (arg, &se->pre);
4469 /* Call the builtin twice. */
4470 call1 = build_call_expr_loc (input_location, func, 1,
4471 fold_convert (long_long_unsigned_type_node,
4472 arg));
4474 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
4475 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
4476 call2 = build_call_expr_loc (input_location, func, 1,
4477 fold_convert (long_long_unsigned_type_node,
4478 arg2));
4480 /* Combine the results. */
4481 if (parity)
4482 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
4483 call1, call2);
4484 else
4485 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4486 call1, call2);
4488 return;
4491 /* Convert the actual argument twice: first, to the unsigned type of the
4492 same size; then, to the proper argument type for the built-in
4493 function. */
4494 arg = fold_convert (gfc_build_uint_type (argsize), arg);
4495 arg = fold_convert (arg_type, arg);
4497 se->expr = fold_convert (result_type,
4498 build_call_expr_loc (input_location, func, 1, arg));
4502 /* Process an intrinsic with unspecified argument-types that has an optional
4503 argument (which could be of type character), e.g. EOSHIFT. For those, we
4504 need to append the string length of the optional argument if it is not
4505 present and the type is really character.
4506 primary specifies the position (starting at 1) of the non-optional argument
4507 specifying the type and optional gives the position of the optional
4508 argument in the arglist. */
4510 static void
4511 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
4512 unsigned primary, unsigned optional)
4514 gfc_actual_arglist* prim_arg;
4515 gfc_actual_arglist* opt_arg;
4516 unsigned cur_pos;
4517 gfc_actual_arglist* arg;
4518 gfc_symbol* sym;
4519 vec<tree, va_gc> *append_args;
4521 /* Find the two arguments given as position. */
4522 cur_pos = 0;
4523 prim_arg = NULL;
4524 opt_arg = NULL;
4525 for (arg = expr->value.function.actual; arg; arg = arg->next)
4527 ++cur_pos;
4529 if (cur_pos == primary)
4530 prim_arg = arg;
4531 if (cur_pos == optional)
4532 opt_arg = arg;
4534 if (cur_pos >= primary && cur_pos >= optional)
4535 break;
4537 gcc_assert (prim_arg);
4538 gcc_assert (prim_arg->expr);
4539 gcc_assert (opt_arg);
4541 /* If we do have type CHARACTER and the optional argument is really absent,
4542 append a dummy 0 as string length. */
4543 append_args = NULL;
4544 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
4546 tree dummy;
4548 dummy = build_int_cst (gfc_charlen_type_node, 0);
4549 vec_alloc (append_args, 1);
4550 append_args->quick_push (dummy);
4553 /* Build the call itself. */
4554 sym = gfc_get_symbol_for_expr (expr);
4555 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4556 append_args);
4557 gfc_free_symbol (sym);
4561 /* The length of a character string. */
4562 static void
4563 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
4565 tree len;
4566 tree type;
4567 tree decl;
4568 gfc_symbol *sym;
4569 gfc_se argse;
4570 gfc_expr *arg;
4572 gcc_assert (!se->ss);
4574 arg = expr->value.function.actual->expr;
4576 type = gfc_typenode_for_spec (&expr->ts);
4577 switch (arg->expr_type)
4579 case EXPR_CONSTANT:
4580 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
4581 break;
4583 case EXPR_ARRAY:
4584 /* Obtain the string length from the function used by
4585 trans-array.c(gfc_trans_array_constructor). */
4586 len = NULL_TREE;
4587 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
4588 break;
4590 case EXPR_VARIABLE:
4591 if (arg->ref == NULL
4592 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
4594 /* This doesn't catch all cases.
4595 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
4596 and the surrounding thread. */
4597 sym = arg->symtree->n.sym;
4598 decl = gfc_get_symbol_decl (sym);
4599 if (decl == current_function_decl && sym->attr.function
4600 && (sym->result == sym))
4601 decl = gfc_get_fake_result_decl (sym, 0);
4603 len = sym->ts.u.cl->backend_decl;
4604 gcc_assert (len);
4605 break;
4608 /* Otherwise fall through. */
4610 default:
4611 /* Anybody stupid enough to do this deserves inefficient code. */
4612 gfc_init_se (&argse, se);
4613 if (arg->rank == 0)
4614 gfc_conv_expr (&argse, arg);
4615 else
4616 gfc_conv_expr_descriptor (&argse, arg);
4617 gfc_add_block_to_block (&se->pre, &argse.pre);
4618 gfc_add_block_to_block (&se->post, &argse.post);
4619 len = argse.string_length;
4620 break;
4622 se->expr = convert (type, len);
4625 /* The length of a character string not including trailing blanks. */
4626 static void
4627 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
4629 int kind = expr->value.function.actual->expr->ts.kind;
4630 tree args[2], type, fndecl;
4632 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4633 type = gfc_typenode_for_spec (&expr->ts);
4635 if (kind == 1)
4636 fndecl = gfor_fndecl_string_len_trim;
4637 else if (kind == 4)
4638 fndecl = gfor_fndecl_string_len_trim_char4;
4639 else
4640 gcc_unreachable ();
4642 se->expr = build_call_expr_loc (input_location,
4643 fndecl, 2, args[0], args[1]);
4644 se->expr = convert (type, se->expr);
4648 /* Returns the starting position of a substring within a string. */
4650 static void
4651 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
4652 tree function)
4654 tree logical4_type_node = gfc_get_logical_type (4);
4655 tree type;
4656 tree fndecl;
4657 tree *args;
4658 unsigned int num_args;
4660 args = XALLOCAVEC (tree, 5);
4662 /* Get number of arguments; characters count double due to the
4663 string length argument. Kind= is not passed to the library
4664 and thus ignored. */
4665 if (expr->value.function.actual->next->next->expr == NULL)
4666 num_args = 4;
4667 else
4668 num_args = 5;
4670 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4671 type = gfc_typenode_for_spec (&expr->ts);
4673 if (num_args == 4)
4674 args[4] = build_int_cst (logical4_type_node, 0);
4675 else
4676 args[4] = convert (logical4_type_node, args[4]);
4678 fndecl = build_addr (function, current_function_decl);
4679 se->expr = build_call_array_loc (input_location,
4680 TREE_TYPE (TREE_TYPE (function)), fndecl,
4681 5, args);
4682 se->expr = convert (type, se->expr);
4686 /* The ascii value for a single character. */
4687 static void
4688 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
4690 tree args[3], type, pchartype;
4691 int nargs;
4693 nargs = gfc_intrinsic_argument_list_length (expr);
4694 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
4695 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
4696 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
4697 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
4698 type = gfc_typenode_for_spec (&expr->ts);
4700 se->expr = build_fold_indirect_ref_loc (input_location,
4701 args[1]);
4702 se->expr = convert (type, se->expr);
4706 /* Intrinsic ISNAN calls __builtin_isnan. */
4708 static void
4709 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
4711 tree arg;
4713 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4714 se->expr = build_call_expr_loc (input_location,
4715 builtin_decl_explicit (BUILT_IN_ISNAN),
4716 1, arg);
4717 STRIP_TYPE_NOPS (se->expr);
4718 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
4722 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
4723 their argument against a constant integer value. */
4725 static void
4726 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
4728 tree arg;
4730 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4731 se->expr = fold_build2_loc (input_location, EQ_EXPR,
4732 gfc_typenode_for_spec (&expr->ts),
4733 arg, build_int_cst (TREE_TYPE (arg), value));
4738 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
4740 static void
4741 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
4743 tree tsource;
4744 tree fsource;
4745 tree mask;
4746 tree type;
4747 tree len, len2;
4748 tree *args;
4749 unsigned int num_args;
4751 num_args = gfc_intrinsic_argument_list_length (expr);
4752 args = XALLOCAVEC (tree, num_args);
4754 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4755 if (expr->ts.type != BT_CHARACTER)
4757 tsource = args[0];
4758 fsource = args[1];
4759 mask = args[2];
4761 else
4763 /* We do the same as in the non-character case, but the argument
4764 list is different because of the string length arguments. We
4765 also have to set the string length for the result. */
4766 len = args[0];
4767 tsource = args[1];
4768 len2 = args[2];
4769 fsource = args[3];
4770 mask = args[4];
4772 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
4773 &se->pre);
4774 se->string_length = len;
4776 type = TREE_TYPE (tsource);
4777 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
4778 fold_convert (type, fsource));
4782 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
4784 static void
4785 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
4787 tree args[3], mask, type;
4789 gfc_conv_intrinsic_function_args (se, expr, args, 3);
4790 mask = gfc_evaluate_now (args[2], &se->pre);
4792 type = TREE_TYPE (args[0]);
4793 gcc_assert (TREE_TYPE (args[1]) == type);
4794 gcc_assert (TREE_TYPE (mask) == type);
4796 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
4797 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
4798 fold_build1_loc (input_location, BIT_NOT_EXPR,
4799 type, mask));
4800 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
4801 args[0], args[1]);
4805 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
4806 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
4808 static void
4809 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
4811 tree arg, allones, type, utype, res, cond, bitsize;
4812 int i;
4814 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4815 arg = gfc_evaluate_now (arg, &se->pre);
4817 type = gfc_get_int_type (expr->ts.kind);
4818 utype = unsigned_type_for (type);
4820 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
4821 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
4823 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
4824 build_int_cst (utype, 0));
4826 if (left)
4828 /* Left-justified mask. */
4829 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
4830 bitsize, arg);
4831 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
4832 fold_convert (utype, res));
4834 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
4835 smaller than type width. */
4836 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
4837 build_int_cst (TREE_TYPE (arg), 0));
4838 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
4839 build_int_cst (utype, 0), res);
4841 else
4843 /* Right-justified mask. */
4844 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
4845 fold_convert (utype, arg));
4846 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
4848 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
4849 strictly smaller than type width. */
4850 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4851 arg, bitsize);
4852 res = fold_build3_loc (input_location, COND_EXPR, utype,
4853 cond, allones, res);
4856 se->expr = fold_convert (type, res);
4860 /* FRACTION (s) is translated into frexp (s, &dummy_int). */
4861 static void
4862 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
4864 tree arg, type, tmp, frexp;
4866 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4868 type = gfc_typenode_for_spec (&expr->ts);
4869 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4870 tmp = gfc_create_var (integer_type_node, NULL);
4871 se->expr = build_call_expr_loc (input_location, frexp, 2,
4872 fold_convert (type, arg),
4873 gfc_build_addr_expr (NULL_TREE, tmp));
4874 se->expr = fold_convert (type, se->expr);
4878 /* NEAREST (s, dir) is translated into
4879 tmp = copysign (HUGE_VAL, dir);
4880 return nextafter (s, tmp);
4882 static void
4883 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
4885 tree args[2], type, tmp, nextafter, copysign, huge_val;
4887 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
4888 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
4890 type = gfc_typenode_for_spec (&expr->ts);
4891 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4893 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
4894 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
4895 fold_convert (type, args[1]));
4896 se->expr = build_call_expr_loc (input_location, nextafter, 2,
4897 fold_convert (type, args[0]), tmp);
4898 se->expr = fold_convert (type, se->expr);
4902 /* SPACING (s) is translated into
4903 int e;
4904 if (s == 0)
4905 res = tiny;
4906 else
4908 frexp (s, &e);
4909 e = e - prec;
4910 e = MAX_EXPR (e, emin);
4911 res = scalbn (1., e);
4913 return res;
4915 where prec is the precision of s, gfc_real_kinds[k].digits,
4916 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
4917 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
4919 static void
4920 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
4922 tree arg, type, prec, emin, tiny, res, e;
4923 tree cond, tmp, frexp, scalbn;
4924 int k;
4925 stmtblock_t block;
4927 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
4928 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
4929 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
4930 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
4932 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4933 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
4935 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4936 arg = gfc_evaluate_now (arg, &se->pre);
4938 type = gfc_typenode_for_spec (&expr->ts);
4939 e = gfc_create_var (integer_type_node, NULL);
4940 res = gfc_create_var (type, NULL);
4943 /* Build the block for s /= 0. */
4944 gfc_start_block (&block);
4945 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
4946 gfc_build_addr_expr (NULL_TREE, e));
4947 gfc_add_expr_to_block (&block, tmp);
4949 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
4950 prec);
4951 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
4952 integer_type_node, tmp, emin));
4954 tmp = build_call_expr_loc (input_location, scalbn, 2,
4955 build_real_from_int_cst (type, integer_one_node), e);
4956 gfc_add_modify (&block, res, tmp);
4958 /* Finish by building the IF statement. */
4959 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
4960 build_real_from_int_cst (type, integer_zero_node));
4961 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
4962 gfc_finish_block (&block));
4964 gfc_add_expr_to_block (&se->pre, tmp);
4965 se->expr = res;
4969 /* RRSPACING (s) is translated into
4970 int e;
4971 real x;
4972 x = fabs (s);
4973 if (x != 0)
4975 frexp (s, &e);
4976 x = scalbn (x, precision - e);
4978 return x;
4980 where precision is gfc_real_kinds[k].digits. */
4982 static void
4983 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
4985 tree arg, type, e, x, cond, stmt, tmp, frexp, scalbn, fabs;
4986 int prec, k;
4987 stmtblock_t block;
4989 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
4990 prec = gfc_real_kinds[k].digits;
4992 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4993 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
4994 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
4996 type = gfc_typenode_for_spec (&expr->ts);
4997 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4998 arg = gfc_evaluate_now (arg, &se->pre);
5000 e = gfc_create_var (integer_type_node, NULL);
5001 x = gfc_create_var (type, NULL);
5002 gfc_add_modify (&se->pre, x,
5003 build_call_expr_loc (input_location, fabs, 1, arg));
5006 gfc_start_block (&block);
5007 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
5008 gfc_build_addr_expr (NULL_TREE, e));
5009 gfc_add_expr_to_block (&block, tmp);
5011 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
5012 build_int_cst (integer_type_node, prec), e);
5013 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
5014 gfc_add_modify (&block, x, tmp);
5015 stmt = gfc_finish_block (&block);
5017 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, x,
5018 build_real_from_int_cst (type, integer_zero_node));
5019 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
5020 gfc_add_expr_to_block (&se->pre, tmp);
5022 se->expr = fold_convert (type, x);
5026 /* SCALE (s, i) is translated into scalbn (s, i). */
5027 static void
5028 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
5030 tree args[2], type, scalbn;
5032 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5034 type = gfc_typenode_for_spec (&expr->ts);
5035 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5036 se->expr = build_call_expr_loc (input_location, scalbn, 2,
5037 fold_convert (type, args[0]),
5038 fold_convert (integer_type_node, args[1]));
5039 se->expr = fold_convert (type, se->expr);
5043 /* SET_EXPONENT (s, i) is translated into
5044 scalbn (frexp (s, &dummy_int), i). */
5045 static void
5046 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
5048 tree args[2], type, tmp, frexp, scalbn;
5050 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
5051 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5053 type = gfc_typenode_for_spec (&expr->ts);
5054 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5056 tmp = gfc_create_var (integer_type_node, NULL);
5057 tmp = build_call_expr_loc (input_location, frexp, 2,
5058 fold_convert (type, args[0]),
5059 gfc_build_addr_expr (NULL_TREE, tmp));
5060 se->expr = build_call_expr_loc (input_location, scalbn, 2, tmp,
5061 fold_convert (integer_type_node, args[1]));
5062 se->expr = fold_convert (type, se->expr);
5066 static void
5067 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
5069 gfc_actual_arglist *actual;
5070 tree arg1;
5071 tree type;
5072 tree fncall0;
5073 tree fncall1;
5074 gfc_se argse;
5076 gfc_init_se (&argse, NULL);
5077 actual = expr->value.function.actual;
5079 if (actual->expr->ts.type == BT_CLASS)
5080 gfc_add_class_array_ref (actual->expr);
5082 argse.want_pointer = 1;
5083 argse.data_not_needed = 1;
5084 gfc_conv_expr_descriptor (&argse, actual->expr);
5085 gfc_add_block_to_block (&se->pre, &argse.pre);
5086 gfc_add_block_to_block (&se->post, &argse.post);
5087 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
5089 /* Build the call to size0. */
5090 fncall0 = build_call_expr_loc (input_location,
5091 gfor_fndecl_size0, 1, arg1);
5093 actual = actual->next;
5095 if (actual->expr)
5097 gfc_init_se (&argse, NULL);
5098 gfc_conv_expr_type (&argse, actual->expr,
5099 gfc_array_index_type);
5100 gfc_add_block_to_block (&se->pre, &argse.pre);
5102 /* Unusually, for an intrinsic, size does not exclude
5103 an optional arg2, so we must test for it. */
5104 if (actual->expr->expr_type == EXPR_VARIABLE
5105 && actual->expr->symtree->n.sym->attr.dummy
5106 && actual->expr->symtree->n.sym->attr.optional)
5108 tree tmp;
5109 /* Build the call to size1. */
5110 fncall1 = build_call_expr_loc (input_location,
5111 gfor_fndecl_size1, 2,
5112 arg1, argse.expr);
5114 gfc_init_se (&argse, NULL);
5115 argse.want_pointer = 1;
5116 argse.data_not_needed = 1;
5117 gfc_conv_expr (&argse, actual->expr);
5118 gfc_add_block_to_block (&se->pre, &argse.pre);
5119 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5120 argse.expr, null_pointer_node);
5121 tmp = gfc_evaluate_now (tmp, &se->pre);
5122 se->expr = fold_build3_loc (input_location, COND_EXPR,
5123 pvoid_type_node, tmp, fncall1, fncall0);
5125 else
5127 se->expr = NULL_TREE;
5128 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
5129 gfc_array_index_type,
5130 argse.expr, gfc_index_one_node);
5133 else if (expr->value.function.actual->expr->rank == 1)
5135 argse.expr = gfc_index_zero_node;
5136 se->expr = NULL_TREE;
5138 else
5139 se->expr = fncall0;
5141 if (se->expr == NULL_TREE)
5143 tree ubound, lbound;
5145 arg1 = build_fold_indirect_ref_loc (input_location,
5146 arg1);
5147 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
5148 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
5149 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
5150 gfc_array_index_type, ubound, lbound);
5151 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
5152 gfc_array_index_type,
5153 se->expr, gfc_index_one_node);
5154 se->expr = fold_build2_loc (input_location, MAX_EXPR,
5155 gfc_array_index_type, se->expr,
5156 gfc_index_zero_node);
5159 type = gfc_typenode_for_spec (&expr->ts);
5160 se->expr = convert (type, se->expr);
5164 /* Helper function to compute the size of a character variable,
5165 excluding the terminating null characters. The result has
5166 gfc_array_index_type type. */
5168 tree
5169 size_of_string_in_bytes (int kind, tree string_length)
5171 tree bytesize;
5172 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
5174 bytesize = build_int_cst (gfc_array_index_type,
5175 gfc_character_kinds[i].bit_size / 8);
5177 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5178 bytesize,
5179 fold_convert (gfc_array_index_type, string_length));
5183 static void
5184 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
5186 gfc_expr *arg;
5187 gfc_se argse;
5188 tree source_bytes;
5189 tree type;
5190 tree tmp;
5191 tree lower;
5192 tree upper;
5193 int n;
5195 arg = expr->value.function.actual->expr;
5197 gfc_init_se (&argse, NULL);
5199 if (arg->rank == 0)
5201 if (arg->ts.type == BT_CLASS)
5202 gfc_add_data_component (arg);
5204 gfc_conv_expr_reference (&argse, arg);
5206 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5207 argse.expr));
5209 /* Obtain the source word length. */
5210 if (arg->ts.type == BT_CHARACTER)
5211 se->expr = size_of_string_in_bytes (arg->ts.kind,
5212 argse.string_length);
5213 else
5214 se->expr = fold_convert (gfc_array_index_type, size_in_bytes (type));
5216 else
5218 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
5219 argse.want_pointer = 0;
5220 gfc_conv_expr_descriptor (&argse, arg);
5221 type = gfc_get_element_type (TREE_TYPE (argse.expr));
5223 /* Obtain the argument's word length. */
5224 if (arg->ts.type == BT_CHARACTER)
5225 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
5226 else
5227 tmp = fold_convert (gfc_array_index_type,
5228 size_in_bytes (type));
5229 gfc_add_modify (&argse.pre, source_bytes, tmp);
5231 /* Obtain the size of the array in bytes. */
5232 for (n = 0; n < arg->rank; n++)
5234 tree idx;
5235 idx = gfc_rank_cst[n];
5236 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
5237 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
5238 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5239 gfc_array_index_type, upper, lower);
5240 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5241 gfc_array_index_type, tmp, gfc_index_one_node);
5242 tmp = fold_build2_loc (input_location, MULT_EXPR,
5243 gfc_array_index_type, tmp, source_bytes);
5244 gfc_add_modify (&argse.pre, source_bytes, tmp);
5246 se->expr = source_bytes;
5249 gfc_add_block_to_block (&se->pre, &argse.pre);
5253 static void
5254 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
5256 gfc_expr *arg;
5257 gfc_se argse;
5258 tree type, result_type, tmp;
5260 arg = expr->value.function.actual->expr;
5262 gfc_init_se (&argse, NULL);
5263 result_type = gfc_get_int_type (expr->ts.kind);
5265 if (arg->rank == 0)
5267 if (arg->ts.type == BT_CLASS)
5269 gfc_add_vptr_component (arg);
5270 gfc_add_size_component (arg);
5271 gfc_conv_expr (&argse, arg);
5272 tmp = fold_convert (result_type, argse.expr);
5273 goto done;
5276 gfc_conv_expr_reference (&argse, arg);
5277 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5278 argse.expr));
5280 else
5282 argse.want_pointer = 0;
5283 gfc_conv_expr_descriptor (&argse, arg);
5284 type = gfc_get_element_type (TREE_TYPE (argse.expr));
5287 /* Obtain the argument's word length. */
5288 if (arg->ts.type == BT_CHARACTER)
5289 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
5290 else
5291 tmp = size_in_bytes (type);
5292 tmp = fold_convert (result_type, tmp);
5294 done:
5295 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
5296 build_int_cst (result_type, BITS_PER_UNIT));
5297 gfc_add_block_to_block (&se->pre, &argse.pre);
5301 /* Intrinsic string comparison functions. */
5303 static void
5304 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
5306 tree args[4];
5308 gfc_conv_intrinsic_function_args (se, expr, args, 4);
5310 se->expr
5311 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
5312 expr->value.function.actual->expr->ts.kind,
5313 op);
5314 se->expr = fold_build2_loc (input_location, op,
5315 gfc_typenode_for_spec (&expr->ts), se->expr,
5316 build_int_cst (TREE_TYPE (se->expr), 0));
5319 /* Generate a call to the adjustl/adjustr library function. */
5320 static void
5321 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
5323 tree args[3];
5324 tree len;
5325 tree type;
5326 tree var;
5327 tree tmp;
5329 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
5330 len = args[1];
5332 type = TREE_TYPE (args[2]);
5333 var = gfc_conv_string_tmp (se, type, len);
5334 args[0] = var;
5336 tmp = build_call_expr_loc (input_location,
5337 fndecl, 3, args[0], args[1], args[2]);
5338 gfc_add_expr_to_block (&se->pre, tmp);
5339 se->expr = var;
5340 se->string_length = len;
5344 /* Generate code for the TRANSFER intrinsic:
5345 For scalar results:
5346 DEST = TRANSFER (SOURCE, MOLD)
5347 where:
5348 typeof<DEST> = typeof<MOLD>
5349 and:
5350 MOLD is scalar.
5352 For array results:
5353 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
5354 where:
5355 typeof<DEST> = typeof<MOLD>
5356 and:
5357 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
5358 sizeof (DEST(0) * SIZE). */
5359 static void
5360 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
5362 tree tmp;
5363 tree tmpdecl;
5364 tree ptr;
5365 tree extent;
5366 tree source;
5367 tree source_type;
5368 tree source_bytes;
5369 tree mold_type;
5370 tree dest_word_len;
5371 tree size_words;
5372 tree size_bytes;
5373 tree upper;
5374 tree lower;
5375 tree stmt;
5376 gfc_actual_arglist *arg;
5377 gfc_se argse;
5378 gfc_array_info *info;
5379 stmtblock_t block;
5380 int n;
5381 bool scalar_mold;
5382 gfc_expr *source_expr, *mold_expr;
5384 info = NULL;
5385 if (se->loop)
5386 info = &se->ss->info->data.array;
5388 /* Convert SOURCE. The output from this stage is:-
5389 source_bytes = length of the source in bytes
5390 source = pointer to the source data. */
5391 arg = expr->value.function.actual;
5392 source_expr = arg->expr;
5394 /* Ensure double transfer through LOGICAL preserves all
5395 the needed bits. */
5396 if (arg->expr->expr_type == EXPR_FUNCTION
5397 && arg->expr->value.function.esym == NULL
5398 && arg->expr->value.function.isym != NULL
5399 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
5400 && arg->expr->ts.type == BT_LOGICAL
5401 && expr->ts.type != arg->expr->ts.type)
5402 arg->expr->value.function.name = "__transfer_in_transfer";
5404 gfc_init_se (&argse, NULL);
5406 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
5408 /* Obtain the pointer to source and the length of source in bytes. */
5409 if (arg->expr->rank == 0)
5411 gfc_conv_expr_reference (&argse, arg->expr);
5412 if (arg->expr->ts.type == BT_CLASS)
5413 source = gfc_class_data_get (argse.expr);
5414 else
5415 source = argse.expr;
5417 /* Obtain the source word length. */
5418 switch (arg->expr->ts.type)
5420 case BT_CHARACTER:
5421 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
5422 argse.string_length);
5423 break;
5424 case BT_CLASS:
5425 tmp = gfc_vtable_size_get (argse.expr);
5426 break;
5427 default:
5428 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5429 source));
5430 tmp = fold_convert (gfc_array_index_type,
5431 size_in_bytes (source_type));
5432 break;
5435 else
5437 argse.want_pointer = 0;
5438 gfc_conv_expr_descriptor (&argse, arg->expr);
5439 source = gfc_conv_descriptor_data_get (argse.expr);
5440 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
5442 /* Repack the source if not simply contiguous. */
5443 if (!gfc_is_simply_contiguous (arg->expr, false))
5445 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
5447 if (gfc_option.warn_array_temp)
5448 gfc_warning ("Creating array temporary at %L", &expr->where);
5450 source = build_call_expr_loc (input_location,
5451 gfor_fndecl_in_pack, 1, tmp);
5452 source = gfc_evaluate_now (source, &argse.pre);
5454 /* Free the temporary. */
5455 gfc_start_block (&block);
5456 tmp = gfc_call_free (convert (pvoid_type_node, source));
5457 gfc_add_expr_to_block (&block, tmp);
5458 stmt = gfc_finish_block (&block);
5460 /* Clean up if it was repacked. */
5461 gfc_init_block (&block);
5462 tmp = gfc_conv_array_data (argse.expr);
5463 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5464 source, tmp);
5465 tmp = build3_v (COND_EXPR, tmp, stmt,
5466 build_empty_stmt (input_location));
5467 gfc_add_expr_to_block (&block, tmp);
5468 gfc_add_block_to_block (&block, &se->post);
5469 gfc_init_block (&se->post);
5470 gfc_add_block_to_block (&se->post, &block);
5473 /* Obtain the source word length. */
5474 if (arg->expr->ts.type == BT_CHARACTER)
5475 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
5476 argse.string_length);
5477 else
5478 tmp = fold_convert (gfc_array_index_type,
5479 size_in_bytes (source_type));
5481 /* Obtain the size of the array in bytes. */
5482 extent = gfc_create_var (gfc_array_index_type, NULL);
5483 for (n = 0; n < arg->expr->rank; n++)
5485 tree idx;
5486 idx = gfc_rank_cst[n];
5487 gfc_add_modify (&argse.pre, source_bytes, tmp);
5488 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
5489 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
5490 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5491 gfc_array_index_type, upper, lower);
5492 gfc_add_modify (&argse.pre, extent, tmp);
5493 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5494 gfc_array_index_type, extent,
5495 gfc_index_one_node);
5496 tmp = fold_build2_loc (input_location, MULT_EXPR,
5497 gfc_array_index_type, tmp, source_bytes);
5501 gfc_add_modify (&argse.pre, source_bytes, tmp);
5502 gfc_add_block_to_block (&se->pre, &argse.pre);
5503 gfc_add_block_to_block (&se->post, &argse.post);
5505 /* Now convert MOLD. The outputs are:
5506 mold_type = the TREE type of MOLD
5507 dest_word_len = destination word length in bytes. */
5508 arg = arg->next;
5509 mold_expr = arg->expr;
5511 gfc_init_se (&argse, NULL);
5513 scalar_mold = arg->expr->rank == 0;
5515 if (arg->expr->rank == 0)
5517 gfc_conv_expr_reference (&argse, arg->expr);
5518 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5519 argse.expr));
5521 else
5523 gfc_init_se (&argse, NULL);
5524 argse.want_pointer = 0;
5525 gfc_conv_expr_descriptor (&argse, arg->expr);
5526 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
5529 gfc_add_block_to_block (&se->pre, &argse.pre);
5530 gfc_add_block_to_block (&se->post, &argse.post);
5532 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
5534 /* If this TRANSFER is nested in another TRANSFER, use a type
5535 that preserves all bits. */
5536 if (arg->expr->ts.type == BT_LOGICAL)
5537 mold_type = gfc_get_int_type (arg->expr->ts.kind);
5540 /* Obtain the destination word length. */
5541 switch (arg->expr->ts.type)
5543 case BT_CHARACTER:
5544 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
5545 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
5546 break;
5547 case BT_CLASS:
5548 tmp = gfc_vtable_size_get (argse.expr);
5549 break;
5550 default:
5551 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
5552 break;
5554 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
5555 gfc_add_modify (&se->pre, dest_word_len, tmp);
5557 /* Finally convert SIZE, if it is present. */
5558 arg = arg->next;
5559 size_words = gfc_create_var (gfc_array_index_type, NULL);
5561 if (arg->expr)
5563 gfc_init_se (&argse, NULL);
5564 gfc_conv_expr_reference (&argse, arg->expr);
5565 tmp = convert (gfc_array_index_type,
5566 build_fold_indirect_ref_loc (input_location,
5567 argse.expr));
5568 gfc_add_block_to_block (&se->pre, &argse.pre);
5569 gfc_add_block_to_block (&se->post, &argse.post);
5571 else
5572 tmp = NULL_TREE;
5574 /* Separate array and scalar results. */
5575 if (scalar_mold && tmp == NULL_TREE)
5576 goto scalar_transfer;
5578 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
5579 if (tmp != NULL_TREE)
5580 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5581 tmp, dest_word_len);
5582 else
5583 tmp = source_bytes;
5585 gfc_add_modify (&se->pre, size_bytes, tmp);
5586 gfc_add_modify (&se->pre, size_words,
5587 fold_build2_loc (input_location, CEIL_DIV_EXPR,
5588 gfc_array_index_type,
5589 size_bytes, dest_word_len));
5591 /* Evaluate the bounds of the result. If the loop range exists, we have
5592 to check if it is too large. If so, we modify loop->to be consistent
5593 with min(size, size(source)). Otherwise, size is made consistent with
5594 the loop range, so that the right number of bytes is transferred.*/
5595 n = se->loop->order[0];
5596 if (se->loop->to[n] != NULL_TREE)
5598 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5599 se->loop->to[n], se->loop->from[n]);
5600 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5601 tmp, gfc_index_one_node);
5602 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
5603 tmp, size_words);
5604 gfc_add_modify (&se->pre, size_words, tmp);
5605 gfc_add_modify (&se->pre, size_bytes,
5606 fold_build2_loc (input_location, MULT_EXPR,
5607 gfc_array_index_type,
5608 size_words, dest_word_len));
5609 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5610 size_words, se->loop->from[n]);
5611 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5612 upper, gfc_index_one_node);
5614 else
5616 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5617 size_words, gfc_index_one_node);
5618 se->loop->from[n] = gfc_index_zero_node;
5621 se->loop->to[n] = upper;
5623 /* Build a destination descriptor, using the pointer, source, as the
5624 data field. */
5625 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
5626 NULL_TREE, false, true, false, &expr->where);
5628 /* Cast the pointer to the result. */
5629 tmp = gfc_conv_descriptor_data_get (info->descriptor);
5630 tmp = fold_convert (pvoid_type_node, tmp);
5632 /* Use memcpy to do the transfer. */
5634 = build_call_expr_loc (input_location,
5635 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
5636 fold_convert (pvoid_type_node, source),
5637 fold_convert (size_type_node,
5638 fold_build2_loc (input_location,
5639 MIN_EXPR,
5640 gfc_array_index_type,
5641 size_bytes,
5642 source_bytes)));
5643 gfc_add_expr_to_block (&se->pre, tmp);
5645 se->expr = info->descriptor;
5646 if (expr->ts.type == BT_CHARACTER)
5647 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
5649 return;
5651 /* Deal with scalar results. */
5652 scalar_transfer:
5653 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
5654 dest_word_len, source_bytes);
5655 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
5656 extent, gfc_index_zero_node);
5658 if (expr->ts.type == BT_CHARACTER)
5660 tree direct, indirect, free;
5662 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
5663 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
5664 "transfer");
5666 /* If source is longer than the destination, use a pointer to
5667 the source directly. */
5668 gfc_init_block (&block);
5669 gfc_add_modify (&block, tmpdecl, ptr);
5670 direct = gfc_finish_block (&block);
5672 /* Otherwise, allocate a string with the length of the destination
5673 and copy the source into it. */
5674 gfc_init_block (&block);
5675 tmp = gfc_get_pchar_type (expr->ts.kind);
5676 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
5677 gfc_add_modify (&block, tmpdecl,
5678 fold_convert (TREE_TYPE (ptr), tmp));
5679 tmp = build_call_expr_loc (input_location,
5680 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
5681 fold_convert (pvoid_type_node, tmpdecl),
5682 fold_convert (pvoid_type_node, ptr),
5683 fold_convert (size_type_node, extent));
5684 gfc_add_expr_to_block (&block, tmp);
5685 indirect = gfc_finish_block (&block);
5687 /* Wrap it up with the condition. */
5688 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
5689 dest_word_len, source_bytes);
5690 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
5691 gfc_add_expr_to_block (&se->pre, tmp);
5693 /* Free the temporary string, if necessary. */
5694 free = gfc_call_free (tmpdecl);
5695 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
5696 dest_word_len, source_bytes);
5697 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
5698 gfc_add_expr_to_block (&se->post, tmp);
5700 se->expr = tmpdecl;
5701 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
5703 else
5705 tmpdecl = gfc_create_var (mold_type, "transfer");
5707 ptr = convert (build_pointer_type (mold_type), source);
5709 /* For CLASS results, allocate the needed memory first. */
5710 if (mold_expr->ts.type == BT_CLASS)
5712 tree cdata;
5713 cdata = gfc_class_data_get (tmpdecl);
5714 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
5715 gfc_add_modify (&se->pre, cdata, tmp);
5718 /* Use memcpy to do the transfer. */
5719 if (mold_expr->ts.type == BT_CLASS)
5720 tmp = gfc_class_data_get (tmpdecl);
5721 else
5722 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
5724 tmp = build_call_expr_loc (input_location,
5725 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
5726 fold_convert (pvoid_type_node, tmp),
5727 fold_convert (pvoid_type_node, ptr),
5728 fold_convert (size_type_node, extent));
5729 gfc_add_expr_to_block (&se->pre, tmp);
5731 /* For CLASS results, set the _vptr. */
5732 if (mold_expr->ts.type == BT_CLASS)
5734 tree vptr;
5735 gfc_symbol *vtab;
5736 vptr = gfc_class_vptr_get (tmpdecl);
5737 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
5738 gcc_assert (vtab);
5739 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
5740 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
5743 se->expr = tmpdecl;
5748 /* Generate code for the ALLOCATED intrinsic.
5749 Generate inline code that directly check the address of the argument. */
5751 static void
5752 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
5754 gfc_actual_arglist *arg1;
5755 gfc_se arg1se;
5756 tree tmp;
5758 gfc_init_se (&arg1se, NULL);
5759 arg1 = expr->value.function.actual;
5761 if (arg1->expr->ts.type == BT_CLASS)
5763 /* Make sure that class array expressions have both a _data
5764 component reference and an array reference.... */
5765 if (CLASS_DATA (arg1->expr)->attr.dimension)
5766 gfc_add_class_array_ref (arg1->expr);
5767 /* .... whilst scalars only need the _data component. */
5768 else
5769 gfc_add_data_component (arg1->expr);
5772 if (arg1->expr->rank == 0)
5774 /* Allocatable scalar. */
5775 arg1se.want_pointer = 1;
5776 gfc_conv_expr (&arg1se, arg1->expr);
5777 tmp = arg1se.expr;
5779 else
5781 /* Allocatable array. */
5782 arg1se.descriptor_only = 1;
5783 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
5784 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
5787 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
5788 fold_convert (TREE_TYPE (tmp), null_pointer_node));
5789 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
5793 /* Generate code for the ASSOCIATED intrinsic.
5794 If both POINTER and TARGET are arrays, generate a call to library function
5795 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
5796 In other cases, generate inline code that directly compare the address of
5797 POINTER with the address of TARGET. */
5799 static void
5800 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
5802 gfc_actual_arglist *arg1;
5803 gfc_actual_arglist *arg2;
5804 gfc_se arg1se;
5805 gfc_se arg2se;
5806 tree tmp2;
5807 tree tmp;
5808 tree nonzero_charlen;
5809 tree nonzero_arraylen;
5810 gfc_ss *ss;
5811 bool scalar;
5813 gfc_init_se (&arg1se, NULL);
5814 gfc_init_se (&arg2se, NULL);
5815 arg1 = expr->value.function.actual;
5816 arg2 = arg1->next;
5818 /* Check whether the expression is a scalar or not; we cannot use
5819 arg1->expr->rank as it can be nonzero for proc pointers. */
5820 ss = gfc_walk_expr (arg1->expr);
5821 scalar = ss == gfc_ss_terminator;
5822 if (!scalar)
5823 gfc_free_ss_chain (ss);
5825 if (!arg2->expr)
5827 /* No optional target. */
5828 if (scalar)
5830 /* A pointer to a scalar. */
5831 arg1se.want_pointer = 1;
5832 gfc_conv_expr (&arg1se, arg1->expr);
5833 if (arg1->expr->symtree->n.sym->attr.proc_pointer
5834 && arg1->expr->symtree->n.sym->attr.dummy)
5835 arg1se.expr = build_fold_indirect_ref_loc (input_location,
5836 arg1se.expr);
5837 if (arg1->expr->ts.type == BT_CLASS)
5838 tmp2 = gfc_class_data_get (arg1se.expr);
5839 else
5840 tmp2 = arg1se.expr;
5842 else
5844 /* A pointer to an array. */
5845 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
5846 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
5848 gfc_add_block_to_block (&se->pre, &arg1se.pre);
5849 gfc_add_block_to_block (&se->post, &arg1se.post);
5850 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp2,
5851 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
5852 se->expr = tmp;
5854 else
5856 /* An optional target. */
5857 if (arg2->expr->ts.type == BT_CLASS)
5858 gfc_add_data_component (arg2->expr);
5860 nonzero_charlen = NULL_TREE;
5861 if (arg1->expr->ts.type == BT_CHARACTER)
5862 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
5863 boolean_type_node,
5864 arg1->expr->ts.u.cl->backend_decl,
5865 integer_zero_node);
5866 if (scalar)
5868 /* A pointer to a scalar. */
5869 arg1se.want_pointer = 1;
5870 gfc_conv_expr (&arg1se, arg1->expr);
5871 if (arg1->expr->symtree->n.sym->attr.proc_pointer
5872 && arg1->expr->symtree->n.sym->attr.dummy)
5873 arg1se.expr = build_fold_indirect_ref_loc (input_location,
5874 arg1se.expr);
5875 if (arg1->expr->ts.type == BT_CLASS)
5876 arg1se.expr = gfc_class_data_get (arg1se.expr);
5878 arg2se.want_pointer = 1;
5879 gfc_conv_expr (&arg2se, arg2->expr);
5880 if (arg2->expr->symtree->n.sym->attr.proc_pointer
5881 && arg2->expr->symtree->n.sym->attr.dummy)
5882 arg2se.expr = build_fold_indirect_ref_loc (input_location,
5883 arg2se.expr);
5884 gfc_add_block_to_block (&se->pre, &arg1se.pre);
5885 gfc_add_block_to_block (&se->post, &arg1se.post);
5886 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5887 arg1se.expr, arg2se.expr);
5888 tmp2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5889 arg1se.expr, null_pointer_node);
5890 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5891 boolean_type_node, tmp, tmp2);
5893 else
5895 /* An array pointer of zero length is not associated if target is
5896 present. */
5897 arg1se.descriptor_only = 1;
5898 gfc_conv_expr_lhs (&arg1se, arg1->expr);
5899 if (arg1->expr->rank == -1)
5901 tmp = gfc_conv_descriptor_rank (arg1se.expr);
5902 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5903 TREE_TYPE (tmp), tmp, gfc_index_one_node);
5905 else
5906 tmp = gfc_rank_cst[arg1->expr->rank - 1];
5907 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
5908 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
5909 boolean_type_node, tmp,
5910 build_int_cst (TREE_TYPE (tmp), 0));
5912 /* A pointer to an array, call library function _gfor_associated. */
5913 arg1se.want_pointer = 1;
5914 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
5916 arg2se.want_pointer = 1;
5917 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
5918 gfc_add_block_to_block (&se->pre, &arg2se.pre);
5919 gfc_add_block_to_block (&se->post, &arg2se.post);
5920 se->expr = build_call_expr_loc (input_location,
5921 gfor_fndecl_associated, 2,
5922 arg1se.expr, arg2se.expr);
5923 se->expr = convert (boolean_type_node, se->expr);
5924 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5925 boolean_type_node, se->expr,
5926 nonzero_arraylen);
5929 /* If target is present zero character length pointers cannot
5930 be associated. */
5931 if (nonzero_charlen != NULL_TREE)
5932 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5933 boolean_type_node,
5934 se->expr, nonzero_charlen);
5937 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
5941 /* Generate code for the SAME_TYPE_AS intrinsic.
5942 Generate inline code that directly checks the vindices. */
5944 static void
5945 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
5947 gfc_expr *a, *b;
5948 gfc_se se1, se2;
5949 tree tmp;
5950 tree conda = NULL_TREE, condb = NULL_TREE;
5952 gfc_init_se (&se1, NULL);
5953 gfc_init_se (&se2, NULL);
5955 a = expr->value.function.actual->expr;
5956 b = expr->value.function.actual->next->expr;
5958 if (UNLIMITED_POLY (a))
5960 tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
5961 conda = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5962 tmp, build_int_cst (TREE_TYPE (tmp), 0));
5965 if (UNLIMITED_POLY (b))
5967 tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
5968 condb = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5969 tmp, build_int_cst (TREE_TYPE (tmp), 0));
5972 if (a->ts.type == BT_CLASS)
5974 gfc_add_vptr_component (a);
5975 gfc_add_hash_component (a);
5977 else if (a->ts.type == BT_DERIVED)
5978 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
5979 a->ts.u.derived->hash_value);
5981 if (b->ts.type == BT_CLASS)
5983 gfc_add_vptr_component (b);
5984 gfc_add_hash_component (b);
5986 else if (b->ts.type == BT_DERIVED)
5987 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
5988 b->ts.u.derived->hash_value);
5990 gfc_conv_expr (&se1, a);
5991 gfc_conv_expr (&se2, b);
5993 tmp = fold_build2_loc (input_location, EQ_EXPR,
5994 boolean_type_node, se1.expr,
5995 fold_convert (TREE_TYPE (se1.expr), se2.expr));
5997 if (conda)
5998 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
5999 boolean_type_node, conda, tmp);
6001 if (condb)
6002 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
6003 boolean_type_node, condb, tmp);
6005 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
6009 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
6011 static void
6012 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
6014 tree args[2];
6016 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6017 se->expr = build_call_expr_loc (input_location,
6018 gfor_fndecl_sc_kind, 2, args[0], args[1]);
6019 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6023 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
6025 static void
6026 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
6028 tree arg, type;
6030 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6032 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
6033 type = gfc_get_int_type (4);
6034 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
6036 /* Convert it to the required type. */
6037 type = gfc_typenode_for_spec (&expr->ts);
6038 se->expr = build_call_expr_loc (input_location,
6039 gfor_fndecl_si_kind, 1, arg);
6040 se->expr = fold_convert (type, se->expr);
6044 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
6046 static void
6047 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
6049 gfc_actual_arglist *actual;
6050 tree type;
6051 gfc_se argse;
6052 vec<tree, va_gc> *args = NULL;
6054 for (actual = expr->value.function.actual; actual; actual = actual->next)
6056 gfc_init_se (&argse, se);
6058 /* Pass a NULL pointer for an absent arg. */
6059 if (actual->expr == NULL)
6060 argse.expr = null_pointer_node;
6061 else
6063 gfc_typespec ts;
6064 gfc_clear_ts (&ts);
6066 if (actual->expr->ts.kind != gfc_c_int_kind)
6068 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
6069 ts.type = BT_INTEGER;
6070 ts.kind = gfc_c_int_kind;
6071 gfc_convert_type (actual->expr, &ts, 2);
6073 gfc_conv_expr_reference (&argse, actual->expr);
6076 gfc_add_block_to_block (&se->pre, &argse.pre);
6077 gfc_add_block_to_block (&se->post, &argse.post);
6078 vec_safe_push (args, argse.expr);
6081 /* Convert it to the required type. */
6082 type = gfc_typenode_for_spec (&expr->ts);
6083 se->expr = build_call_expr_loc_vec (input_location,
6084 gfor_fndecl_sr_kind, args);
6085 se->expr = fold_convert (type, se->expr);
6089 /* Generate code for TRIM (A) intrinsic function. */
6091 static void
6092 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
6094 tree var;
6095 tree len;
6096 tree addr;
6097 tree tmp;
6098 tree cond;
6099 tree fndecl;
6100 tree function;
6101 tree *args;
6102 unsigned int num_args;
6104 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
6105 args = XALLOCAVEC (tree, num_args);
6107 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
6108 addr = gfc_build_addr_expr (ppvoid_type_node, var);
6109 len = gfc_create_var (gfc_charlen_type_node, "len");
6111 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
6112 args[0] = gfc_build_addr_expr (NULL_TREE, len);
6113 args[1] = addr;
6115 if (expr->ts.kind == 1)
6116 function = gfor_fndecl_string_trim;
6117 else if (expr->ts.kind == 4)
6118 function = gfor_fndecl_string_trim_char4;
6119 else
6120 gcc_unreachable ();
6122 fndecl = build_addr (function, current_function_decl);
6123 tmp = build_call_array_loc (input_location,
6124 TREE_TYPE (TREE_TYPE (function)), fndecl,
6125 num_args, args);
6126 gfc_add_expr_to_block (&se->pre, tmp);
6128 /* Free the temporary afterwards, if necessary. */
6129 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6130 len, build_int_cst (TREE_TYPE (len), 0));
6131 tmp = gfc_call_free (var);
6132 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
6133 gfc_add_expr_to_block (&se->post, tmp);
6135 se->expr = var;
6136 se->string_length = len;
6140 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
6142 static void
6143 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
6145 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
6146 tree type, cond, tmp, count, exit_label, n, max, largest;
6147 tree size;
6148 stmtblock_t block, body;
6149 int i;
6151 /* We store in charsize the size of a character. */
6152 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
6153 size = build_int_cst (size_type_node, gfc_character_kinds[i].bit_size / 8);
6155 /* Get the arguments. */
6156 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6157 slen = fold_convert (size_type_node, gfc_evaluate_now (args[0], &se->pre));
6158 src = args[1];
6159 ncopies = gfc_evaluate_now (args[2], &se->pre);
6160 ncopies_type = TREE_TYPE (ncopies);
6162 /* Check that NCOPIES is not negative. */
6163 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, ncopies,
6164 build_int_cst (ncopies_type, 0));
6165 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
6166 "Argument NCOPIES of REPEAT intrinsic is negative "
6167 "(its value is %ld)",
6168 fold_convert (long_integer_type_node, ncopies));
6170 /* If the source length is zero, any non negative value of NCOPIES
6171 is valid, and nothing happens. */
6172 n = gfc_create_var (ncopies_type, "ncopies");
6173 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
6174 build_int_cst (size_type_node, 0));
6175 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
6176 build_int_cst (ncopies_type, 0), ncopies);
6177 gfc_add_modify (&se->pre, n, tmp);
6178 ncopies = n;
6180 /* Check that ncopies is not too large: ncopies should be less than
6181 (or equal to) MAX / slen, where MAX is the maximal integer of
6182 the gfc_charlen_type_node type. If slen == 0, we need a special
6183 case to avoid the division by zero. */
6184 i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
6185 max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_charlen_int_kind);
6186 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node,
6187 fold_convert (size_type_node, max), slen);
6188 largest = TYPE_PRECISION (size_type_node) > TYPE_PRECISION (ncopies_type)
6189 ? size_type_node : ncopies_type;
6190 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6191 fold_convert (largest, ncopies),
6192 fold_convert (largest, max));
6193 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
6194 build_int_cst (size_type_node, 0));
6195 cond = fold_build3_loc (input_location, COND_EXPR, boolean_type_node, tmp,
6196 boolean_false_node, cond);
6197 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
6198 "Argument NCOPIES of REPEAT intrinsic is too large");
6200 /* Compute the destination length. */
6201 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6202 fold_convert (gfc_charlen_type_node, slen),
6203 fold_convert (gfc_charlen_type_node, ncopies));
6204 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
6205 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
6207 /* Generate the code to do the repeat operation:
6208 for (i = 0; i < ncopies; i++)
6209 memmove (dest + (i * slen * size), src, slen*size); */
6210 gfc_start_block (&block);
6211 count = gfc_create_var (ncopies_type, "count");
6212 gfc_add_modify (&block, count, build_int_cst (ncopies_type, 0));
6213 exit_label = gfc_build_label_decl (NULL_TREE);
6215 /* Start the loop body. */
6216 gfc_start_block (&body);
6218 /* Exit the loop if count >= ncopies. */
6219 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, count,
6220 ncopies);
6221 tmp = build1_v (GOTO_EXPR, exit_label);
6222 TREE_USED (exit_label) = 1;
6223 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
6224 build_empty_stmt (input_location));
6225 gfc_add_expr_to_block (&body, tmp);
6227 /* Call memmove (dest + (i*slen*size), src, slen*size). */
6228 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6229 fold_convert (gfc_charlen_type_node, slen),
6230 fold_convert (gfc_charlen_type_node, count));
6231 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6232 tmp, fold_convert (gfc_charlen_type_node, size));
6233 tmp = fold_build_pointer_plus_loc (input_location,
6234 fold_convert (pvoid_type_node, dest), tmp);
6235 tmp = build_call_expr_loc (input_location,
6236 builtin_decl_explicit (BUILT_IN_MEMMOVE),
6237 3, tmp, src,
6238 fold_build2_loc (input_location, MULT_EXPR,
6239 size_type_node, slen,
6240 fold_convert (size_type_node,
6241 size)));
6242 gfc_add_expr_to_block (&body, tmp);
6244 /* Increment count. */
6245 tmp = fold_build2_loc (input_location, PLUS_EXPR, ncopies_type,
6246 count, build_int_cst (TREE_TYPE (count), 1));
6247 gfc_add_modify (&body, count, tmp);
6249 /* Build the loop. */
6250 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
6251 gfc_add_expr_to_block (&block, tmp);
6253 /* Add the exit label. */
6254 tmp = build1_v (LABEL_EXPR, exit_label);
6255 gfc_add_expr_to_block (&block, tmp);
6257 /* Finish the block. */
6258 tmp = gfc_finish_block (&block);
6259 gfc_add_expr_to_block (&se->pre, tmp);
6261 /* Set the result value. */
6262 se->expr = dest;
6263 se->string_length = dlen;
6267 /* Generate code for the IARGC intrinsic. */
6269 static void
6270 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
6272 tree tmp;
6273 tree fndecl;
6274 tree type;
6276 /* Call the library function. This always returns an INTEGER(4). */
6277 fndecl = gfor_fndecl_iargc;
6278 tmp = build_call_expr_loc (input_location,
6279 fndecl, 0);
6281 /* Convert it to the required type. */
6282 type = gfc_typenode_for_spec (&expr->ts);
6283 tmp = fold_convert (type, tmp);
6285 se->expr = tmp;
6289 /* The loc intrinsic returns the address of its argument as
6290 gfc_index_integer_kind integer. */
6292 static void
6293 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
6295 tree temp_var;
6296 gfc_expr *arg_expr;
6298 gcc_assert (!se->ss);
6300 arg_expr = expr->value.function.actual->expr;
6301 if (arg_expr->rank == 0)
6302 gfc_conv_expr_reference (se, arg_expr);
6303 else
6304 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
6305 se->expr= convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
6307 /* Create a temporary variable for loc return value. Without this,
6308 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
6309 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
6310 gfc_add_modify (&se->pre, temp_var, se->expr);
6311 se->expr = temp_var;
6315 /* The following routine generates code for the intrinsic
6316 functions from the ISO_C_BINDING module:
6317 * C_LOC
6318 * C_FUNLOC
6319 * C_ASSOCIATED */
6321 static void
6322 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
6324 gfc_actual_arglist *arg = expr->value.function.actual;
6326 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
6328 if (arg->expr->rank == 0)
6329 gfc_conv_expr_reference (se, arg->expr);
6330 else if (gfc_is_simply_contiguous (arg->expr, false))
6331 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
6332 else
6334 gfc_conv_expr_descriptor (se, arg->expr);
6335 se->expr = gfc_conv_descriptor_data_get (se->expr);
6338 /* TODO -- the following two lines shouldn't be necessary, but if
6339 they're removed, a bug is exposed later in the code path.
6340 This workaround was thus introduced, but will have to be
6341 removed; please see PR 35150 for details about the issue. */
6342 se->expr = convert (pvoid_type_node, se->expr);
6343 se->expr = gfc_evaluate_now (se->expr, &se->pre);
6345 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
6346 gfc_conv_expr_reference (se, arg->expr);
6347 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
6349 gfc_se arg1se;
6350 gfc_se arg2se;
6352 /* Build the addr_expr for the first argument. The argument is
6353 already an *address* so we don't need to set want_pointer in
6354 the gfc_se. */
6355 gfc_init_se (&arg1se, NULL);
6356 gfc_conv_expr (&arg1se, arg->expr);
6357 gfc_add_block_to_block (&se->pre, &arg1se.pre);
6358 gfc_add_block_to_block (&se->post, &arg1se.post);
6360 /* See if we were given two arguments. */
6361 if (arg->next->expr == NULL)
6362 /* Only given one arg so generate a null and do a
6363 not-equal comparison against the first arg. */
6364 se->expr = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6365 arg1se.expr,
6366 fold_convert (TREE_TYPE (arg1se.expr),
6367 null_pointer_node));
6368 else
6370 tree eq_expr;
6371 tree not_null_expr;
6373 /* Given two arguments so build the arg2se from second arg. */
6374 gfc_init_se (&arg2se, NULL);
6375 gfc_conv_expr (&arg2se, arg->next->expr);
6376 gfc_add_block_to_block (&se->pre, &arg2se.pre);
6377 gfc_add_block_to_block (&se->post, &arg2se.post);
6379 /* Generate test to compare that the two args are equal. */
6380 eq_expr = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
6381 arg1se.expr, arg2se.expr);
6382 /* Generate test to ensure that the first arg is not null. */
6383 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
6384 boolean_type_node,
6385 arg1se.expr, null_pointer_node);
6387 /* Finally, the generated test must check that both arg1 is not
6388 NULL and that it is equal to the second arg. */
6389 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6390 boolean_type_node,
6391 not_null_expr, eq_expr);
6394 else
6395 gcc_unreachable ();
6399 /* The following routine generates code for the intrinsic
6400 subroutines from the ISO_C_BINDING module:
6401 * C_F_POINTER
6402 * C_F_PROCPOINTER. */
6404 static tree
6405 conv_isocbinding_subroutine (gfc_code *code)
6407 gfc_se se;
6408 gfc_se cptrse;
6409 gfc_se fptrse;
6410 gfc_se shapese;
6411 gfc_ss *shape_ss;
6412 tree desc, dim, tmp, stride, offset;
6413 stmtblock_t body, block;
6414 gfc_loopinfo loop;
6415 gfc_actual_arglist *arg = code->ext.actual;
6417 gfc_init_se (&se, NULL);
6418 gfc_init_se (&cptrse, NULL);
6419 gfc_conv_expr (&cptrse, arg->expr);
6420 gfc_add_block_to_block (&se.pre, &cptrse.pre);
6421 gfc_add_block_to_block (&se.post, &cptrse.post);
6423 gfc_init_se (&fptrse, NULL);
6424 if (arg->next->expr->rank == 0)
6426 fptrse.want_pointer = 1;
6427 gfc_conv_expr (&fptrse, arg->next->expr);
6428 gfc_add_block_to_block (&se.pre, &fptrse.pre);
6429 gfc_add_block_to_block (&se.post, &fptrse.post);
6430 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
6431 && arg->next->expr->symtree->n.sym->attr.dummy)
6432 fptrse.expr = build_fold_indirect_ref_loc (input_location,
6433 fptrse.expr);
6434 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
6435 TREE_TYPE (fptrse.expr),
6436 fptrse.expr,
6437 fold_convert (TREE_TYPE (fptrse.expr),
6438 cptrse.expr));
6439 gfc_add_expr_to_block (&se.pre, se.expr);
6440 gfc_add_block_to_block (&se.pre, &se.post);
6441 return gfc_finish_block (&se.pre);
6444 gfc_start_block (&block);
6446 /* Get the descriptor of the Fortran pointer. */
6447 fptrse.descriptor_only = 1;
6448 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
6449 gfc_add_block_to_block (&block, &fptrse.pre);
6450 desc = fptrse.expr;
6452 /* Set data value, dtype, and offset. */
6453 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
6454 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
6455 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
6456 gfc_get_dtype (TREE_TYPE (desc)));
6458 /* Start scalarization of the bounds, using the shape argument. */
6460 shape_ss = gfc_walk_expr (arg->next->next->expr);
6461 gcc_assert (shape_ss != gfc_ss_terminator);
6462 gfc_init_se (&shapese, NULL);
6464 gfc_init_loopinfo (&loop);
6465 gfc_add_ss_to_loop (&loop, shape_ss);
6466 gfc_conv_ss_startstride (&loop);
6467 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
6468 gfc_mark_ss_chain_used (shape_ss, 1);
6470 gfc_copy_loopinfo_to_se (&shapese, &loop);
6471 shapese.ss = shape_ss;
6473 stride = gfc_create_var (gfc_array_index_type, "stride");
6474 offset = gfc_create_var (gfc_array_index_type, "offset");
6475 gfc_add_modify (&block, stride, gfc_index_one_node);
6476 gfc_add_modify (&block, offset, gfc_index_zero_node);
6478 /* Loop body. */
6479 gfc_start_scalarized_body (&loop, &body);
6481 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6482 loop.loopvar[0], loop.from[0]);
6484 /* Set bounds and stride. */
6485 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
6486 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
6488 gfc_conv_expr (&shapese, arg->next->next->expr);
6489 gfc_add_block_to_block (&body, &shapese.pre);
6490 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
6491 gfc_add_block_to_block (&body, &shapese.post);
6493 /* Calculate offset. */
6494 gfc_add_modify (&body, offset,
6495 fold_build2_loc (input_location, PLUS_EXPR,
6496 gfc_array_index_type, offset, stride));
6497 /* Update stride. */
6498 gfc_add_modify (&body, stride,
6499 fold_build2_loc (input_location, MULT_EXPR,
6500 gfc_array_index_type, stride,
6501 fold_convert (gfc_array_index_type,
6502 shapese.expr)));
6503 /* Finish scalarization loop. */
6504 gfc_trans_scalarizing_loops (&loop, &body);
6505 gfc_add_block_to_block (&block, &loop.pre);
6506 gfc_add_block_to_block (&block, &loop.post);
6507 gfc_add_block_to_block (&block, &fptrse.post);
6508 gfc_cleanup_loop (&loop);
6510 gfc_add_modify (&block, offset,
6511 fold_build1_loc (input_location, NEGATE_EXPR,
6512 gfc_array_index_type, offset));
6513 gfc_conv_descriptor_offset_set (&block, desc, offset);
6515 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
6516 gfc_add_block_to_block (&se.pre, &se.post);
6517 return gfc_finish_block (&se.pre);
6521 /* Generate code for an intrinsic function. Some map directly to library
6522 calls, others get special handling. In some cases the name of the function
6523 used depends on the type specifiers. */
6525 void
6526 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
6528 const char *name;
6529 int lib, kind;
6530 tree fndecl;
6532 name = &expr->value.function.name[2];
6534 if (expr->rank > 0)
6536 lib = gfc_is_intrinsic_libcall (expr);
6537 if (lib != 0)
6539 if (lib == 1)
6540 se->ignore_optional = 1;
6542 switch (expr->value.function.isym->id)
6544 case GFC_ISYM_EOSHIFT:
6545 case GFC_ISYM_PACK:
6546 case GFC_ISYM_RESHAPE:
6547 /* For all of those the first argument specifies the type and the
6548 third is optional. */
6549 conv_generic_with_optional_char_arg (se, expr, 1, 3);
6550 break;
6552 default:
6553 gfc_conv_intrinsic_funcall (se, expr);
6554 break;
6557 return;
6561 switch (expr->value.function.isym->id)
6563 case GFC_ISYM_NONE:
6564 gcc_unreachable ();
6566 case GFC_ISYM_REPEAT:
6567 gfc_conv_intrinsic_repeat (se, expr);
6568 break;
6570 case GFC_ISYM_TRIM:
6571 gfc_conv_intrinsic_trim (se, expr);
6572 break;
6574 case GFC_ISYM_SC_KIND:
6575 gfc_conv_intrinsic_sc_kind (se, expr);
6576 break;
6578 case GFC_ISYM_SI_KIND:
6579 gfc_conv_intrinsic_si_kind (se, expr);
6580 break;
6582 case GFC_ISYM_SR_KIND:
6583 gfc_conv_intrinsic_sr_kind (se, expr);
6584 break;
6586 case GFC_ISYM_EXPONENT:
6587 gfc_conv_intrinsic_exponent (se, expr);
6588 break;
6590 case GFC_ISYM_SCAN:
6591 kind = expr->value.function.actual->expr->ts.kind;
6592 if (kind == 1)
6593 fndecl = gfor_fndecl_string_scan;
6594 else if (kind == 4)
6595 fndecl = gfor_fndecl_string_scan_char4;
6596 else
6597 gcc_unreachable ();
6599 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6600 break;
6602 case GFC_ISYM_VERIFY:
6603 kind = expr->value.function.actual->expr->ts.kind;
6604 if (kind == 1)
6605 fndecl = gfor_fndecl_string_verify;
6606 else if (kind == 4)
6607 fndecl = gfor_fndecl_string_verify_char4;
6608 else
6609 gcc_unreachable ();
6611 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6612 break;
6614 case GFC_ISYM_ALLOCATED:
6615 gfc_conv_allocated (se, expr);
6616 break;
6618 case GFC_ISYM_ASSOCIATED:
6619 gfc_conv_associated(se, expr);
6620 break;
6622 case GFC_ISYM_SAME_TYPE_AS:
6623 gfc_conv_same_type_as (se, expr);
6624 break;
6626 case GFC_ISYM_ABS:
6627 gfc_conv_intrinsic_abs (se, expr);
6628 break;
6630 case GFC_ISYM_ADJUSTL:
6631 if (expr->ts.kind == 1)
6632 fndecl = gfor_fndecl_adjustl;
6633 else if (expr->ts.kind == 4)
6634 fndecl = gfor_fndecl_adjustl_char4;
6635 else
6636 gcc_unreachable ();
6638 gfc_conv_intrinsic_adjust (se, expr, fndecl);
6639 break;
6641 case GFC_ISYM_ADJUSTR:
6642 if (expr->ts.kind == 1)
6643 fndecl = gfor_fndecl_adjustr;
6644 else if (expr->ts.kind == 4)
6645 fndecl = gfor_fndecl_adjustr_char4;
6646 else
6647 gcc_unreachable ();
6649 gfc_conv_intrinsic_adjust (se, expr, fndecl);
6650 break;
6652 case GFC_ISYM_AIMAG:
6653 gfc_conv_intrinsic_imagpart (se, expr);
6654 break;
6656 case GFC_ISYM_AINT:
6657 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
6658 break;
6660 case GFC_ISYM_ALL:
6661 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
6662 break;
6664 case GFC_ISYM_ANINT:
6665 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
6666 break;
6668 case GFC_ISYM_AND:
6669 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
6670 break;
6672 case GFC_ISYM_ANY:
6673 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
6674 break;
6676 case GFC_ISYM_BTEST:
6677 gfc_conv_intrinsic_btest (se, expr);
6678 break;
6680 case GFC_ISYM_BGE:
6681 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
6682 break;
6684 case GFC_ISYM_BGT:
6685 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
6686 break;
6688 case GFC_ISYM_BLE:
6689 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
6690 break;
6692 case GFC_ISYM_BLT:
6693 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
6694 break;
6696 case GFC_ISYM_C_ASSOCIATED:
6697 case GFC_ISYM_C_FUNLOC:
6698 case GFC_ISYM_C_LOC:
6699 conv_isocbinding_function (se, expr);
6700 break;
6702 case GFC_ISYM_ACHAR:
6703 case GFC_ISYM_CHAR:
6704 gfc_conv_intrinsic_char (se, expr);
6705 break;
6707 case GFC_ISYM_CONVERSION:
6708 case GFC_ISYM_REAL:
6709 case GFC_ISYM_LOGICAL:
6710 case GFC_ISYM_DBLE:
6711 gfc_conv_intrinsic_conversion (se, expr);
6712 break;
6714 /* Integer conversions are handled separately to make sure we get the
6715 correct rounding mode. */
6716 case GFC_ISYM_INT:
6717 case GFC_ISYM_INT2:
6718 case GFC_ISYM_INT8:
6719 case GFC_ISYM_LONG:
6720 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
6721 break;
6723 case GFC_ISYM_NINT:
6724 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
6725 break;
6727 case GFC_ISYM_CEILING:
6728 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
6729 break;
6731 case GFC_ISYM_FLOOR:
6732 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
6733 break;
6735 case GFC_ISYM_MOD:
6736 gfc_conv_intrinsic_mod (se, expr, 0);
6737 break;
6739 case GFC_ISYM_MODULO:
6740 gfc_conv_intrinsic_mod (se, expr, 1);
6741 break;
6743 case GFC_ISYM_CMPLX:
6744 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
6745 break;
6747 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
6748 gfc_conv_intrinsic_iargc (se, expr);
6749 break;
6751 case GFC_ISYM_COMPLEX:
6752 gfc_conv_intrinsic_cmplx (se, expr, 1);
6753 break;
6755 case GFC_ISYM_CONJG:
6756 gfc_conv_intrinsic_conjg (se, expr);
6757 break;
6759 case GFC_ISYM_COUNT:
6760 gfc_conv_intrinsic_count (se, expr);
6761 break;
6763 case GFC_ISYM_CTIME:
6764 gfc_conv_intrinsic_ctime (se, expr);
6765 break;
6767 case GFC_ISYM_DIM:
6768 gfc_conv_intrinsic_dim (se, expr);
6769 break;
6771 case GFC_ISYM_DOT_PRODUCT:
6772 gfc_conv_intrinsic_dot_product (se, expr);
6773 break;
6775 case GFC_ISYM_DPROD:
6776 gfc_conv_intrinsic_dprod (se, expr);
6777 break;
6779 case GFC_ISYM_DSHIFTL:
6780 gfc_conv_intrinsic_dshift (se, expr, true);
6781 break;
6783 case GFC_ISYM_DSHIFTR:
6784 gfc_conv_intrinsic_dshift (se, expr, false);
6785 break;
6787 case GFC_ISYM_FDATE:
6788 gfc_conv_intrinsic_fdate (se, expr);
6789 break;
6791 case GFC_ISYM_FRACTION:
6792 gfc_conv_intrinsic_fraction (se, expr);
6793 break;
6795 case GFC_ISYM_IALL:
6796 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
6797 break;
6799 case GFC_ISYM_IAND:
6800 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
6801 break;
6803 case GFC_ISYM_IANY:
6804 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
6805 break;
6807 case GFC_ISYM_IBCLR:
6808 gfc_conv_intrinsic_singlebitop (se, expr, 0);
6809 break;
6811 case GFC_ISYM_IBITS:
6812 gfc_conv_intrinsic_ibits (se, expr);
6813 break;
6815 case GFC_ISYM_IBSET:
6816 gfc_conv_intrinsic_singlebitop (se, expr, 1);
6817 break;
6819 case GFC_ISYM_IACHAR:
6820 case GFC_ISYM_ICHAR:
6821 /* We assume ASCII character sequence. */
6822 gfc_conv_intrinsic_ichar (se, expr);
6823 break;
6825 case GFC_ISYM_IARGC:
6826 gfc_conv_intrinsic_iargc (se, expr);
6827 break;
6829 case GFC_ISYM_IEOR:
6830 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
6831 break;
6833 case GFC_ISYM_INDEX:
6834 kind = expr->value.function.actual->expr->ts.kind;
6835 if (kind == 1)
6836 fndecl = gfor_fndecl_string_index;
6837 else if (kind == 4)
6838 fndecl = gfor_fndecl_string_index_char4;
6839 else
6840 gcc_unreachable ();
6842 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6843 break;
6845 case GFC_ISYM_IOR:
6846 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
6847 break;
6849 case GFC_ISYM_IPARITY:
6850 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
6851 break;
6853 case GFC_ISYM_IS_IOSTAT_END:
6854 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
6855 break;
6857 case GFC_ISYM_IS_IOSTAT_EOR:
6858 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
6859 break;
6861 case GFC_ISYM_ISNAN:
6862 gfc_conv_intrinsic_isnan (se, expr);
6863 break;
6865 case GFC_ISYM_LSHIFT:
6866 gfc_conv_intrinsic_shift (se, expr, false, false);
6867 break;
6869 case GFC_ISYM_RSHIFT:
6870 gfc_conv_intrinsic_shift (se, expr, true, true);
6871 break;
6873 case GFC_ISYM_SHIFTA:
6874 gfc_conv_intrinsic_shift (se, expr, true, true);
6875 break;
6877 case GFC_ISYM_SHIFTL:
6878 gfc_conv_intrinsic_shift (se, expr, false, false);
6879 break;
6881 case GFC_ISYM_SHIFTR:
6882 gfc_conv_intrinsic_shift (se, expr, true, false);
6883 break;
6885 case GFC_ISYM_ISHFT:
6886 gfc_conv_intrinsic_ishft (se, expr);
6887 break;
6889 case GFC_ISYM_ISHFTC:
6890 gfc_conv_intrinsic_ishftc (se, expr);
6891 break;
6893 case GFC_ISYM_LEADZ:
6894 gfc_conv_intrinsic_leadz (se, expr);
6895 break;
6897 case GFC_ISYM_TRAILZ:
6898 gfc_conv_intrinsic_trailz (se, expr);
6899 break;
6901 case GFC_ISYM_POPCNT:
6902 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
6903 break;
6905 case GFC_ISYM_POPPAR:
6906 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
6907 break;
6909 case GFC_ISYM_LBOUND:
6910 gfc_conv_intrinsic_bound (se, expr, 0);
6911 break;
6913 case GFC_ISYM_LCOBOUND:
6914 conv_intrinsic_cobound (se, expr);
6915 break;
6917 case GFC_ISYM_TRANSPOSE:
6918 /* The scalarizer has already been set up for reversed dimension access
6919 order ; now we just get the argument value normally. */
6920 gfc_conv_expr (se, expr->value.function.actual->expr);
6921 break;
6923 case GFC_ISYM_LEN:
6924 gfc_conv_intrinsic_len (se, expr);
6925 break;
6927 case GFC_ISYM_LEN_TRIM:
6928 gfc_conv_intrinsic_len_trim (se, expr);
6929 break;
6931 case GFC_ISYM_LGE:
6932 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
6933 break;
6935 case GFC_ISYM_LGT:
6936 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
6937 break;
6939 case GFC_ISYM_LLE:
6940 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
6941 break;
6943 case GFC_ISYM_LLT:
6944 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
6945 break;
6947 case GFC_ISYM_MASKL:
6948 gfc_conv_intrinsic_mask (se, expr, 1);
6949 break;
6951 case GFC_ISYM_MASKR:
6952 gfc_conv_intrinsic_mask (se, expr, 0);
6953 break;
6955 case GFC_ISYM_MAX:
6956 if (expr->ts.type == BT_CHARACTER)
6957 gfc_conv_intrinsic_minmax_char (se, expr, 1);
6958 else
6959 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
6960 break;
6962 case GFC_ISYM_MAXLOC:
6963 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
6964 break;
6966 case GFC_ISYM_MAXVAL:
6967 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
6968 break;
6970 case GFC_ISYM_MERGE:
6971 gfc_conv_intrinsic_merge (se, expr);
6972 break;
6974 case GFC_ISYM_MERGE_BITS:
6975 gfc_conv_intrinsic_merge_bits (se, expr);
6976 break;
6978 case GFC_ISYM_MIN:
6979 if (expr->ts.type == BT_CHARACTER)
6980 gfc_conv_intrinsic_minmax_char (se, expr, -1);
6981 else
6982 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
6983 break;
6985 case GFC_ISYM_MINLOC:
6986 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
6987 break;
6989 case GFC_ISYM_MINVAL:
6990 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
6991 break;
6993 case GFC_ISYM_NEAREST:
6994 gfc_conv_intrinsic_nearest (se, expr);
6995 break;
6997 case GFC_ISYM_NORM2:
6998 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
6999 break;
7001 case GFC_ISYM_NOT:
7002 gfc_conv_intrinsic_not (se, expr);
7003 break;
7005 case GFC_ISYM_OR:
7006 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
7007 break;
7009 case GFC_ISYM_PARITY:
7010 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
7011 break;
7013 case GFC_ISYM_PRESENT:
7014 gfc_conv_intrinsic_present (se, expr);
7015 break;
7017 case GFC_ISYM_PRODUCT:
7018 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
7019 break;
7021 case GFC_ISYM_RANK:
7022 gfc_conv_intrinsic_rank (se, expr);
7023 break;
7025 case GFC_ISYM_RRSPACING:
7026 gfc_conv_intrinsic_rrspacing (se, expr);
7027 break;
7029 case GFC_ISYM_SET_EXPONENT:
7030 gfc_conv_intrinsic_set_exponent (se, expr);
7031 break;
7033 case GFC_ISYM_SCALE:
7034 gfc_conv_intrinsic_scale (se, expr);
7035 break;
7037 case GFC_ISYM_SIGN:
7038 gfc_conv_intrinsic_sign (se, expr);
7039 break;
7041 case GFC_ISYM_SIZE:
7042 gfc_conv_intrinsic_size (se, expr);
7043 break;
7045 case GFC_ISYM_SIZEOF:
7046 case GFC_ISYM_C_SIZEOF:
7047 gfc_conv_intrinsic_sizeof (se, expr);
7048 break;
7050 case GFC_ISYM_STORAGE_SIZE:
7051 gfc_conv_intrinsic_storage_size (se, expr);
7052 break;
7054 case GFC_ISYM_SPACING:
7055 gfc_conv_intrinsic_spacing (se, expr);
7056 break;
7058 case GFC_ISYM_STRIDE:
7059 conv_intrinsic_stride (se, expr);
7060 break;
7062 case GFC_ISYM_SUM:
7063 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
7064 break;
7066 case GFC_ISYM_TRANSFER:
7067 if (se->ss && se->ss->info->useflags)
7068 /* Access the previously obtained result. */
7069 gfc_conv_tmp_array_ref (se);
7070 else
7071 gfc_conv_intrinsic_transfer (se, expr);
7072 break;
7074 case GFC_ISYM_TTYNAM:
7075 gfc_conv_intrinsic_ttynam (se, expr);
7076 break;
7078 case GFC_ISYM_UBOUND:
7079 gfc_conv_intrinsic_bound (se, expr, 1);
7080 break;
7082 case GFC_ISYM_UCOBOUND:
7083 conv_intrinsic_cobound (se, expr);
7084 break;
7086 case GFC_ISYM_XOR:
7087 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
7088 break;
7090 case GFC_ISYM_LOC:
7091 gfc_conv_intrinsic_loc (se, expr);
7092 break;
7094 case GFC_ISYM_THIS_IMAGE:
7095 /* For num_images() == 1, handle as LCOBOUND. */
7096 if (expr->value.function.actual->expr
7097 && gfc_option.coarray == GFC_FCOARRAY_SINGLE)
7098 conv_intrinsic_cobound (se, expr);
7099 else
7100 trans_this_image (se, expr);
7101 break;
7103 case GFC_ISYM_IMAGE_INDEX:
7104 trans_image_index (se, expr);
7105 break;
7107 case GFC_ISYM_NUM_IMAGES:
7108 trans_num_images (se);
7109 break;
7111 case GFC_ISYM_ACCESS:
7112 case GFC_ISYM_CHDIR:
7113 case GFC_ISYM_CHMOD:
7114 case GFC_ISYM_DTIME:
7115 case GFC_ISYM_ETIME:
7116 case GFC_ISYM_EXTENDS_TYPE_OF:
7117 case GFC_ISYM_FGET:
7118 case GFC_ISYM_FGETC:
7119 case GFC_ISYM_FNUM:
7120 case GFC_ISYM_FPUT:
7121 case GFC_ISYM_FPUTC:
7122 case GFC_ISYM_FSTAT:
7123 case GFC_ISYM_FTELL:
7124 case GFC_ISYM_GETCWD:
7125 case GFC_ISYM_GETGID:
7126 case GFC_ISYM_GETPID:
7127 case GFC_ISYM_GETUID:
7128 case GFC_ISYM_HOSTNM:
7129 case GFC_ISYM_KILL:
7130 case GFC_ISYM_IERRNO:
7131 case GFC_ISYM_IRAND:
7132 case GFC_ISYM_ISATTY:
7133 case GFC_ISYM_JN2:
7134 case GFC_ISYM_LINK:
7135 case GFC_ISYM_LSTAT:
7136 case GFC_ISYM_MALLOC:
7137 case GFC_ISYM_MATMUL:
7138 case GFC_ISYM_MCLOCK:
7139 case GFC_ISYM_MCLOCK8:
7140 case GFC_ISYM_RAND:
7141 case GFC_ISYM_RENAME:
7142 case GFC_ISYM_SECOND:
7143 case GFC_ISYM_SECNDS:
7144 case GFC_ISYM_SIGNAL:
7145 case GFC_ISYM_STAT:
7146 case GFC_ISYM_SYMLNK:
7147 case GFC_ISYM_SYSTEM:
7148 case GFC_ISYM_TIME:
7149 case GFC_ISYM_TIME8:
7150 case GFC_ISYM_UMASK:
7151 case GFC_ISYM_UNLINK:
7152 case GFC_ISYM_YN2:
7153 gfc_conv_intrinsic_funcall (se, expr);
7154 break;
7156 case GFC_ISYM_EOSHIFT:
7157 case GFC_ISYM_PACK:
7158 case GFC_ISYM_RESHAPE:
7159 /* For those, expr->rank should always be >0 and thus the if above the
7160 switch should have matched. */
7161 gcc_unreachable ();
7162 break;
7164 default:
7165 gfc_conv_intrinsic_lib_function (se, expr);
7166 break;
7171 static gfc_ss *
7172 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
7174 gfc_ss *arg_ss, *tmp_ss;
7175 gfc_actual_arglist *arg;
7177 arg = expr->value.function.actual;
7179 gcc_assert (arg->expr);
7181 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
7182 gcc_assert (arg_ss != gfc_ss_terminator);
7184 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
7186 if (tmp_ss->info->type != GFC_SS_SCALAR
7187 && tmp_ss->info->type != GFC_SS_REFERENCE)
7189 int tmp_dim;
7191 gcc_assert (tmp_ss->dimen == 2);
7193 /* We just invert dimensions. */
7194 tmp_dim = tmp_ss->dim[0];
7195 tmp_ss->dim[0] = tmp_ss->dim[1];
7196 tmp_ss->dim[1] = tmp_dim;
7199 /* Stop when tmp_ss points to the last valid element of the chain... */
7200 if (tmp_ss->next == gfc_ss_terminator)
7201 break;
7204 /* ... so that we can attach the rest of the chain to it. */
7205 tmp_ss->next = ss;
7207 return arg_ss;
7211 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
7212 This has the side effect of reversing the nested list, so there is no
7213 need to call gfc_reverse_ss on it (the given list is assumed not to be
7214 reversed yet). */
7216 static gfc_ss *
7217 nest_loop_dimension (gfc_ss *ss, int dim)
7219 int ss_dim, i;
7220 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
7221 gfc_loopinfo *new_loop;
7223 gcc_assert (ss != gfc_ss_terminator);
7225 for (; ss != gfc_ss_terminator; ss = ss->next)
7227 new_ss = gfc_get_ss ();
7228 new_ss->next = prev_ss;
7229 new_ss->parent = ss;
7230 new_ss->info = ss->info;
7231 new_ss->info->refcount++;
7232 if (ss->dimen != 0)
7234 gcc_assert (ss->info->type != GFC_SS_SCALAR
7235 && ss->info->type != GFC_SS_REFERENCE);
7237 new_ss->dimen = 1;
7238 new_ss->dim[0] = ss->dim[dim];
7240 gcc_assert (dim < ss->dimen);
7242 ss_dim = --ss->dimen;
7243 for (i = dim; i < ss_dim; i++)
7244 ss->dim[i] = ss->dim[i + 1];
7246 ss->dim[ss_dim] = 0;
7248 prev_ss = new_ss;
7250 if (ss->nested_ss)
7252 ss->nested_ss->parent = new_ss;
7253 new_ss->nested_ss = ss->nested_ss;
7255 ss->nested_ss = new_ss;
7258 new_loop = gfc_get_loopinfo ();
7259 gfc_init_loopinfo (new_loop);
7261 gcc_assert (prev_ss != NULL);
7262 gcc_assert (prev_ss != gfc_ss_terminator);
7263 gfc_add_ss_to_loop (new_loop, prev_ss);
7264 return new_ss->parent;
7268 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
7269 is to be inlined. */
7271 static gfc_ss *
7272 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
7274 gfc_ss *tmp_ss, *tail, *array_ss;
7275 gfc_actual_arglist *arg1, *arg2, *arg3;
7276 int sum_dim;
7277 bool scalar_mask = false;
7279 /* The rank of the result will be determined later. */
7280 arg1 = expr->value.function.actual;
7281 arg2 = arg1->next;
7282 arg3 = arg2->next;
7283 gcc_assert (arg3 != NULL);
7285 if (expr->rank == 0)
7286 return ss;
7288 tmp_ss = gfc_ss_terminator;
7290 if (arg3->expr)
7292 gfc_ss *mask_ss;
7294 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
7295 if (mask_ss == tmp_ss)
7296 scalar_mask = 1;
7298 tmp_ss = mask_ss;
7301 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
7302 gcc_assert (array_ss != tmp_ss);
7304 /* Odd thing: If the mask is scalar, it is used by the frontend after
7305 the array (to make an if around the nested loop). Thus it shall
7306 be after array_ss once the gfc_ss list is reversed. */
7307 if (scalar_mask)
7308 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
7309 else
7310 tmp_ss = array_ss;
7312 /* "Hide" the dimension on which we will sum in the first arg's scalarization
7313 chain. */
7314 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
7315 tail = nest_loop_dimension (tmp_ss, sum_dim);
7316 tail->next = ss;
7318 return tmp_ss;
7322 static gfc_ss *
7323 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
7326 switch (expr->value.function.isym->id)
7328 case GFC_ISYM_PRODUCT:
7329 case GFC_ISYM_SUM:
7330 return walk_inline_intrinsic_arith (ss, expr);
7332 case GFC_ISYM_TRANSPOSE:
7333 return walk_inline_intrinsic_transpose (ss, expr);
7335 default:
7336 gcc_unreachable ();
7338 gcc_unreachable ();
7342 /* This generates code to execute before entering the scalarization loop.
7343 Currently does nothing. */
7345 void
7346 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
7348 switch (ss->info->expr->value.function.isym->id)
7350 case GFC_ISYM_UBOUND:
7351 case GFC_ISYM_LBOUND:
7352 case GFC_ISYM_UCOBOUND:
7353 case GFC_ISYM_LCOBOUND:
7354 case GFC_ISYM_THIS_IMAGE:
7355 break;
7357 default:
7358 gcc_unreachable ();
7363 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
7364 are expanded into code inside the scalarization loop. */
7366 static gfc_ss *
7367 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
7369 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
7370 gfc_add_class_array_ref (expr->value.function.actual->expr);
7372 /* The two argument version returns a scalar. */
7373 if (expr->value.function.actual->next->expr)
7374 return ss;
7376 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
7380 /* Walk an intrinsic array libcall. */
7382 static gfc_ss *
7383 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
7385 gcc_assert (expr->rank > 0);
7386 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
7390 /* Return whether the function call expression EXPR will be expanded
7391 inline by gfc_conv_intrinsic_function. */
7393 bool
7394 gfc_inline_intrinsic_function_p (gfc_expr *expr)
7396 gfc_actual_arglist *args;
7398 if (!expr->value.function.isym)
7399 return false;
7401 switch (expr->value.function.isym->id)
7403 case GFC_ISYM_PRODUCT:
7404 case GFC_ISYM_SUM:
7405 /* Disable inline expansion if code size matters. */
7406 if (optimize_size)
7407 return false;
7409 args = expr->value.function.actual;
7410 /* We need to be able to subset the SUM argument at compile-time. */
7411 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
7412 return false;
7414 return true;
7416 case GFC_ISYM_TRANSPOSE:
7417 return true;
7419 default:
7420 return false;
7425 /* Returns nonzero if the specified intrinsic function call maps directly to
7426 an external library call. Should only be used for functions that return
7427 arrays. */
7430 gfc_is_intrinsic_libcall (gfc_expr * expr)
7432 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
7433 gcc_assert (expr->rank > 0);
7435 if (gfc_inline_intrinsic_function_p (expr))
7436 return 0;
7438 switch (expr->value.function.isym->id)
7440 case GFC_ISYM_ALL:
7441 case GFC_ISYM_ANY:
7442 case GFC_ISYM_COUNT:
7443 case GFC_ISYM_JN2:
7444 case GFC_ISYM_IANY:
7445 case GFC_ISYM_IALL:
7446 case GFC_ISYM_IPARITY:
7447 case GFC_ISYM_MATMUL:
7448 case GFC_ISYM_MAXLOC:
7449 case GFC_ISYM_MAXVAL:
7450 case GFC_ISYM_MINLOC:
7451 case GFC_ISYM_MINVAL:
7452 case GFC_ISYM_NORM2:
7453 case GFC_ISYM_PARITY:
7454 case GFC_ISYM_PRODUCT:
7455 case GFC_ISYM_SUM:
7456 case GFC_ISYM_SHAPE:
7457 case GFC_ISYM_SPREAD:
7458 case GFC_ISYM_YN2:
7459 /* Ignore absent optional parameters. */
7460 return 1;
7462 case GFC_ISYM_RESHAPE:
7463 case GFC_ISYM_CSHIFT:
7464 case GFC_ISYM_EOSHIFT:
7465 case GFC_ISYM_PACK:
7466 case GFC_ISYM_UNPACK:
7467 /* Pass absent optional parameters. */
7468 return 2;
7470 default:
7471 return 0;
7475 /* Walk an intrinsic function. */
7476 gfc_ss *
7477 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
7478 gfc_intrinsic_sym * isym)
7480 gcc_assert (isym);
7482 if (isym->elemental)
7483 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
7484 NULL, GFC_SS_SCALAR);
7486 if (expr->rank == 0)
7487 return ss;
7489 if (gfc_inline_intrinsic_function_p (expr))
7490 return walk_inline_intrinsic_function (ss, expr);
7492 if (gfc_is_intrinsic_libcall (expr))
7493 return gfc_walk_intrinsic_libfunc (ss, expr);
7495 /* Special cases. */
7496 switch (isym->id)
7498 case GFC_ISYM_LBOUND:
7499 case GFC_ISYM_LCOBOUND:
7500 case GFC_ISYM_UBOUND:
7501 case GFC_ISYM_UCOBOUND:
7502 case GFC_ISYM_THIS_IMAGE:
7503 return gfc_walk_intrinsic_bound (ss, expr);
7505 case GFC_ISYM_TRANSFER:
7506 return gfc_walk_intrinsic_libfunc (ss, expr);
7508 default:
7509 /* This probably meant someone forgot to add an intrinsic to the above
7510 list(s) when they implemented it, or something's gone horribly
7511 wrong. */
7512 gcc_unreachable ();
7517 static tree
7518 conv_intrinsic_atomic_def (gfc_code *code)
7520 gfc_se atom, value;
7521 stmtblock_t block;
7523 gfc_init_se (&atom, NULL);
7524 gfc_init_se (&value, NULL);
7525 gfc_conv_expr (&atom, code->ext.actual->expr);
7526 gfc_conv_expr (&value, code->ext.actual->next->expr);
7528 gfc_init_block (&block);
7529 gfc_add_modify (&block, atom.expr,
7530 fold_convert (TREE_TYPE (atom.expr), value.expr));
7531 return gfc_finish_block (&block);
7535 static tree
7536 conv_intrinsic_atomic_ref (gfc_code *code)
7538 gfc_se atom, value;
7539 stmtblock_t block;
7541 gfc_init_se (&atom, NULL);
7542 gfc_init_se (&value, NULL);
7543 gfc_conv_expr (&value, code->ext.actual->expr);
7544 gfc_conv_expr (&atom, code->ext.actual->next->expr);
7546 gfc_init_block (&block);
7547 gfc_add_modify (&block, value.expr,
7548 fold_convert (TREE_TYPE (value.expr), atom.expr));
7549 return gfc_finish_block (&block);
7553 static tree
7554 conv_intrinsic_move_alloc (gfc_code *code)
7556 stmtblock_t block;
7557 gfc_expr *from_expr, *to_expr;
7558 gfc_expr *to_expr2, *from_expr2 = NULL;
7559 gfc_se from_se, to_se;
7560 tree tmp;
7561 bool coarray;
7563 gfc_start_block (&block);
7565 from_expr = code->ext.actual->expr;
7566 to_expr = code->ext.actual->next->expr;
7568 gfc_init_se (&from_se, NULL);
7569 gfc_init_se (&to_se, NULL);
7571 gcc_assert (from_expr->ts.type != BT_CLASS
7572 || to_expr->ts.type == BT_CLASS);
7573 coarray = gfc_get_corank (from_expr) != 0;
7575 if (from_expr->rank == 0 && !coarray)
7577 if (from_expr->ts.type != BT_CLASS)
7578 from_expr2 = from_expr;
7579 else
7581 from_expr2 = gfc_copy_expr (from_expr);
7582 gfc_add_data_component (from_expr2);
7585 if (to_expr->ts.type != BT_CLASS)
7586 to_expr2 = to_expr;
7587 else
7589 to_expr2 = gfc_copy_expr (to_expr);
7590 gfc_add_data_component (to_expr2);
7593 from_se.want_pointer = 1;
7594 to_se.want_pointer = 1;
7595 gfc_conv_expr (&from_se, from_expr2);
7596 gfc_conv_expr (&to_se, to_expr2);
7597 gfc_add_block_to_block (&block, &from_se.pre);
7598 gfc_add_block_to_block (&block, &to_se.pre);
7600 /* Deallocate "to". */
7601 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, true,
7602 to_expr, to_expr->ts);
7603 gfc_add_expr_to_block (&block, tmp);
7605 /* Assign (_data) pointers. */
7606 gfc_add_modify_loc (input_location, &block, to_se.expr,
7607 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
7609 /* Set "from" to NULL. */
7610 gfc_add_modify_loc (input_location, &block, from_se.expr,
7611 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
7613 gfc_add_block_to_block (&block, &from_se.post);
7614 gfc_add_block_to_block (&block, &to_se.post);
7616 /* Set _vptr. */
7617 if (to_expr->ts.type == BT_CLASS)
7619 gfc_symbol *vtab;
7621 gfc_free_expr (to_expr2);
7622 gfc_init_se (&to_se, NULL);
7623 to_se.want_pointer = 1;
7624 gfc_add_vptr_component (to_expr);
7625 gfc_conv_expr (&to_se, to_expr);
7627 if (from_expr->ts.type == BT_CLASS)
7629 if (UNLIMITED_POLY (from_expr))
7630 vtab = NULL;
7631 else
7633 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
7634 gcc_assert (vtab);
7637 gfc_free_expr (from_expr2);
7638 gfc_init_se (&from_se, NULL);
7639 from_se.want_pointer = 1;
7640 gfc_add_vptr_component (from_expr);
7641 gfc_conv_expr (&from_se, from_expr);
7642 gfc_add_modify_loc (input_location, &block, to_se.expr,
7643 fold_convert (TREE_TYPE (to_se.expr),
7644 from_se.expr));
7646 /* Reset _vptr component to declared type. */
7647 if (vtab == NULL)
7648 /* Unlimited polymorphic. */
7649 gfc_add_modify_loc (input_location, &block, from_se.expr,
7650 fold_convert (TREE_TYPE (from_se.expr),
7651 null_pointer_node));
7652 else
7654 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7655 gfc_add_modify_loc (input_location, &block, from_se.expr,
7656 fold_convert (TREE_TYPE (from_se.expr), tmp));
7659 else
7661 vtab = gfc_find_vtab (&from_expr->ts);
7662 gcc_assert (vtab);
7663 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7664 gfc_add_modify_loc (input_location, &block, to_se.expr,
7665 fold_convert (TREE_TYPE (to_se.expr), tmp));
7669 return gfc_finish_block (&block);
7672 /* Update _vptr component. */
7673 if (to_expr->ts.type == BT_CLASS)
7675 gfc_symbol *vtab;
7677 to_se.want_pointer = 1;
7678 to_expr2 = gfc_copy_expr (to_expr);
7679 gfc_add_vptr_component (to_expr2);
7680 gfc_conv_expr (&to_se, to_expr2);
7682 if (from_expr->ts.type == BT_CLASS)
7684 if (UNLIMITED_POLY (from_expr))
7685 vtab = NULL;
7686 else
7688 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
7689 gcc_assert (vtab);
7692 from_se.want_pointer = 1;
7693 from_expr2 = gfc_copy_expr (from_expr);
7694 gfc_add_vptr_component (from_expr2);
7695 gfc_conv_expr (&from_se, from_expr2);
7696 gfc_add_modify_loc (input_location, &block, to_se.expr,
7697 fold_convert (TREE_TYPE (to_se.expr),
7698 from_se.expr));
7700 /* Reset _vptr component to declared type. */
7701 if (vtab == NULL)
7702 /* Unlimited polymorphic. */
7703 gfc_add_modify_loc (input_location, &block, from_se.expr,
7704 fold_convert (TREE_TYPE (from_se.expr),
7705 null_pointer_node));
7706 else
7708 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7709 gfc_add_modify_loc (input_location, &block, from_se.expr,
7710 fold_convert (TREE_TYPE (from_se.expr), tmp));
7713 else
7715 vtab = gfc_find_vtab (&from_expr->ts);
7716 gcc_assert (vtab);
7717 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7718 gfc_add_modify_loc (input_location, &block, to_se.expr,
7719 fold_convert (TREE_TYPE (to_se.expr), tmp));
7722 gfc_free_expr (to_expr2);
7723 gfc_init_se (&to_se, NULL);
7725 if (from_expr->ts.type == BT_CLASS)
7727 gfc_free_expr (from_expr2);
7728 gfc_init_se (&from_se, NULL);
7733 /* Deallocate "to". */
7734 if (from_expr->rank == 0)
7736 to_se.want_coarray = 1;
7737 from_se.want_coarray = 1;
7739 gfc_conv_expr_descriptor (&to_se, to_expr);
7740 gfc_conv_expr_descriptor (&from_se, from_expr);
7742 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
7743 is an image control "statement", cf. IR F08/0040 in 12-006A. */
7744 if (coarray && gfc_option.coarray == GFC_FCOARRAY_LIB)
7746 tree cond;
7748 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
7749 NULL_TREE, NULL_TREE, true, to_expr,
7750 true);
7751 gfc_add_expr_to_block (&block, tmp);
7753 tmp = gfc_conv_descriptor_data_get (to_se.expr);
7754 cond = fold_build2_loc (input_location, EQ_EXPR,
7755 boolean_type_node, tmp,
7756 fold_convert (TREE_TYPE (tmp),
7757 null_pointer_node));
7758 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
7759 3, null_pointer_node, null_pointer_node,
7760 build_int_cst (integer_type_node, 0));
7762 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
7763 tmp, build_empty_stmt (input_location));
7764 gfc_add_expr_to_block (&block, tmp);
7766 else
7768 tmp = gfc_conv_descriptor_data_get (to_se.expr);
7769 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
7770 NULL_TREE, true, to_expr, false);
7771 gfc_add_expr_to_block (&block, tmp);
7774 /* Move the pointer and update the array descriptor data. */
7775 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
7777 /* Set "from" to NULL. */
7778 tmp = gfc_conv_descriptor_data_get (from_se.expr);
7779 gfc_add_modify_loc (input_location, &block, tmp,
7780 fold_convert (TREE_TYPE (tmp), null_pointer_node));
7782 return gfc_finish_block (&block);
7786 tree
7787 gfc_conv_intrinsic_subroutine (gfc_code *code)
7789 tree res;
7791 gcc_assert (code->resolved_isym);
7793 switch (code->resolved_isym->id)
7795 case GFC_ISYM_MOVE_ALLOC:
7796 res = conv_intrinsic_move_alloc (code);
7797 break;
7799 case GFC_ISYM_ATOMIC_DEF:
7800 res = conv_intrinsic_atomic_def (code);
7801 break;
7803 case GFC_ISYM_ATOMIC_REF:
7804 res = conv_intrinsic_atomic_ref (code);
7805 break;
7807 case GFC_ISYM_C_F_POINTER:
7808 case GFC_ISYM_C_F_PROCPOINTER:
7809 res = conv_isocbinding_subroutine (code);
7810 break;
7813 default:
7814 res = NULL_TREE;
7815 break;
7818 return res;
7821 #include "gt-fortran-trans-intrinsic.h"