2011-03-27 Tobias Burnus <burnus@net-b.de>
[official-gcc.git] / gcc / fortran / trans-intrinsic.c
blobfa3e4c2c060238605441c73eb5bdafd01f593b05
1 /* Intrinsic translation
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
3 Free Software Foundation, Inc.
4 Contributed by Paul Brook <paul@nowt.org>
5 and Steven Bosscher <s.bosscher@student.tudelft.nl>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* trans-intrinsic.c-- generate GENERIC trees for calls to intrinsics. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h" /* For UNITS_PER_WORD. */
29 #include "tree.h"
30 #include "ggc.h"
31 #include "diagnostic-core.h" /* For internal_error. */
32 #include "toplev.h" /* For rest_of_decl_compilation. */
33 #include "flags.h"
34 #include "gfortran.h"
35 #include "arith.h"
36 #include "intrinsic.h"
37 #include "trans.h"
38 #include "trans-const.h"
39 #include "trans-types.h"
40 #include "trans-array.h"
41 #include "defaults.h"
42 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
43 #include "trans-stmt.h"
45 /* This maps fortran intrinsic math functions to external library or GCC
46 builtin functions. */
47 typedef struct GTY(()) gfc_intrinsic_map_t {
48 /* The explicit enum is required to work around inadequacies in the
49 garbage collection/gengtype parsing mechanism. */
50 enum gfc_isym_id id;
52 /* Enum value from the "language-independent", aka C-centric, part
53 of gcc, or END_BUILTINS of no such value set. */
54 enum built_in_function float_built_in;
55 enum built_in_function double_built_in;
56 enum built_in_function long_double_built_in;
57 enum built_in_function complex_float_built_in;
58 enum built_in_function complex_double_built_in;
59 enum built_in_function complex_long_double_built_in;
61 /* True if the naming pattern is to prepend "c" for complex and
62 append "f" for kind=4. False if the naming pattern is to
63 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
64 bool libm_name;
66 /* True if a complex version of the function exists. */
67 bool complex_available;
69 /* True if the function should be marked const. */
70 bool is_constant;
72 /* The base library name of this function. */
73 const char *name;
75 /* Cache decls created for the various operand types. */
76 tree real4_decl;
77 tree real8_decl;
78 tree real10_decl;
79 tree real16_decl;
80 tree complex4_decl;
81 tree complex8_decl;
82 tree complex10_decl;
83 tree complex16_decl;
85 gfc_intrinsic_map_t;
87 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
88 defines complex variants of all of the entries in mathbuiltins.def
89 except for atan2. */
90 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
91 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
92 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
93 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
94 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
96 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
97 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
98 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
99 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
100 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
102 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
103 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
104 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
105 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
106 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
108 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
109 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
110 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
111 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
112 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
114 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
116 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
117 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
118 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
119 #include "mathbuiltins.def"
121 /* Functions in libgfortran. */
122 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
124 /* End the list. */
125 LIB_FUNCTION (NONE, NULL, false)
128 #undef OTHER_BUILTIN
129 #undef LIB_FUNCTION
130 #undef DEFINE_MATH_BUILTIN
131 #undef DEFINE_MATH_BUILTIN_C
134 enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
137 /* Find the correct variant of a given builtin from its argument. */
138 static tree
139 builtin_decl_for_precision (enum built_in_function base_built_in,
140 int precision)
142 int i = END_BUILTINS;
144 gfc_intrinsic_map_t *m;
145 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
148 if (precision == TYPE_PRECISION (float_type_node))
149 i = m->float_built_in;
150 else if (precision == TYPE_PRECISION (double_type_node))
151 i = m->double_built_in;
152 else if (precision == TYPE_PRECISION (long_double_type_node))
153 i = m->long_double_built_in;
154 else if (precision == TYPE_PRECISION (float128_type_node))
156 /* Special treatment, because it is not exactly a built-in, but
157 a library function. */
158 return m->real16_decl;
161 return (i == END_BUILTINS ? NULL_TREE : built_in_decls[i]);
165 tree
166 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
167 int kind)
169 int i = gfc_validate_kind (BT_REAL, kind, false);
171 if (gfc_real_kinds[i].c_float128)
173 /* For __float128, the story is a bit different, because we return
174 a decl to a library function rather than a built-in. */
175 gfc_intrinsic_map_t *m;
176 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
179 return m->real16_decl;
182 return builtin_decl_for_precision (double_built_in,
183 gfc_real_kinds[i].mode_precision);
187 /* Evaluate the arguments to an intrinsic function. The value
188 of NARGS may be less than the actual number of arguments in EXPR
189 to allow optional "KIND" arguments that are not included in the
190 generated code to be ignored. */
192 static void
193 gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
194 tree *argarray, int nargs)
196 gfc_actual_arglist *actual;
197 gfc_expr *e;
198 gfc_intrinsic_arg *formal;
199 gfc_se argse;
200 int curr_arg;
202 formal = expr->value.function.isym->formal;
203 actual = expr->value.function.actual;
205 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
206 actual = actual->next,
207 formal = formal ? formal->next : NULL)
209 gcc_assert (actual);
210 e = actual->expr;
211 /* Skip omitted optional arguments. */
212 if (!e)
214 --curr_arg;
215 continue;
218 /* Evaluate the parameter. This will substitute scalarized
219 references automatically. */
220 gfc_init_se (&argse, se);
222 if (e->ts.type == BT_CHARACTER)
224 gfc_conv_expr (&argse, e);
225 gfc_conv_string_parameter (&argse);
226 argarray[curr_arg++] = argse.string_length;
227 gcc_assert (curr_arg < nargs);
229 else
230 gfc_conv_expr_val (&argse, e);
232 /* If an optional argument is itself an optional dummy argument,
233 check its presence and substitute a null if absent. */
234 if (e->expr_type == EXPR_VARIABLE
235 && e->symtree->n.sym->attr.optional
236 && formal
237 && formal->optional)
238 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
240 gfc_add_block_to_block (&se->pre, &argse.pre);
241 gfc_add_block_to_block (&se->post, &argse.post);
242 argarray[curr_arg] = argse.expr;
246 /* Count the number of actual arguments to the intrinsic function EXPR
247 including any "hidden" string length arguments. */
249 static unsigned int
250 gfc_intrinsic_argument_list_length (gfc_expr *expr)
252 int n = 0;
253 gfc_actual_arglist *actual;
255 for (actual = expr->value.function.actual; actual; actual = actual->next)
257 if (!actual->expr)
258 continue;
260 if (actual->expr->ts.type == BT_CHARACTER)
261 n += 2;
262 else
263 n++;
266 return n;
270 /* Conversions between different types are output by the frontend as
271 intrinsic functions. We implement these directly with inline code. */
273 static void
274 gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
276 tree type;
277 tree *args;
278 int nargs;
280 nargs = gfc_intrinsic_argument_list_length (expr);
281 args = XALLOCAVEC (tree, nargs);
283 /* Evaluate all the arguments passed. Whilst we're only interested in the
284 first one here, there are other parts of the front-end that assume this
285 and will trigger an ICE if it's not the case. */
286 type = gfc_typenode_for_spec (&expr->ts);
287 gcc_assert (expr->value.function.actual->expr);
288 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
290 /* Conversion between character kinds involves a call to a library
291 function. */
292 if (expr->ts.type == BT_CHARACTER)
294 tree fndecl, var, addr, tmp;
296 if (expr->ts.kind == 1
297 && expr->value.function.actual->expr->ts.kind == 4)
298 fndecl = gfor_fndecl_convert_char4_to_char1;
299 else if (expr->ts.kind == 4
300 && expr->value.function.actual->expr->ts.kind == 1)
301 fndecl = gfor_fndecl_convert_char1_to_char4;
302 else
303 gcc_unreachable ();
305 /* Create the variable storing the converted value. */
306 type = gfc_get_pchar_type (expr->ts.kind);
307 var = gfc_create_var (type, "str");
308 addr = gfc_build_addr_expr (build_pointer_type (type), var);
310 /* Call the library function that will perform the conversion. */
311 gcc_assert (nargs >= 2);
312 tmp = build_call_expr_loc (input_location,
313 fndecl, 3, addr, args[0], args[1]);
314 gfc_add_expr_to_block (&se->pre, tmp);
316 /* Free the temporary afterwards. */
317 tmp = gfc_call_free (var);
318 gfc_add_expr_to_block (&se->post, tmp);
320 se->expr = var;
321 se->string_length = args[0];
323 return;
326 /* Conversion from complex to non-complex involves taking the real
327 component of the value. */
328 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
329 && expr->ts.type != BT_COMPLEX)
331 tree artype;
333 artype = TREE_TYPE (TREE_TYPE (args[0]));
334 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
335 args[0]);
338 se->expr = convert (type, args[0]);
341 /* This is needed because the gcc backend only implements
342 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
343 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
344 Similarly for CEILING. */
346 static tree
347 build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
349 tree tmp;
350 tree cond;
351 tree argtype;
352 tree intval;
354 argtype = TREE_TYPE (arg);
355 arg = gfc_evaluate_now (arg, pblock);
357 intval = convert (type, arg);
358 intval = gfc_evaluate_now (intval, pblock);
360 tmp = convert (argtype, intval);
361 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
362 boolean_type_node, tmp, arg);
364 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
365 intval, build_int_cst (type, 1));
366 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
367 return tmp;
371 /* Round to nearest integer, away from zero. */
373 static tree
374 build_round_expr (tree arg, tree restype)
376 tree argtype;
377 tree fn;
378 bool longlong;
379 int argprec, resprec;
381 argtype = TREE_TYPE (arg);
382 argprec = TYPE_PRECISION (argtype);
383 resprec = TYPE_PRECISION (restype);
385 /* Depending on the type of the result, choose the long int intrinsic
386 (lround family) or long long intrinsic (llround). We might also
387 need to convert the result afterwards. */
388 if (resprec <= LONG_TYPE_SIZE)
389 longlong = false;
390 else if (resprec <= LONG_LONG_TYPE_SIZE)
391 longlong = true;
392 else
393 gcc_unreachable ();
395 /* Now, depending on the argument type, we choose between intrinsics. */
396 if (longlong)
397 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
398 else
399 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
401 return fold_convert (restype, build_call_expr_loc (input_location,
402 fn, 1, arg));
406 /* Convert a real to an integer using a specific rounding mode.
407 Ideally we would just build the corresponding GENERIC node,
408 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
410 static tree
411 build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
412 enum rounding_mode op)
414 switch (op)
416 case RND_FLOOR:
417 return build_fixbound_expr (pblock, arg, type, 0);
418 break;
420 case RND_CEIL:
421 return build_fixbound_expr (pblock, arg, type, 1);
422 break;
424 case RND_ROUND:
425 return build_round_expr (arg, type);
426 break;
428 case RND_TRUNC:
429 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
430 break;
432 default:
433 gcc_unreachable ();
438 /* Round a real value using the specified rounding mode.
439 We use a temporary integer of that same kind size as the result.
440 Values larger than those that can be represented by this kind are
441 unchanged, as they will not be accurate enough to represent the
442 rounding.
443 huge = HUGE (KIND (a))
444 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
447 static void
448 gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
450 tree type;
451 tree itype;
452 tree arg[2];
453 tree tmp;
454 tree cond;
455 tree decl;
456 mpfr_t huge;
457 int n, nargs;
458 int kind;
460 kind = expr->ts.kind;
461 nargs = gfc_intrinsic_argument_list_length (expr);
463 decl = NULL_TREE;
464 /* We have builtin functions for some cases. */
465 switch (op)
467 case RND_ROUND:
468 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
469 break;
471 case RND_TRUNC:
472 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
473 break;
475 default:
476 gcc_unreachable ();
479 /* Evaluate the argument. */
480 gcc_assert (expr->value.function.actual->expr);
481 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
483 /* Use a builtin function if one exists. */
484 if (decl != NULL_TREE)
486 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
487 return;
490 /* This code is probably redundant, but we'll keep it lying around just
491 in case. */
492 type = gfc_typenode_for_spec (&expr->ts);
493 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
495 /* Test if the value is too large to handle sensibly. */
496 gfc_set_model_kind (kind);
497 mpfr_init (huge);
498 n = gfc_validate_kind (BT_INTEGER, kind, false);
499 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
500 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
501 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, arg[0],
502 tmp);
504 mpfr_neg (huge, huge, GFC_RND_MODE);
505 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
506 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, arg[0],
507 tmp);
508 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
509 cond, tmp);
510 itype = gfc_get_int_type (kind);
512 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
513 tmp = convert (type, tmp);
514 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
515 arg[0]);
516 mpfr_clear (huge);
520 /* Convert to an integer using the specified rounding mode. */
522 static void
523 gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
525 tree type;
526 tree *args;
527 int nargs;
529 nargs = gfc_intrinsic_argument_list_length (expr);
530 args = XALLOCAVEC (tree, nargs);
532 /* Evaluate the argument, we process all arguments even though we only
533 use the first one for code generation purposes. */
534 type = gfc_typenode_for_spec (&expr->ts);
535 gcc_assert (expr->value.function.actual->expr);
536 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
538 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
540 /* Conversion to a different integer kind. */
541 se->expr = convert (type, args[0]);
543 else
545 /* Conversion from complex to non-complex involves taking the real
546 component of the value. */
547 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
548 && expr->ts.type != BT_COMPLEX)
550 tree artype;
552 artype = TREE_TYPE (TREE_TYPE (args[0]));
553 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
554 args[0]);
557 se->expr = build_fix_expr (&se->pre, args[0], type, op);
562 /* Get the imaginary component of a value. */
564 static void
565 gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
567 tree arg;
569 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
570 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
571 TREE_TYPE (TREE_TYPE (arg)), arg);
575 /* Get the complex conjugate of a value. */
577 static void
578 gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
580 tree arg;
582 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
583 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
588 static tree
589 define_quad_builtin (const char *name, tree type, bool is_const)
591 tree fndecl;
592 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
593 type);
595 /* Mark the decl as external. */
596 DECL_EXTERNAL (fndecl) = 1;
597 TREE_PUBLIC (fndecl) = 1;
599 /* Mark it __attribute__((const)). */
600 TREE_READONLY (fndecl) = is_const;
602 rest_of_decl_compilation (fndecl, 1, 0);
604 return fndecl;
609 /* Initialize function decls for library functions. The external functions
610 are created as required. Builtin functions are added here. */
612 void
613 gfc_build_intrinsic_lib_fndecls (void)
615 gfc_intrinsic_map_t *m;
616 tree quad_decls[END_BUILTINS + 1];
618 if (gfc_real16_is_float128)
620 /* If we have soft-float types, we create the decls for their
621 C99-like library functions. For now, we only handle __float128
622 q-suffixed functions. */
624 tree tmp, func_1, func_2, func_cabs, func_frexp;
625 tree func_lround, func_llround, func_scalbn, func_cpow;
627 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
629 /* type (*) (type) */
630 tmp = tree_cons (NULL_TREE, float128_type_node, void_list_node);
631 func_1 = build_function_type (float128_type_node, tmp);
632 /* long (*) (type) */
633 func_lround = build_function_type (long_integer_type_node, tmp);
634 /* long long (*) (type) */
635 func_llround = build_function_type (long_long_integer_type_node, tmp);
636 /* type (*) (type, type) */
637 tmp = tree_cons (NULL_TREE, float128_type_node, tmp);
638 func_2 = build_function_type (float128_type_node, tmp);
639 /* type (*) (type, &int) */
640 tmp = tree_cons (NULL_TREE, float128_type_node, void_list_node);
641 tmp = tree_cons (NULL_TREE, build_pointer_type (integer_type_node), tmp);
642 func_frexp = build_function_type (float128_type_node, tmp);
643 /* type (*) (type, int) */
644 tmp = tree_cons (NULL_TREE, float128_type_node, void_list_node);
645 tmp = tree_cons (NULL_TREE, integer_type_node, tmp);
646 func_scalbn = build_function_type (float128_type_node, tmp);
647 /* type (*) (complex type) */
648 tmp = tree_cons (NULL_TREE, complex_float128_type_node, void_list_node);
649 func_cabs = build_function_type (float128_type_node, tmp);
650 /* complex type (*) (complex type, complex type) */
651 tmp = tree_cons (NULL_TREE, complex_float128_type_node, tmp);
652 func_cpow = build_function_type (complex_float128_type_node, tmp);
654 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
655 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
656 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
658 /* Only these built-ins are actually needed here. These are used directly
659 from the code, when calling builtin_decl_for_precision() or
660 builtin_decl_for_float_type(). The others are all constructed by
661 gfc_get_intrinsic_lib_fndecl(). */
662 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
663 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
665 #include "mathbuiltins.def"
667 #undef OTHER_BUILTIN
668 #undef LIB_FUNCTION
669 #undef DEFINE_MATH_BUILTIN
670 #undef DEFINE_MATH_BUILTIN_C
674 /* Add GCC builtin functions. */
675 for (m = gfc_intrinsic_map;
676 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
678 if (m->float_built_in != END_BUILTINS)
679 m->real4_decl = built_in_decls[m->float_built_in];
680 if (m->complex_float_built_in != END_BUILTINS)
681 m->complex4_decl = built_in_decls[m->complex_float_built_in];
682 if (m->double_built_in != END_BUILTINS)
683 m->real8_decl = built_in_decls[m->double_built_in];
684 if (m->complex_double_built_in != END_BUILTINS)
685 m->complex8_decl = built_in_decls[m->complex_double_built_in];
687 /* If real(kind=10) exists, it is always long double. */
688 if (m->long_double_built_in != END_BUILTINS)
689 m->real10_decl = built_in_decls[m->long_double_built_in];
690 if (m->complex_long_double_built_in != END_BUILTINS)
691 m->complex10_decl = built_in_decls[m->complex_long_double_built_in];
693 if (!gfc_real16_is_float128)
695 if (m->long_double_built_in != END_BUILTINS)
696 m->real16_decl = built_in_decls[m->long_double_built_in];
697 if (m->complex_long_double_built_in != END_BUILTINS)
698 m->complex16_decl = built_in_decls[m->complex_long_double_built_in];
700 else if (quad_decls[m->double_built_in] != NULL_TREE)
702 /* Quad-precision function calls are constructed when first
703 needed by builtin_decl_for_precision(), except for those
704 that will be used directly (define by OTHER_BUILTIN). */
705 m->real16_decl = quad_decls[m->double_built_in];
707 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
709 /* Same thing for the complex ones. */
710 m->complex16_decl = quad_decls[m->double_built_in];
716 /* Create a fndecl for a simple intrinsic library function. */
718 static tree
719 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
721 tree type;
722 tree argtypes;
723 tree fndecl;
724 gfc_actual_arglist *actual;
725 tree *pdecl;
726 gfc_typespec *ts;
727 char name[GFC_MAX_SYMBOL_LEN + 3];
729 ts = &expr->ts;
730 if (ts->type == BT_REAL)
732 switch (ts->kind)
734 case 4:
735 pdecl = &m->real4_decl;
736 break;
737 case 8:
738 pdecl = &m->real8_decl;
739 break;
740 case 10:
741 pdecl = &m->real10_decl;
742 break;
743 case 16:
744 pdecl = &m->real16_decl;
745 break;
746 default:
747 gcc_unreachable ();
750 else if (ts->type == BT_COMPLEX)
752 gcc_assert (m->complex_available);
754 switch (ts->kind)
756 case 4:
757 pdecl = &m->complex4_decl;
758 break;
759 case 8:
760 pdecl = &m->complex8_decl;
761 break;
762 case 10:
763 pdecl = &m->complex10_decl;
764 break;
765 case 16:
766 pdecl = &m->complex16_decl;
767 break;
768 default:
769 gcc_unreachable ();
772 else
773 gcc_unreachable ();
775 if (*pdecl)
776 return *pdecl;
778 if (m->libm_name)
780 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
781 if (gfc_real_kinds[n].c_float)
782 snprintf (name, sizeof (name), "%s%s%s",
783 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
784 else if (gfc_real_kinds[n].c_double)
785 snprintf (name, sizeof (name), "%s%s",
786 ts->type == BT_COMPLEX ? "c" : "", m->name);
787 else if (gfc_real_kinds[n].c_long_double)
788 snprintf (name, sizeof (name), "%s%s%s",
789 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
790 else if (gfc_real_kinds[n].c_float128)
791 snprintf (name, sizeof (name), "%s%s%s",
792 ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
793 else
794 gcc_unreachable ();
796 else
798 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
799 ts->type == BT_COMPLEX ? 'c' : 'r',
800 ts->kind);
803 argtypes = NULL_TREE;
804 for (actual = expr->value.function.actual; actual; actual = actual->next)
806 type = gfc_typenode_for_spec (&actual->expr->ts);
807 argtypes = gfc_chainon_list (argtypes, type);
809 argtypes = chainon (argtypes, void_list_node);
810 type = build_function_type (gfc_typenode_for_spec (ts), argtypes);
811 fndecl = build_decl (input_location,
812 FUNCTION_DECL, get_identifier (name), type);
814 /* Mark the decl as external. */
815 DECL_EXTERNAL (fndecl) = 1;
816 TREE_PUBLIC (fndecl) = 1;
818 /* Mark it __attribute__((const)), if possible. */
819 TREE_READONLY (fndecl) = m->is_constant;
821 rest_of_decl_compilation (fndecl, 1, 0);
823 (*pdecl) = fndecl;
824 return fndecl;
828 /* Convert an intrinsic function into an external or builtin call. */
830 static void
831 gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
833 gfc_intrinsic_map_t *m;
834 tree fndecl;
835 tree rettype;
836 tree *args;
837 unsigned int num_args;
838 gfc_isym_id id;
840 id = expr->value.function.isym->id;
841 /* Find the entry for this function. */
842 for (m = gfc_intrinsic_map;
843 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
845 if (id == m->id)
846 break;
849 if (m->id == GFC_ISYM_NONE)
851 internal_error ("Intrinsic function %s(%d) not recognized",
852 expr->value.function.name, id);
855 /* Get the decl and generate the call. */
856 num_args = gfc_intrinsic_argument_list_length (expr);
857 args = XALLOCAVEC (tree, num_args);
859 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
860 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
861 rettype = TREE_TYPE (TREE_TYPE (fndecl));
863 fndecl = build_addr (fndecl, current_function_decl);
864 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
868 /* If bounds-checking is enabled, create code to verify at runtime that the
869 string lengths for both expressions are the same (needed for e.g. MERGE).
870 If bounds-checking is not enabled, does nothing. */
872 void
873 gfc_trans_same_strlen_check (const char* intr_name, locus* where,
874 tree a, tree b, stmtblock_t* target)
876 tree cond;
877 tree name;
879 /* If bounds-checking is disabled, do nothing. */
880 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
881 return;
883 /* Compare the two string lengths. */
884 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, a, b);
886 /* Output the runtime-check. */
887 name = gfc_build_cstring_const (intr_name);
888 name = gfc_build_addr_expr (pchar_type_node, name);
889 gfc_trans_runtime_check (true, false, cond, target, where,
890 "Unequal character lengths (%ld/%ld) in %s",
891 fold_convert (long_integer_type_node, a),
892 fold_convert (long_integer_type_node, b), name);
896 /* The EXPONENT(s) intrinsic function is translated into
897 int ret;
898 frexp (s, &ret);
899 return ret;
902 static void
903 gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
905 tree arg, type, res, tmp, frexp;
907 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
908 expr->value.function.actual->expr->ts.kind);
910 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
912 res = gfc_create_var (integer_type_node, NULL);
913 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
914 gfc_build_addr_expr (NULL_TREE, res));
915 gfc_add_expr_to_block (&se->pre, tmp);
917 type = gfc_typenode_for_spec (&expr->ts);
918 se->expr = fold_convert (type, res);
921 static void
922 trans_this_image (gfc_se * se, gfc_expr *expr ATTRIBUTE_UNUSED)
924 gfc_init_coarray_decl ();
925 se->expr = gfort_gvar_caf_this_image;
928 static void
929 trans_num_images (gfc_se * se)
931 gfc_init_coarray_decl ();
932 se->expr = gfort_gvar_caf_num_images;
935 /* Evaluate a single upper or lower bound. */
936 /* TODO: bound intrinsic generates way too much unnecessary code. */
938 static void
939 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
941 gfc_actual_arglist *arg;
942 gfc_actual_arglist *arg2;
943 tree desc;
944 tree type;
945 tree bound;
946 tree tmp;
947 tree cond, cond1, cond3, cond4, size;
948 tree ubound;
949 tree lbound;
950 gfc_se argse;
951 gfc_ss *ss;
952 gfc_array_spec * as;
954 arg = expr->value.function.actual;
955 arg2 = arg->next;
957 if (se->ss)
959 /* Create an implicit second parameter from the loop variable. */
960 gcc_assert (!arg2->expr);
961 gcc_assert (se->loop->dimen == 1);
962 gcc_assert (se->ss->expr == expr);
963 gfc_advance_se_ss_chain (se);
964 bound = se->loop->loopvar[0];
965 bound = fold_build2_loc (input_location, MINUS_EXPR,
966 gfc_array_index_type, bound,
967 se->loop->from[0]);
969 else
971 /* use the passed argument. */
972 gcc_assert (arg->next->expr);
973 gfc_init_se (&argse, NULL);
974 gfc_conv_expr_type (&argse, arg->next->expr, gfc_array_index_type);
975 gfc_add_block_to_block (&se->pre, &argse.pre);
976 bound = argse.expr;
977 /* Convert from one based to zero based. */
978 bound = fold_build2_loc (input_location, MINUS_EXPR,
979 gfc_array_index_type, bound,
980 gfc_index_one_node);
983 /* TODO: don't re-evaluate the descriptor on each iteration. */
984 /* Get a descriptor for the first parameter. */
985 ss = gfc_walk_expr (arg->expr);
986 gcc_assert (ss != gfc_ss_terminator);
987 gfc_init_se (&argse, NULL);
988 gfc_conv_expr_descriptor (&argse, arg->expr, ss);
989 gfc_add_block_to_block (&se->pre, &argse.pre);
990 gfc_add_block_to_block (&se->post, &argse.post);
992 desc = argse.expr;
994 if (INTEGER_CST_P (bound))
996 int hi, low;
998 hi = TREE_INT_CST_HIGH (bound);
999 low = TREE_INT_CST_LOW (bound);
1000 if (hi || low < 0 || low >= GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)))
1001 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
1002 "dimension index", upper ? "UBOUND" : "LBOUND",
1003 &expr->where);
1005 else
1007 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1009 bound = gfc_evaluate_now (bound, &se->pre);
1010 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1011 bound, build_int_cst (TREE_TYPE (bound), 0));
1012 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
1013 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1014 bound, tmp);
1015 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1016 boolean_type_node, cond, tmp);
1017 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1018 gfc_msg_fault);
1022 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
1023 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
1025 as = gfc_get_full_arrayspec_from_expr (arg->expr);
1027 /* 13.14.53: Result value for LBOUND
1029 Case (i): For an array section or for an array expression other than a
1030 whole array or array structure component, LBOUND(ARRAY, DIM)
1031 has the value 1. For a whole array or array structure
1032 component, LBOUND(ARRAY, DIM) has the value:
1033 (a) equal to the lower bound for subscript DIM of ARRAY if
1034 dimension DIM of ARRAY does not have extent zero
1035 or if ARRAY is an assumed-size array of rank DIM,
1036 or (b) 1 otherwise.
1038 13.14.113: Result value for UBOUND
1040 Case (i): For an array section or for an array expression other than a
1041 whole array or array structure component, UBOUND(ARRAY, DIM)
1042 has the value equal to the number of elements in the given
1043 dimension; otherwise, it has a value equal to the upper bound
1044 for subscript DIM of ARRAY if dimension DIM of ARRAY does
1045 not have size zero and has value zero if dimension DIM has
1046 size zero. */
1048 if (as)
1050 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
1052 cond1 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1053 ubound, lbound);
1054 cond3 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1055 stride, gfc_index_zero_node);
1056 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1057 boolean_type_node, cond3, cond1);
1058 cond4 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1059 stride, gfc_index_zero_node);
1061 if (upper)
1063 tree cond5;
1064 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1065 boolean_type_node, cond3, cond4);
1066 cond5 = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1067 gfc_index_one_node, lbound);
1068 cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1069 boolean_type_node, cond4, cond5);
1071 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1072 boolean_type_node, cond, cond5);
1074 se->expr = fold_build3_loc (input_location, COND_EXPR,
1075 gfc_array_index_type, cond,
1076 ubound, gfc_index_zero_node);
1078 else
1080 if (as->type == AS_ASSUMED_SIZE)
1081 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1082 bound, build_int_cst (TREE_TYPE (bound),
1083 arg->expr->rank - 1));
1084 else
1085 cond = boolean_false_node;
1087 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1088 boolean_type_node, cond3, cond4);
1089 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1090 boolean_type_node, cond, cond1);
1092 se->expr = fold_build3_loc (input_location, COND_EXPR,
1093 gfc_array_index_type, cond,
1094 lbound, gfc_index_one_node);
1097 else
1099 if (upper)
1101 size = fold_build2_loc (input_location, MINUS_EXPR,
1102 gfc_array_index_type, ubound, lbound);
1103 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
1104 gfc_array_index_type, size,
1105 gfc_index_one_node);
1106 se->expr = fold_build2_loc (input_location, MAX_EXPR,
1107 gfc_array_index_type, se->expr,
1108 gfc_index_zero_node);
1110 else
1111 se->expr = gfc_index_one_node;
1114 type = gfc_typenode_for_spec (&expr->ts);
1115 se->expr = convert (type, se->expr);
1119 static void
1120 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
1122 tree arg, cabs;
1124 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
1126 switch (expr->value.function.actual->expr->ts.type)
1128 case BT_INTEGER:
1129 case BT_REAL:
1130 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
1131 arg);
1132 break;
1134 case BT_COMPLEX:
1135 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
1136 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
1137 break;
1139 default:
1140 gcc_unreachable ();
1145 /* Create a complex value from one or two real components. */
1147 static void
1148 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
1150 tree real;
1151 tree imag;
1152 tree type;
1153 tree *args;
1154 unsigned int num_args;
1156 num_args = gfc_intrinsic_argument_list_length (expr);
1157 args = XALLOCAVEC (tree, num_args);
1159 type = gfc_typenode_for_spec (&expr->ts);
1160 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
1161 real = convert (TREE_TYPE (type), args[0]);
1162 if (both)
1163 imag = convert (TREE_TYPE (type), args[1]);
1164 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
1166 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
1167 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
1168 imag = convert (TREE_TYPE (type), imag);
1170 else
1171 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
1173 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
1176 /* Remainder function MOD(A, P) = A - INT(A / P) * P
1177 MODULO(A, P) = A - FLOOR (A / P) * P */
1178 /* TODO: MOD(x, 0) */
1180 static void
1181 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
1183 tree type;
1184 tree itype;
1185 tree tmp;
1186 tree test;
1187 tree test2;
1188 tree fmod;
1189 mpfr_t huge;
1190 int n, ikind;
1191 tree args[2];
1193 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1195 switch (expr->ts.type)
1197 case BT_INTEGER:
1198 /* Integer case is easy, we've got a builtin op. */
1199 type = TREE_TYPE (args[0]);
1201 if (modulo)
1202 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
1203 args[0], args[1]);
1204 else
1205 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
1206 args[0], args[1]);
1207 break;
1209 case BT_REAL:
1210 fmod = NULL_TREE;
1211 /* Check if we have a builtin fmod. */
1212 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
1214 /* Use it if it exists. */
1215 if (fmod != NULL_TREE)
1217 tmp = build_addr (fmod, current_function_decl);
1218 se->expr = build_call_array_loc (input_location,
1219 TREE_TYPE (TREE_TYPE (fmod)),
1220 tmp, 2, args);
1221 if (modulo == 0)
1222 return;
1225 type = TREE_TYPE (args[0]);
1227 args[0] = gfc_evaluate_now (args[0], &se->pre);
1228 args[1] = gfc_evaluate_now (args[1], &se->pre);
1230 /* Definition:
1231 modulo = arg - floor (arg/arg2) * arg2, so
1232 = test ? fmod (arg, arg2) : fmod (arg, arg2) + arg2,
1233 where
1234 test = (fmod (arg, arg2) != 0) && ((arg < 0) xor (arg2 < 0))
1235 thereby avoiding another division and retaining the accuracy
1236 of the builtin function. */
1237 if (fmod != NULL_TREE && modulo)
1239 tree zero = gfc_build_const (type, integer_zero_node);
1240 tmp = gfc_evaluate_now (se->expr, &se->pre);
1241 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1242 args[0], zero);
1243 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1244 args[1], zero);
1245 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
1246 boolean_type_node, test, test2);
1247 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1248 tmp, zero);
1249 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1250 boolean_type_node, test, test2);
1251 test = gfc_evaluate_now (test, &se->pre);
1252 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
1253 fold_build2_loc (input_location, PLUS_EXPR,
1254 type, tmp, args[1]), tmp);
1255 return;
1258 /* If we do not have a built_in fmod, the calculation is going to
1259 have to be done longhand. */
1260 tmp = fold_build2_loc (input_location, RDIV_EXPR, type, args[0], args[1]);
1262 /* Test if the value is too large to handle sensibly. */
1263 gfc_set_model_kind (expr->ts.kind);
1264 mpfr_init (huge);
1265 n = gfc_validate_kind (BT_INTEGER, expr->ts.kind, true);
1266 ikind = expr->ts.kind;
1267 if (n < 0)
1269 n = gfc_validate_kind (BT_INTEGER, gfc_max_integer_kind, false);
1270 ikind = gfc_max_integer_kind;
1272 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
1273 test = gfc_conv_mpfr_to_tree (huge, expr->ts.kind, 0);
1274 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1275 tmp, test);
1277 mpfr_neg (huge, huge, GFC_RND_MODE);
1278 test = gfc_conv_mpfr_to_tree (huge, expr->ts.kind, 0);
1279 test = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, tmp,
1280 test);
1281 test2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1282 boolean_type_node, test, test2);
1284 itype = gfc_get_int_type (ikind);
1285 if (modulo)
1286 tmp = build_fix_expr (&se->pre, tmp, itype, RND_FLOOR);
1287 else
1288 tmp = build_fix_expr (&se->pre, tmp, itype, RND_TRUNC);
1289 tmp = convert (type, tmp);
1290 tmp = fold_build3_loc (input_location, COND_EXPR, type, test2, tmp,
1291 args[0]);
1292 tmp = fold_build2_loc (input_location, MULT_EXPR, type, tmp, args[1]);
1293 se->expr = fold_build2_loc (input_location, MINUS_EXPR, type, args[0],
1294 tmp);
1295 mpfr_clear (huge);
1296 break;
1298 default:
1299 gcc_unreachable ();
1303 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
1304 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
1305 where the right shifts are logical (i.e. 0's are shifted in).
1306 Because SHIFT_EXPR's want shifts strictly smaller than the integral
1307 type width, we have to special-case both S == 0 and S == BITSIZE(J):
1308 DSHIFTL(I,J,0) = I
1309 DSHIFTL(I,J,BITSIZE) = J
1310 DSHIFTR(I,J,0) = J
1311 DSHIFTR(I,J,BITSIZE) = I. */
1313 static void
1314 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
1316 tree type, utype, stype, arg1, arg2, shift, res, left, right;
1317 tree args[3], cond, tmp;
1318 int bitsize;
1320 gfc_conv_intrinsic_function_args (se, expr, args, 3);
1322 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
1323 type = TREE_TYPE (args[0]);
1324 bitsize = TYPE_PRECISION (type);
1325 utype = unsigned_type_for (type);
1326 stype = TREE_TYPE (args[2]);
1328 arg1 = gfc_evaluate_now (args[0], &se->pre);
1329 arg2 = gfc_evaluate_now (args[1], &se->pre);
1330 shift = gfc_evaluate_now (args[2], &se->pre);
1332 /* The generic case. */
1333 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
1334 build_int_cst (stype, bitsize), shift);
1335 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
1336 arg1, dshiftl ? shift : tmp);
1338 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
1339 fold_convert (utype, arg2), dshiftl ? tmp : shift);
1340 right = fold_convert (type, right);
1342 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
1344 /* Special cases. */
1345 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
1346 build_int_cst (stype, 0));
1347 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
1348 dshiftl ? arg1 : arg2, res);
1350 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
1351 build_int_cst (stype, bitsize));
1352 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
1353 dshiftl ? arg2 : arg1, res);
1355 se->expr = res;
1359 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
1361 static void
1362 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
1364 tree val;
1365 tree tmp;
1366 tree type;
1367 tree zero;
1368 tree args[2];
1370 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1371 type = TREE_TYPE (args[0]);
1373 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
1374 val = gfc_evaluate_now (val, &se->pre);
1376 zero = gfc_build_const (type, integer_zero_node);
1377 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, val, zero);
1378 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
1382 /* SIGN(A, B) is absolute value of A times sign of B.
1383 The real value versions use library functions to ensure the correct
1384 handling of negative zero. Integer case implemented as:
1385 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
1388 static void
1389 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
1391 tree tmp;
1392 tree type;
1393 tree args[2];
1395 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1396 if (expr->ts.type == BT_REAL)
1398 tree abs;
1400 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
1401 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
1403 /* We explicitly have to ignore the minus sign. We do so by using
1404 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
1405 if (!gfc_option.flag_sign_zero
1406 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
1408 tree cond, zero;
1409 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
1410 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1411 args[1], zero);
1412 se->expr = fold_build3_loc (input_location, COND_EXPR,
1413 TREE_TYPE (args[0]), cond,
1414 build_call_expr_loc (input_location, abs, 1,
1415 args[0]),
1416 build_call_expr_loc (input_location, tmp, 2,
1417 args[0], args[1]));
1419 else
1420 se->expr = build_call_expr_loc (input_location, tmp, 2,
1421 args[0], args[1]);
1422 return;
1425 /* Having excluded floating point types, we know we are now dealing
1426 with signed integer types. */
1427 type = TREE_TYPE (args[0]);
1429 /* Args[0] is used multiple times below. */
1430 args[0] = gfc_evaluate_now (args[0], &se->pre);
1432 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
1433 the signs of A and B are the same, and of all ones if they differ. */
1434 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
1435 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
1436 build_int_cst (type, TYPE_PRECISION (type) - 1));
1437 tmp = gfc_evaluate_now (tmp, &se->pre);
1439 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
1440 is all ones (i.e. -1). */
1441 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
1442 fold_build2_loc (input_location, PLUS_EXPR,
1443 type, args[0], tmp), tmp);
1447 /* Test for the presence of an optional argument. */
1449 static void
1450 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
1452 gfc_expr *arg;
1454 arg = expr->value.function.actual->expr;
1455 gcc_assert (arg->expr_type == EXPR_VARIABLE);
1456 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
1457 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
1461 /* Calculate the double precision product of two single precision values. */
1463 static void
1464 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
1466 tree type;
1467 tree args[2];
1469 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1471 /* Convert the args to double precision before multiplying. */
1472 type = gfc_typenode_for_spec (&expr->ts);
1473 args[0] = convert (type, args[0]);
1474 args[1] = convert (type, args[1]);
1475 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
1476 args[1]);
1480 /* Return a length one character string containing an ascii character. */
1482 static void
1483 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
1485 tree arg[2];
1486 tree var;
1487 tree type;
1488 unsigned int num_args;
1490 num_args = gfc_intrinsic_argument_list_length (expr);
1491 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
1493 type = gfc_get_char_type (expr->ts.kind);
1494 var = gfc_create_var (type, "char");
1496 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
1497 gfc_add_modify (&se->pre, var, arg[0]);
1498 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
1499 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
1503 static void
1504 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
1506 tree var;
1507 tree len;
1508 tree tmp;
1509 tree cond;
1510 tree fndecl;
1511 tree *args;
1512 unsigned int num_args;
1514 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1515 args = XALLOCAVEC (tree, num_args);
1517 var = gfc_create_var (pchar_type_node, "pstr");
1518 len = gfc_create_var (gfc_charlen_type_node, "len");
1520 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
1521 args[0] = gfc_build_addr_expr (NULL_TREE, var);
1522 args[1] = gfc_build_addr_expr (NULL_TREE, len);
1524 fndecl = build_addr (gfor_fndecl_ctime, current_function_decl);
1525 tmp = build_call_array_loc (input_location,
1526 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
1527 fndecl, num_args, args);
1528 gfc_add_expr_to_block (&se->pre, tmp);
1530 /* Free the temporary afterwards, if necessary. */
1531 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1532 len, build_int_cst (TREE_TYPE (len), 0));
1533 tmp = gfc_call_free (var);
1534 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
1535 gfc_add_expr_to_block (&se->post, tmp);
1537 se->expr = var;
1538 se->string_length = len;
1542 static void
1543 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
1545 tree var;
1546 tree len;
1547 tree tmp;
1548 tree cond;
1549 tree fndecl;
1550 tree *args;
1551 unsigned int num_args;
1553 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1554 args = XALLOCAVEC (tree, num_args);
1556 var = gfc_create_var (pchar_type_node, "pstr");
1557 len = gfc_create_var (gfc_charlen_type_node, "len");
1559 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
1560 args[0] = gfc_build_addr_expr (NULL_TREE, var);
1561 args[1] = gfc_build_addr_expr (NULL_TREE, len);
1563 fndecl = build_addr (gfor_fndecl_fdate, current_function_decl);
1564 tmp = build_call_array_loc (input_location,
1565 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
1566 fndecl, num_args, args);
1567 gfc_add_expr_to_block (&se->pre, tmp);
1569 /* Free the temporary afterwards, if necessary. */
1570 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1571 len, build_int_cst (TREE_TYPE (len), 0));
1572 tmp = gfc_call_free (var);
1573 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
1574 gfc_add_expr_to_block (&se->post, tmp);
1576 se->expr = var;
1577 se->string_length = len;
1581 /* Return a character string containing the tty name. */
1583 static void
1584 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
1586 tree var;
1587 tree len;
1588 tree tmp;
1589 tree cond;
1590 tree fndecl;
1591 tree *args;
1592 unsigned int num_args;
1594 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1595 args = XALLOCAVEC (tree, num_args);
1597 var = gfc_create_var (pchar_type_node, "pstr");
1598 len = gfc_create_var (gfc_charlen_type_node, "len");
1600 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
1601 args[0] = gfc_build_addr_expr (NULL_TREE, var);
1602 args[1] = gfc_build_addr_expr (NULL_TREE, len);
1604 fndecl = build_addr (gfor_fndecl_ttynam, current_function_decl);
1605 tmp = build_call_array_loc (input_location,
1606 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
1607 fndecl, num_args, args);
1608 gfc_add_expr_to_block (&se->pre, tmp);
1610 /* Free the temporary afterwards, if necessary. */
1611 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1612 len, build_int_cst (TREE_TYPE (len), 0));
1613 tmp = gfc_call_free (var);
1614 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
1615 gfc_add_expr_to_block (&se->post, tmp);
1617 se->expr = var;
1618 se->string_length = len;
1622 /* Get the minimum/maximum value of all the parameters.
1623 minmax (a1, a2, a3, ...)
1625 mvar = a1;
1626 if (a2 .op. mvar || isnan(mvar))
1627 mvar = a2;
1628 if (a3 .op. mvar || isnan(mvar))
1629 mvar = a3;
1631 return mvar
1635 /* TODO: Mismatching types can occur when specific names are used.
1636 These should be handled during resolution. */
1637 static void
1638 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
1640 tree tmp;
1641 tree mvar;
1642 tree val;
1643 tree thencase;
1644 tree *args;
1645 tree type;
1646 gfc_actual_arglist *argexpr;
1647 unsigned int i, nargs;
1649 nargs = gfc_intrinsic_argument_list_length (expr);
1650 args = XALLOCAVEC (tree, nargs);
1652 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
1653 type = gfc_typenode_for_spec (&expr->ts);
1655 argexpr = expr->value.function.actual;
1656 if (TREE_TYPE (args[0]) != type)
1657 args[0] = convert (type, args[0]);
1658 /* Only evaluate the argument once. */
1659 if (TREE_CODE (args[0]) != VAR_DECL && !TREE_CONSTANT (args[0]))
1660 args[0] = gfc_evaluate_now (args[0], &se->pre);
1662 mvar = gfc_create_var (type, "M");
1663 gfc_add_modify (&se->pre, mvar, args[0]);
1664 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
1666 tree cond, isnan;
1668 val = args[i];
1670 /* Handle absent optional arguments by ignoring the comparison. */
1671 if (argexpr->expr->expr_type == EXPR_VARIABLE
1672 && argexpr->expr->symtree->n.sym->attr.optional
1673 && TREE_CODE (val) == INDIRECT_REF)
1674 cond = fold_build2_loc (input_location,
1675 NE_EXPR, boolean_type_node,
1676 TREE_OPERAND (val, 0),
1677 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
1678 else
1680 cond = NULL_TREE;
1682 /* Only evaluate the argument once. */
1683 if (TREE_CODE (val) != VAR_DECL && !TREE_CONSTANT (val))
1684 val = gfc_evaluate_now (val, &se->pre);
1687 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
1689 tmp = fold_build2_loc (input_location, op, boolean_type_node,
1690 convert (type, val), mvar);
1692 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
1693 __builtin_isnan might be made dependent on that module being loaded,
1694 to help performance of programs that don't rely on IEEE semantics. */
1695 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
1697 isnan = build_call_expr_loc (input_location,
1698 built_in_decls[BUILT_IN_ISNAN], 1, mvar);
1699 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1700 boolean_type_node, tmp,
1701 fold_convert (boolean_type_node, isnan));
1703 tmp = build3_v (COND_EXPR, tmp, thencase,
1704 build_empty_stmt (input_location));
1706 if (cond != NULL_TREE)
1707 tmp = build3_v (COND_EXPR, cond, tmp,
1708 build_empty_stmt (input_location));
1710 gfc_add_expr_to_block (&se->pre, tmp);
1711 argexpr = argexpr->next;
1713 se->expr = mvar;
1717 /* Generate library calls for MIN and MAX intrinsics for character
1718 variables. */
1719 static void
1720 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
1722 tree *args;
1723 tree var, len, fndecl, tmp, cond, function;
1724 unsigned int nargs;
1726 nargs = gfc_intrinsic_argument_list_length (expr);
1727 args = XALLOCAVEC (tree, nargs + 4);
1728 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
1730 /* Create the result variables. */
1731 len = gfc_create_var (gfc_charlen_type_node, "len");
1732 args[0] = gfc_build_addr_expr (NULL_TREE, len);
1733 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
1734 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
1735 args[2] = build_int_cst (NULL_TREE, op);
1736 args[3] = build_int_cst (NULL_TREE, nargs / 2);
1738 if (expr->ts.kind == 1)
1739 function = gfor_fndecl_string_minmax;
1740 else if (expr->ts.kind == 4)
1741 function = gfor_fndecl_string_minmax_char4;
1742 else
1743 gcc_unreachable ();
1745 /* Make the function call. */
1746 fndecl = build_addr (function, current_function_decl);
1747 tmp = build_call_array_loc (input_location,
1748 TREE_TYPE (TREE_TYPE (function)), fndecl,
1749 nargs + 4, args);
1750 gfc_add_expr_to_block (&se->pre, tmp);
1752 /* Free the temporary afterwards, if necessary. */
1753 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1754 len, build_int_cst (TREE_TYPE (len), 0));
1755 tmp = gfc_call_free (var);
1756 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
1757 gfc_add_expr_to_block (&se->post, tmp);
1759 se->expr = var;
1760 se->string_length = len;
1764 /* Create a symbol node for this intrinsic. The symbol from the frontend
1765 has the generic name. */
1767 static gfc_symbol *
1768 gfc_get_symbol_for_expr (gfc_expr * expr)
1770 gfc_symbol *sym;
1772 /* TODO: Add symbols for intrinsic function to the global namespace. */
1773 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
1774 sym = gfc_new_symbol (expr->value.function.name, NULL);
1776 sym->ts = expr->ts;
1777 sym->attr.external = 1;
1778 sym->attr.function = 1;
1779 sym->attr.always_explicit = 1;
1780 sym->attr.proc = PROC_INTRINSIC;
1781 sym->attr.flavor = FL_PROCEDURE;
1782 sym->result = sym;
1783 if (expr->rank > 0)
1785 sym->attr.dimension = 1;
1786 sym->as = gfc_get_array_spec ();
1787 sym->as->type = AS_ASSUMED_SHAPE;
1788 sym->as->rank = expr->rank;
1791 gfc_copy_formal_args_intr (sym, expr->value.function.isym);
1793 return sym;
1796 /* Generate a call to an external intrinsic function. */
1797 static void
1798 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
1800 gfc_symbol *sym;
1801 VEC(tree,gc) *append_args;
1803 gcc_assert (!se->ss || se->ss->expr == expr);
1805 if (se->ss)
1806 gcc_assert (expr->rank > 0);
1807 else
1808 gcc_assert (expr->rank == 0);
1810 sym = gfc_get_symbol_for_expr (expr);
1812 /* Calls to libgfortran_matmul need to be appended special arguments,
1813 to be able to call the BLAS ?gemm functions if required and possible. */
1814 append_args = NULL;
1815 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
1816 && sym->ts.type != BT_LOGICAL)
1818 tree cint = gfc_get_int_type (gfc_c_int_kind);
1820 if (gfc_option.flag_external_blas
1821 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
1822 && (sym->ts.kind == gfc_default_real_kind
1823 || sym->ts.kind == gfc_default_double_kind))
1825 tree gemm_fndecl;
1827 if (sym->ts.type == BT_REAL)
1829 if (sym->ts.kind == gfc_default_real_kind)
1830 gemm_fndecl = gfor_fndecl_sgemm;
1831 else
1832 gemm_fndecl = gfor_fndecl_dgemm;
1834 else
1836 if (sym->ts.kind == gfc_default_real_kind)
1837 gemm_fndecl = gfor_fndecl_cgemm;
1838 else
1839 gemm_fndecl = gfor_fndecl_zgemm;
1842 append_args = VEC_alloc (tree, gc, 3);
1843 VEC_quick_push (tree, append_args, build_int_cst (cint, 1));
1844 VEC_quick_push (tree, append_args,
1845 build_int_cst (cint, gfc_option.blas_matmul_limit));
1846 VEC_quick_push (tree, append_args,
1847 gfc_build_addr_expr (NULL_TREE, gemm_fndecl));
1849 else
1851 append_args = VEC_alloc (tree, gc, 3);
1852 VEC_quick_push (tree, append_args, build_int_cst (cint, 0));
1853 VEC_quick_push (tree, append_args, build_int_cst (cint, 0));
1854 VEC_quick_push (tree, append_args, null_pointer_node);
1858 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
1859 append_args);
1860 gfc_free_symbol (sym);
1863 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
1864 Implemented as
1865 any(a)
1867 forall (i=...)
1868 if (a[i] != 0)
1869 return 1
1870 end forall
1871 return 0
1873 all(a)
1875 forall (i=...)
1876 if (a[i] == 0)
1877 return 0
1878 end forall
1879 return 1
1882 static void
1883 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
1885 tree resvar;
1886 stmtblock_t block;
1887 stmtblock_t body;
1888 tree type;
1889 tree tmp;
1890 tree found;
1891 gfc_loopinfo loop;
1892 gfc_actual_arglist *actual;
1893 gfc_ss *arrayss;
1894 gfc_se arrayse;
1895 tree exit_label;
1897 if (se->ss)
1899 gfc_conv_intrinsic_funcall (se, expr);
1900 return;
1903 actual = expr->value.function.actual;
1904 type = gfc_typenode_for_spec (&expr->ts);
1905 /* Initialize the result. */
1906 resvar = gfc_create_var (type, "test");
1907 if (op == EQ_EXPR)
1908 tmp = convert (type, boolean_true_node);
1909 else
1910 tmp = convert (type, boolean_false_node);
1911 gfc_add_modify (&se->pre, resvar, tmp);
1913 /* Walk the arguments. */
1914 arrayss = gfc_walk_expr (actual->expr);
1915 gcc_assert (arrayss != gfc_ss_terminator);
1917 /* Initialize the scalarizer. */
1918 gfc_init_loopinfo (&loop);
1919 exit_label = gfc_build_label_decl (NULL_TREE);
1920 TREE_USED (exit_label) = 1;
1921 gfc_add_ss_to_loop (&loop, arrayss);
1923 /* Initialize the loop. */
1924 gfc_conv_ss_startstride (&loop);
1925 gfc_conv_loop_setup (&loop, &expr->where);
1927 gfc_mark_ss_chain_used (arrayss, 1);
1928 /* Generate the loop body. */
1929 gfc_start_scalarized_body (&loop, &body);
1931 /* If the condition matches then set the return value. */
1932 gfc_start_block (&block);
1933 if (op == EQ_EXPR)
1934 tmp = convert (type, boolean_false_node);
1935 else
1936 tmp = convert (type, boolean_true_node);
1937 gfc_add_modify (&block, resvar, tmp);
1939 /* And break out of the loop. */
1940 tmp = build1_v (GOTO_EXPR, exit_label);
1941 gfc_add_expr_to_block (&block, tmp);
1943 found = gfc_finish_block (&block);
1945 /* Check this element. */
1946 gfc_init_se (&arrayse, NULL);
1947 gfc_copy_loopinfo_to_se (&arrayse, &loop);
1948 arrayse.ss = arrayss;
1949 gfc_conv_expr_val (&arrayse, actual->expr);
1951 gfc_add_block_to_block (&body, &arrayse.pre);
1952 tmp = fold_build2_loc (input_location, op, boolean_type_node, arrayse.expr,
1953 build_int_cst (TREE_TYPE (arrayse.expr), 0));
1954 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
1955 gfc_add_expr_to_block (&body, tmp);
1956 gfc_add_block_to_block (&body, &arrayse.post);
1958 gfc_trans_scalarizing_loops (&loop, &body);
1960 /* Add the exit label. */
1961 tmp = build1_v (LABEL_EXPR, exit_label);
1962 gfc_add_expr_to_block (&loop.pre, tmp);
1964 gfc_add_block_to_block (&se->pre, &loop.pre);
1965 gfc_add_block_to_block (&se->pre, &loop.post);
1966 gfc_cleanup_loop (&loop);
1968 se->expr = resvar;
1971 /* COUNT(A) = Number of true elements in A. */
1972 static void
1973 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
1975 tree resvar;
1976 tree type;
1977 stmtblock_t body;
1978 tree tmp;
1979 gfc_loopinfo loop;
1980 gfc_actual_arglist *actual;
1981 gfc_ss *arrayss;
1982 gfc_se arrayse;
1984 if (se->ss)
1986 gfc_conv_intrinsic_funcall (se, expr);
1987 return;
1990 actual = expr->value.function.actual;
1992 type = gfc_typenode_for_spec (&expr->ts);
1993 /* Initialize the result. */
1994 resvar = gfc_create_var (type, "count");
1995 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
1997 /* Walk the arguments. */
1998 arrayss = gfc_walk_expr (actual->expr);
1999 gcc_assert (arrayss != gfc_ss_terminator);
2001 /* Initialize the scalarizer. */
2002 gfc_init_loopinfo (&loop);
2003 gfc_add_ss_to_loop (&loop, arrayss);
2005 /* Initialize the loop. */
2006 gfc_conv_ss_startstride (&loop);
2007 gfc_conv_loop_setup (&loop, &expr->where);
2009 gfc_mark_ss_chain_used (arrayss, 1);
2010 /* Generate the loop body. */
2011 gfc_start_scalarized_body (&loop, &body);
2013 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
2014 resvar, build_int_cst (TREE_TYPE (resvar), 1));
2015 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
2017 gfc_init_se (&arrayse, NULL);
2018 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2019 arrayse.ss = arrayss;
2020 gfc_conv_expr_val (&arrayse, actual->expr);
2021 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
2022 build_empty_stmt (input_location));
2024 gfc_add_block_to_block (&body, &arrayse.pre);
2025 gfc_add_expr_to_block (&body, tmp);
2026 gfc_add_block_to_block (&body, &arrayse.post);
2028 gfc_trans_scalarizing_loops (&loop, &body);
2030 gfc_add_block_to_block (&se->pre, &loop.pre);
2031 gfc_add_block_to_block (&se->pre, &loop.post);
2032 gfc_cleanup_loop (&loop);
2034 se->expr = resvar;
2037 /* Inline implementation of the sum and product intrinsics. */
2038 static void
2039 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
2040 bool norm2)
2042 tree resvar;
2043 tree scale = NULL_TREE;
2044 tree type;
2045 stmtblock_t body;
2046 stmtblock_t block;
2047 tree tmp;
2048 gfc_loopinfo loop;
2049 gfc_actual_arglist *actual;
2050 gfc_ss *arrayss;
2051 gfc_ss *maskss;
2052 gfc_se arrayse;
2053 gfc_se maskse;
2054 gfc_expr *arrayexpr;
2055 gfc_expr *maskexpr;
2057 if (se->ss)
2059 gfc_conv_intrinsic_funcall (se, expr);
2060 return;
2063 type = gfc_typenode_for_spec (&expr->ts);
2064 /* Initialize the result. */
2065 resvar = gfc_create_var (type, "val");
2066 if (norm2)
2068 /* result = 0.0;
2069 scale = 1.0. */
2070 scale = gfc_create_var (type, "scale");
2071 gfc_add_modify (&se->pre, scale,
2072 gfc_build_const (type, integer_one_node));
2073 tmp = gfc_build_const (type, integer_zero_node);
2075 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
2076 tmp = gfc_build_const (type, integer_zero_node);
2077 else if (op == NE_EXPR)
2078 /* PARITY. */
2079 tmp = convert (type, boolean_false_node);
2080 else if (op == BIT_AND_EXPR)
2081 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
2082 type, integer_one_node));
2083 else
2084 tmp = gfc_build_const (type, integer_one_node);
2086 gfc_add_modify (&se->pre, resvar, tmp);
2088 /* Walk the arguments. */
2089 actual = expr->value.function.actual;
2090 arrayexpr = actual->expr;
2091 arrayss = gfc_walk_expr (arrayexpr);
2092 gcc_assert (arrayss != gfc_ss_terminator);
2094 if (op == NE_EXPR || norm2)
2095 /* PARITY and NORM2. */
2096 maskexpr = NULL;
2097 else
2099 actual = actual->next->next;
2100 gcc_assert (actual);
2101 maskexpr = actual->expr;
2104 if (maskexpr && maskexpr->rank != 0)
2106 maskss = gfc_walk_expr (maskexpr);
2107 gcc_assert (maskss != gfc_ss_terminator);
2109 else
2110 maskss = NULL;
2112 /* Initialize the scalarizer. */
2113 gfc_init_loopinfo (&loop);
2114 gfc_add_ss_to_loop (&loop, arrayss);
2115 if (maskss)
2116 gfc_add_ss_to_loop (&loop, maskss);
2118 /* Initialize the loop. */
2119 gfc_conv_ss_startstride (&loop);
2120 gfc_conv_loop_setup (&loop, &expr->where);
2122 gfc_mark_ss_chain_used (arrayss, 1);
2123 if (maskss)
2124 gfc_mark_ss_chain_used (maskss, 1);
2125 /* Generate the loop body. */
2126 gfc_start_scalarized_body (&loop, &body);
2128 /* If we have a mask, only add this element if the mask is set. */
2129 if (maskss)
2131 gfc_init_se (&maskse, NULL);
2132 gfc_copy_loopinfo_to_se (&maskse, &loop);
2133 maskse.ss = maskss;
2134 gfc_conv_expr_val (&maskse, maskexpr);
2135 gfc_add_block_to_block (&body, &maskse.pre);
2137 gfc_start_block (&block);
2139 else
2140 gfc_init_block (&block);
2142 /* Do the actual summation/product. */
2143 gfc_init_se (&arrayse, NULL);
2144 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2145 arrayse.ss = arrayss;
2146 gfc_conv_expr_val (&arrayse, arrayexpr);
2147 gfc_add_block_to_block (&block, &arrayse.pre);
2149 if (norm2)
2151 /* if (x(i) != 0.0)
2153 absX = abs(x(i))
2154 if (absX > scale)
2156 val = scale/absX;
2157 result = 1.0 + result * val * val;
2158 scale = absX;
2160 else
2162 val = absX/scale;
2163 result += val * val;
2165 } */
2166 tree res1, res2, cond, absX, val;
2167 stmtblock_t ifblock1, ifblock2, ifblock3;
2169 gfc_init_block (&ifblock1);
2171 absX = gfc_create_var (type, "absX");
2172 gfc_add_modify (&ifblock1, absX,
2173 fold_build1_loc (input_location, ABS_EXPR, type,
2174 arrayse.expr));
2175 val = gfc_create_var (type, "val");
2176 gfc_add_expr_to_block (&ifblock1, val);
2178 gfc_init_block (&ifblock2);
2179 gfc_add_modify (&ifblock2, val,
2180 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
2181 absX));
2182 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
2183 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
2184 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
2185 gfc_build_const (type, integer_one_node));
2186 gfc_add_modify (&ifblock2, resvar, res1);
2187 gfc_add_modify (&ifblock2, scale, absX);
2188 res1 = gfc_finish_block (&ifblock2);
2190 gfc_init_block (&ifblock3);
2191 gfc_add_modify (&ifblock3, val,
2192 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
2193 scale));
2194 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
2195 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
2196 gfc_add_modify (&ifblock3, resvar, res2);
2197 res2 = gfc_finish_block (&ifblock3);
2199 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2200 absX, scale);
2201 tmp = build3_v (COND_EXPR, cond, res1, res2);
2202 gfc_add_expr_to_block (&ifblock1, tmp);
2203 tmp = gfc_finish_block (&ifblock1);
2205 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
2206 arrayse.expr,
2207 gfc_build_const (type, integer_zero_node));
2209 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2210 gfc_add_expr_to_block (&block, tmp);
2212 else
2214 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
2215 gfc_add_modify (&block, resvar, tmp);
2218 gfc_add_block_to_block (&block, &arrayse.post);
2220 if (maskss)
2222 /* We enclose the above in if (mask) {...} . */
2224 tmp = gfc_finish_block (&block);
2225 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2226 build_empty_stmt (input_location));
2228 else
2229 tmp = gfc_finish_block (&block);
2230 gfc_add_expr_to_block (&body, tmp);
2232 gfc_trans_scalarizing_loops (&loop, &body);
2234 /* For a scalar mask, enclose the loop in an if statement. */
2235 if (maskexpr && maskss == NULL)
2237 gfc_init_se (&maskse, NULL);
2238 gfc_conv_expr_val (&maskse, maskexpr);
2239 gfc_init_block (&block);
2240 gfc_add_block_to_block (&block, &loop.pre);
2241 gfc_add_block_to_block (&block, &loop.post);
2242 tmp = gfc_finish_block (&block);
2244 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2245 build_empty_stmt (input_location));
2246 gfc_add_expr_to_block (&block, tmp);
2247 gfc_add_block_to_block (&se->pre, &block);
2249 else
2251 gfc_add_block_to_block (&se->pre, &loop.pre);
2252 gfc_add_block_to_block (&se->pre, &loop.post);
2255 gfc_cleanup_loop (&loop);
2257 if (norm2)
2259 /* result = scale * sqrt(result). */
2260 tree sqrt;
2261 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
2262 resvar = build_call_expr_loc (input_location,
2263 sqrt, 1, resvar);
2264 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
2267 se->expr = resvar;
2271 /* Inline implementation of the dot_product intrinsic. This function
2272 is based on gfc_conv_intrinsic_arith (the previous function). */
2273 static void
2274 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
2276 tree resvar;
2277 tree type;
2278 stmtblock_t body;
2279 stmtblock_t block;
2280 tree tmp;
2281 gfc_loopinfo loop;
2282 gfc_actual_arglist *actual;
2283 gfc_ss *arrayss1, *arrayss2;
2284 gfc_se arrayse1, arrayse2;
2285 gfc_expr *arrayexpr1, *arrayexpr2;
2287 type = gfc_typenode_for_spec (&expr->ts);
2289 /* Initialize the result. */
2290 resvar = gfc_create_var (type, "val");
2291 if (expr->ts.type == BT_LOGICAL)
2292 tmp = build_int_cst (type, 0);
2293 else
2294 tmp = gfc_build_const (type, integer_zero_node);
2296 gfc_add_modify (&se->pre, resvar, tmp);
2298 /* Walk argument #1. */
2299 actual = expr->value.function.actual;
2300 arrayexpr1 = actual->expr;
2301 arrayss1 = gfc_walk_expr (arrayexpr1);
2302 gcc_assert (arrayss1 != gfc_ss_terminator);
2304 /* Walk argument #2. */
2305 actual = actual->next;
2306 arrayexpr2 = actual->expr;
2307 arrayss2 = gfc_walk_expr (arrayexpr2);
2308 gcc_assert (arrayss2 != gfc_ss_terminator);
2310 /* Initialize the scalarizer. */
2311 gfc_init_loopinfo (&loop);
2312 gfc_add_ss_to_loop (&loop, arrayss1);
2313 gfc_add_ss_to_loop (&loop, arrayss2);
2315 /* Initialize the loop. */
2316 gfc_conv_ss_startstride (&loop);
2317 gfc_conv_loop_setup (&loop, &expr->where);
2319 gfc_mark_ss_chain_used (arrayss1, 1);
2320 gfc_mark_ss_chain_used (arrayss2, 1);
2322 /* Generate the loop body. */
2323 gfc_start_scalarized_body (&loop, &body);
2324 gfc_init_block (&block);
2326 /* Make the tree expression for [conjg(]array1[)]. */
2327 gfc_init_se (&arrayse1, NULL);
2328 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
2329 arrayse1.ss = arrayss1;
2330 gfc_conv_expr_val (&arrayse1, arrayexpr1);
2331 if (expr->ts.type == BT_COMPLEX)
2332 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
2333 arrayse1.expr);
2334 gfc_add_block_to_block (&block, &arrayse1.pre);
2336 /* Make the tree expression for array2. */
2337 gfc_init_se (&arrayse2, NULL);
2338 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
2339 arrayse2.ss = arrayss2;
2340 gfc_conv_expr_val (&arrayse2, arrayexpr2);
2341 gfc_add_block_to_block (&block, &arrayse2.pre);
2343 /* Do the actual product and sum. */
2344 if (expr->ts.type == BT_LOGICAL)
2346 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
2347 arrayse1.expr, arrayse2.expr);
2348 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
2350 else
2352 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
2353 arrayse2.expr);
2354 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
2356 gfc_add_modify (&block, resvar, tmp);
2358 /* Finish up the loop block and the loop. */
2359 tmp = gfc_finish_block (&block);
2360 gfc_add_expr_to_block (&body, tmp);
2362 gfc_trans_scalarizing_loops (&loop, &body);
2363 gfc_add_block_to_block (&se->pre, &loop.pre);
2364 gfc_add_block_to_block (&se->pre, &loop.post);
2365 gfc_cleanup_loop (&loop);
2367 se->expr = resvar;
2371 /* Emit code for minloc or maxloc intrinsic. There are many different cases
2372 we need to handle. For performance reasons we sometimes create two
2373 loops instead of one, where the second one is much simpler.
2374 Examples for minloc intrinsic:
2375 1) Result is an array, a call is generated
2376 2) Array mask is used and NaNs need to be supported:
2377 limit = Infinity;
2378 pos = 0;
2379 S = from;
2380 while (S <= to) {
2381 if (mask[S]) {
2382 if (pos == 0) pos = S + (1 - from);
2383 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
2385 S++;
2387 goto lab2;
2388 lab1:;
2389 while (S <= to) {
2390 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
2391 S++;
2393 lab2:;
2394 3) NaNs need to be supported, but it is known at compile time or cheaply
2395 at runtime whether array is nonempty or not:
2396 limit = Infinity;
2397 pos = 0;
2398 S = from;
2399 while (S <= to) {
2400 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
2401 S++;
2403 if (from <= to) pos = 1;
2404 goto lab2;
2405 lab1:;
2406 while (S <= to) {
2407 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
2408 S++;
2410 lab2:;
2411 4) NaNs aren't supported, array mask is used:
2412 limit = infinities_supported ? Infinity : huge (limit);
2413 pos = 0;
2414 S = from;
2415 while (S <= to) {
2416 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
2417 S++;
2419 goto lab2;
2420 lab1:;
2421 while (S <= to) {
2422 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
2423 S++;
2425 lab2:;
2426 5) Same without array mask:
2427 limit = infinities_supported ? Infinity : huge (limit);
2428 pos = (from <= to) ? 1 : 0;
2429 S = from;
2430 while (S <= to) {
2431 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
2432 S++;
2434 For 3) and 5), if mask is scalar, this all goes into a conditional,
2435 setting pos = 0; in the else branch. */
2437 static void
2438 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
2440 stmtblock_t body;
2441 stmtblock_t block;
2442 stmtblock_t ifblock;
2443 stmtblock_t elseblock;
2444 tree limit;
2445 tree type;
2446 tree tmp;
2447 tree cond;
2448 tree elsetmp;
2449 tree ifbody;
2450 tree offset;
2451 tree nonempty;
2452 tree lab1, lab2;
2453 gfc_loopinfo loop;
2454 gfc_actual_arglist *actual;
2455 gfc_ss *arrayss;
2456 gfc_ss *maskss;
2457 gfc_se arrayse;
2458 gfc_se maskse;
2459 gfc_expr *arrayexpr;
2460 gfc_expr *maskexpr;
2461 tree pos;
2462 int n;
2464 if (se->ss)
2466 gfc_conv_intrinsic_funcall (se, expr);
2467 return;
2470 /* Initialize the result. */
2471 pos = gfc_create_var (gfc_array_index_type, "pos");
2472 offset = gfc_create_var (gfc_array_index_type, "offset");
2473 type = gfc_typenode_for_spec (&expr->ts);
2475 /* Walk the arguments. */
2476 actual = expr->value.function.actual;
2477 arrayexpr = actual->expr;
2478 arrayss = gfc_walk_expr (arrayexpr);
2479 gcc_assert (arrayss != gfc_ss_terminator);
2481 actual = actual->next->next;
2482 gcc_assert (actual);
2483 maskexpr = actual->expr;
2484 nonempty = NULL;
2485 if (maskexpr && maskexpr->rank != 0)
2487 maskss = gfc_walk_expr (maskexpr);
2488 gcc_assert (maskss != gfc_ss_terminator);
2490 else
2492 mpz_t asize;
2493 if (gfc_array_size (arrayexpr, &asize) == SUCCESS)
2495 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
2496 mpz_clear (asize);
2497 nonempty = fold_build2_loc (input_location, GT_EXPR,
2498 boolean_type_node, nonempty,
2499 gfc_index_zero_node);
2501 maskss = NULL;
2504 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
2505 switch (arrayexpr->ts.type)
2507 case BT_REAL:
2508 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
2509 break;
2511 case BT_INTEGER:
2512 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
2513 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
2514 arrayexpr->ts.kind);
2515 break;
2517 default:
2518 gcc_unreachable ();
2521 /* We start with the most negative possible value for MAXLOC, and the most
2522 positive possible value for MINLOC. The most negative possible value is
2523 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
2524 possible value is HUGE in both cases. */
2525 if (op == GT_EXPR)
2526 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
2527 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
2528 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
2529 build_int_cst (type, 1));
2531 gfc_add_modify (&se->pre, limit, tmp);
2533 /* Initialize the scalarizer. */
2534 gfc_init_loopinfo (&loop);
2535 gfc_add_ss_to_loop (&loop, arrayss);
2536 if (maskss)
2537 gfc_add_ss_to_loop (&loop, maskss);
2539 /* Initialize the loop. */
2540 gfc_conv_ss_startstride (&loop);
2541 gfc_conv_loop_setup (&loop, &expr->where);
2543 gcc_assert (loop.dimen == 1);
2544 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
2545 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
2546 loop.from[0], loop.to[0]);
2548 lab1 = NULL;
2549 lab2 = NULL;
2550 /* Initialize the position to zero, following Fortran 2003. We are free
2551 to do this because Fortran 95 allows the result of an entirely false
2552 mask to be processor dependent. If we know at compile time the array
2553 is non-empty and no MASK is used, we can initialize to 1 to simplify
2554 the inner loop. */
2555 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
2556 gfc_add_modify (&loop.pre, pos,
2557 fold_build3_loc (input_location, COND_EXPR,
2558 gfc_array_index_type,
2559 nonempty, gfc_index_one_node,
2560 gfc_index_zero_node));
2561 else
2563 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
2564 lab1 = gfc_build_label_decl (NULL_TREE);
2565 TREE_USED (lab1) = 1;
2566 lab2 = gfc_build_label_decl (NULL_TREE);
2567 TREE_USED (lab2) = 1;
2570 gfc_mark_ss_chain_used (arrayss, 1);
2571 if (maskss)
2572 gfc_mark_ss_chain_used (maskss, 1);
2573 /* Generate the loop body. */
2574 gfc_start_scalarized_body (&loop, &body);
2576 /* If we have a mask, only check this element if the mask is set. */
2577 if (maskss)
2579 gfc_init_se (&maskse, NULL);
2580 gfc_copy_loopinfo_to_se (&maskse, &loop);
2581 maskse.ss = maskss;
2582 gfc_conv_expr_val (&maskse, maskexpr);
2583 gfc_add_block_to_block (&body, &maskse.pre);
2585 gfc_start_block (&block);
2587 else
2588 gfc_init_block (&block);
2590 /* Compare with the current limit. */
2591 gfc_init_se (&arrayse, NULL);
2592 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2593 arrayse.ss = arrayss;
2594 gfc_conv_expr_val (&arrayse, arrayexpr);
2595 gfc_add_block_to_block (&block, &arrayse.pre);
2597 /* We do the following if this is a more extreme value. */
2598 gfc_start_block (&ifblock);
2600 /* Assign the value to the limit... */
2601 gfc_add_modify (&ifblock, limit, arrayse.expr);
2603 /* Remember where we are. An offset must be added to the loop
2604 counter to obtain the required position. */
2605 if (loop.from[0])
2606 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2607 gfc_index_one_node, loop.from[0]);
2608 else
2609 tmp = gfc_index_one_node;
2611 gfc_add_modify (&block, offset, tmp);
2613 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
2615 stmtblock_t ifblock2;
2616 tree ifbody2;
2618 gfc_start_block (&ifblock2);
2619 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
2620 loop.loopvar[0], offset);
2621 gfc_add_modify (&ifblock2, pos, tmp);
2622 ifbody2 = gfc_finish_block (&ifblock2);
2623 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, pos,
2624 gfc_index_zero_node);
2625 tmp = build3_v (COND_EXPR, cond, ifbody2,
2626 build_empty_stmt (input_location));
2627 gfc_add_expr_to_block (&block, tmp);
2630 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
2631 loop.loopvar[0], offset);
2632 gfc_add_modify (&ifblock, pos, tmp);
2634 if (lab1)
2635 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
2637 ifbody = gfc_finish_block (&ifblock);
2639 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
2641 if (lab1)
2642 cond = fold_build2_loc (input_location,
2643 op == GT_EXPR ? GE_EXPR : LE_EXPR,
2644 boolean_type_node, arrayse.expr, limit);
2645 else
2646 cond = fold_build2_loc (input_location, op, boolean_type_node,
2647 arrayse.expr, limit);
2649 ifbody = build3_v (COND_EXPR, cond, ifbody,
2650 build_empty_stmt (input_location));
2652 gfc_add_expr_to_block (&block, ifbody);
2654 if (maskss)
2656 /* We enclose the above in if (mask) {...}. */
2657 tmp = gfc_finish_block (&block);
2659 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2660 build_empty_stmt (input_location));
2662 else
2663 tmp = gfc_finish_block (&block);
2664 gfc_add_expr_to_block (&body, tmp);
2666 if (lab1)
2668 gfc_trans_scalarized_loop_end (&loop, 0, &body);
2670 if (HONOR_NANS (DECL_MODE (limit)))
2672 if (nonempty != NULL)
2674 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
2675 tmp = build3_v (COND_EXPR, nonempty, ifbody,
2676 build_empty_stmt (input_location));
2677 gfc_add_expr_to_block (&loop.code[0], tmp);
2681 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
2682 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
2683 gfc_start_block (&body);
2685 /* If we have a mask, only check this element if the mask is set. */
2686 if (maskss)
2688 gfc_init_se (&maskse, NULL);
2689 gfc_copy_loopinfo_to_se (&maskse, &loop);
2690 maskse.ss = maskss;
2691 gfc_conv_expr_val (&maskse, maskexpr);
2692 gfc_add_block_to_block (&body, &maskse.pre);
2694 gfc_start_block (&block);
2696 else
2697 gfc_init_block (&block);
2699 /* Compare with the current limit. */
2700 gfc_init_se (&arrayse, NULL);
2701 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2702 arrayse.ss = arrayss;
2703 gfc_conv_expr_val (&arrayse, arrayexpr);
2704 gfc_add_block_to_block (&block, &arrayse.pre);
2706 /* We do the following if this is a more extreme value. */
2707 gfc_start_block (&ifblock);
2709 /* Assign the value to the limit... */
2710 gfc_add_modify (&ifblock, limit, arrayse.expr);
2712 /* Remember where we are. An offset must be added to the loop
2713 counter to obtain the required position. */
2714 if (loop.from[0])
2715 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2716 gfc_index_one_node, loop.from[0]);
2717 else
2718 tmp = gfc_index_one_node;
2720 gfc_add_modify (&block, offset, tmp);
2722 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
2723 loop.loopvar[0], offset);
2724 gfc_add_modify (&ifblock, pos, tmp);
2726 ifbody = gfc_finish_block (&ifblock);
2728 cond = fold_build2_loc (input_location, op, boolean_type_node,
2729 arrayse.expr, limit);
2731 tmp = build3_v (COND_EXPR, cond, ifbody,
2732 build_empty_stmt (input_location));
2733 gfc_add_expr_to_block (&block, tmp);
2735 if (maskss)
2737 /* We enclose the above in if (mask) {...}. */
2738 tmp = gfc_finish_block (&block);
2740 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2741 build_empty_stmt (input_location));
2743 else
2744 tmp = gfc_finish_block (&block);
2745 gfc_add_expr_to_block (&body, tmp);
2746 /* Avoid initializing loopvar[0] again, it should be left where
2747 it finished by the first loop. */
2748 loop.from[0] = loop.loopvar[0];
2751 gfc_trans_scalarizing_loops (&loop, &body);
2753 if (lab2)
2754 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
2756 /* For a scalar mask, enclose the loop in an if statement. */
2757 if (maskexpr && maskss == NULL)
2759 gfc_init_se (&maskse, NULL);
2760 gfc_conv_expr_val (&maskse, maskexpr);
2761 gfc_init_block (&block);
2762 gfc_add_block_to_block (&block, &loop.pre);
2763 gfc_add_block_to_block (&block, &loop.post);
2764 tmp = gfc_finish_block (&block);
2766 /* For the else part of the scalar mask, just initialize
2767 the pos variable the same way as above. */
2769 gfc_init_block (&elseblock);
2770 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
2771 elsetmp = gfc_finish_block (&elseblock);
2773 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
2774 gfc_add_expr_to_block (&block, tmp);
2775 gfc_add_block_to_block (&se->pre, &block);
2777 else
2779 gfc_add_block_to_block (&se->pre, &loop.pre);
2780 gfc_add_block_to_block (&se->pre, &loop.post);
2782 gfc_cleanup_loop (&loop);
2784 se->expr = convert (type, pos);
2787 /* Emit code for minval or maxval intrinsic. There are many different cases
2788 we need to handle. For performance reasons we sometimes create two
2789 loops instead of one, where the second one is much simpler.
2790 Examples for minval intrinsic:
2791 1) Result is an array, a call is generated
2792 2) Array mask is used and NaNs need to be supported, rank 1:
2793 limit = Infinity;
2794 nonempty = false;
2795 S = from;
2796 while (S <= to) {
2797 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
2798 S++;
2800 limit = nonempty ? NaN : huge (limit);
2801 lab:
2802 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
2803 3) NaNs need to be supported, but it is known at compile time or cheaply
2804 at runtime whether array is nonempty or not, rank 1:
2805 limit = Infinity;
2806 S = from;
2807 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
2808 limit = (from <= to) ? NaN : huge (limit);
2809 lab:
2810 while (S <= to) { limit = min (a[S], limit); S++; }
2811 4) Array mask is used and NaNs need to be supported, rank > 1:
2812 limit = Infinity;
2813 nonempty = false;
2814 fast = false;
2815 S1 = from1;
2816 while (S1 <= to1) {
2817 S2 = from2;
2818 while (S2 <= to2) {
2819 if (mask[S1][S2]) {
2820 if (fast) limit = min (a[S1][S2], limit);
2821 else {
2822 nonempty = true;
2823 if (a[S1][S2] <= limit) {
2824 limit = a[S1][S2];
2825 fast = true;
2829 S2++;
2831 S1++;
2833 if (!fast)
2834 limit = nonempty ? NaN : huge (limit);
2835 5) NaNs need to be supported, but it is known at compile time or cheaply
2836 at runtime whether array is nonempty or not, rank > 1:
2837 limit = Infinity;
2838 fast = false;
2839 S1 = from1;
2840 while (S1 <= to1) {
2841 S2 = from2;
2842 while (S2 <= to2) {
2843 if (fast) limit = min (a[S1][S2], limit);
2844 else {
2845 if (a[S1][S2] <= limit) {
2846 limit = a[S1][S2];
2847 fast = true;
2850 S2++;
2852 S1++;
2854 if (!fast)
2855 limit = (nonempty_array) ? NaN : huge (limit);
2856 6) NaNs aren't supported, but infinities are. Array mask is used:
2857 limit = Infinity;
2858 nonempty = false;
2859 S = from;
2860 while (S <= to) {
2861 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
2862 S++;
2864 limit = nonempty ? limit : huge (limit);
2865 7) Same without array mask:
2866 limit = Infinity;
2867 S = from;
2868 while (S <= to) { limit = min (a[S], limit); S++; }
2869 limit = (from <= to) ? limit : huge (limit);
2870 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
2871 limit = huge (limit);
2872 S = from;
2873 while (S <= to) { limit = min (a[S], limit); S++); }
2875 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
2876 with array mask instead).
2877 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
2878 setting limit = huge (limit); in the else branch. */
2880 static void
2881 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
2883 tree limit;
2884 tree type;
2885 tree tmp;
2886 tree ifbody;
2887 tree nonempty;
2888 tree nonempty_var;
2889 tree lab;
2890 tree fast;
2891 tree huge_cst = NULL, nan_cst = NULL;
2892 stmtblock_t body;
2893 stmtblock_t block, block2;
2894 gfc_loopinfo loop;
2895 gfc_actual_arglist *actual;
2896 gfc_ss *arrayss;
2897 gfc_ss *maskss;
2898 gfc_se arrayse;
2899 gfc_se maskse;
2900 gfc_expr *arrayexpr;
2901 gfc_expr *maskexpr;
2902 int n;
2904 if (se->ss)
2906 gfc_conv_intrinsic_funcall (se, expr);
2907 return;
2910 type = gfc_typenode_for_spec (&expr->ts);
2911 /* Initialize the result. */
2912 limit = gfc_create_var (type, "limit");
2913 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
2914 switch (expr->ts.type)
2916 case BT_REAL:
2917 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
2918 expr->ts.kind, 0);
2919 if (HONOR_INFINITIES (DECL_MODE (limit)))
2921 REAL_VALUE_TYPE real;
2922 real_inf (&real);
2923 tmp = build_real (type, real);
2925 else
2926 tmp = huge_cst;
2927 if (HONOR_NANS (DECL_MODE (limit)))
2929 REAL_VALUE_TYPE real;
2930 real_nan (&real, "", 1, DECL_MODE (limit));
2931 nan_cst = build_real (type, real);
2933 break;
2935 case BT_INTEGER:
2936 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
2937 break;
2939 default:
2940 gcc_unreachable ();
2943 /* We start with the most negative possible value for MAXVAL, and the most
2944 positive possible value for MINVAL. The most negative possible value is
2945 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
2946 possible value is HUGE in both cases. */
2947 if (op == GT_EXPR)
2949 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
2950 if (huge_cst)
2951 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
2952 TREE_TYPE (huge_cst), huge_cst);
2955 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
2956 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
2957 tmp, build_int_cst (type, 1));
2959 gfc_add_modify (&se->pre, limit, tmp);
2961 /* Walk the arguments. */
2962 actual = expr->value.function.actual;
2963 arrayexpr = actual->expr;
2964 arrayss = gfc_walk_expr (arrayexpr);
2965 gcc_assert (arrayss != gfc_ss_terminator);
2967 actual = actual->next->next;
2968 gcc_assert (actual);
2969 maskexpr = actual->expr;
2970 nonempty = NULL;
2971 if (maskexpr && maskexpr->rank != 0)
2973 maskss = gfc_walk_expr (maskexpr);
2974 gcc_assert (maskss != gfc_ss_terminator);
2976 else
2978 mpz_t asize;
2979 if (gfc_array_size (arrayexpr, &asize) == SUCCESS)
2981 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
2982 mpz_clear (asize);
2983 nonempty = fold_build2_loc (input_location, GT_EXPR,
2984 boolean_type_node, nonempty,
2985 gfc_index_zero_node);
2987 maskss = NULL;
2990 /* Initialize the scalarizer. */
2991 gfc_init_loopinfo (&loop);
2992 gfc_add_ss_to_loop (&loop, arrayss);
2993 if (maskss)
2994 gfc_add_ss_to_loop (&loop, maskss);
2996 /* Initialize the loop. */
2997 gfc_conv_ss_startstride (&loop);
2998 gfc_conv_loop_setup (&loop, &expr->where);
3000 if (nonempty == NULL && maskss == NULL
3001 && loop.dimen == 1 && loop.from[0] && loop.to[0])
3002 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3003 loop.from[0], loop.to[0]);
3004 nonempty_var = NULL;
3005 if (nonempty == NULL
3006 && (HONOR_INFINITIES (DECL_MODE (limit))
3007 || HONOR_NANS (DECL_MODE (limit))))
3009 nonempty_var = gfc_create_var (boolean_type_node, "nonempty");
3010 gfc_add_modify (&se->pre, nonempty_var, boolean_false_node);
3011 nonempty = nonempty_var;
3013 lab = NULL;
3014 fast = NULL;
3015 if (HONOR_NANS (DECL_MODE (limit)))
3017 if (loop.dimen == 1)
3019 lab = gfc_build_label_decl (NULL_TREE);
3020 TREE_USED (lab) = 1;
3022 else
3024 fast = gfc_create_var (boolean_type_node, "fast");
3025 gfc_add_modify (&se->pre, fast, boolean_false_node);
3029 gfc_mark_ss_chain_used (arrayss, 1);
3030 if (maskss)
3031 gfc_mark_ss_chain_used (maskss, 1);
3032 /* Generate the loop body. */
3033 gfc_start_scalarized_body (&loop, &body);
3035 /* If we have a mask, only add this element if the mask is set. */
3036 if (maskss)
3038 gfc_init_se (&maskse, NULL);
3039 gfc_copy_loopinfo_to_se (&maskse, &loop);
3040 maskse.ss = maskss;
3041 gfc_conv_expr_val (&maskse, maskexpr);
3042 gfc_add_block_to_block (&body, &maskse.pre);
3044 gfc_start_block (&block);
3046 else
3047 gfc_init_block (&block);
3049 /* Compare with the current limit. */
3050 gfc_init_se (&arrayse, NULL);
3051 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3052 arrayse.ss = arrayss;
3053 gfc_conv_expr_val (&arrayse, arrayexpr);
3054 gfc_add_block_to_block (&block, &arrayse.pre);
3056 gfc_init_block (&block2);
3058 if (nonempty_var)
3059 gfc_add_modify (&block2, nonempty_var, boolean_true_node);
3061 if (HONOR_NANS (DECL_MODE (limit)))
3063 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
3064 boolean_type_node, arrayse.expr, limit);
3065 if (lab)
3066 ifbody = build1_v (GOTO_EXPR, lab);
3067 else
3069 stmtblock_t ifblock;
3071 gfc_init_block (&ifblock);
3072 gfc_add_modify (&ifblock, limit, arrayse.expr);
3073 gfc_add_modify (&ifblock, fast, boolean_true_node);
3074 ifbody = gfc_finish_block (&ifblock);
3076 tmp = build3_v (COND_EXPR, tmp, ifbody,
3077 build_empty_stmt (input_location));
3078 gfc_add_expr_to_block (&block2, tmp);
3080 else
3082 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3083 signed zeros. */
3084 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3086 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3087 arrayse.expr, limit);
3088 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3089 tmp = build3_v (COND_EXPR, tmp, ifbody,
3090 build_empty_stmt (input_location));
3091 gfc_add_expr_to_block (&block2, tmp);
3093 else
3095 tmp = fold_build2_loc (input_location,
3096 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3097 type, arrayse.expr, limit);
3098 gfc_add_modify (&block2, limit, tmp);
3102 if (fast)
3104 tree elsebody = gfc_finish_block (&block2);
3106 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3107 signed zeros. */
3108 if (HONOR_NANS (DECL_MODE (limit))
3109 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3111 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3112 arrayse.expr, limit);
3113 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3114 ifbody = build3_v (COND_EXPR, tmp, ifbody,
3115 build_empty_stmt (input_location));
3117 else
3119 tmp = fold_build2_loc (input_location,
3120 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3121 type, arrayse.expr, limit);
3122 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
3124 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
3125 gfc_add_expr_to_block (&block, tmp);
3127 else
3128 gfc_add_block_to_block (&block, &block2);
3130 gfc_add_block_to_block (&block, &arrayse.post);
3132 tmp = gfc_finish_block (&block);
3133 if (maskss)
3134 /* We enclose the above in if (mask) {...}. */
3135 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3136 build_empty_stmt (input_location));
3137 gfc_add_expr_to_block (&body, tmp);
3139 if (lab)
3141 gfc_trans_scalarized_loop_end (&loop, 0, &body);
3143 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
3144 nan_cst, huge_cst);
3145 gfc_add_modify (&loop.code[0], limit, tmp);
3146 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
3148 gfc_start_block (&body);
3150 /* If we have a mask, only add this element if the mask is set. */
3151 if (maskss)
3153 gfc_init_se (&maskse, NULL);
3154 gfc_copy_loopinfo_to_se (&maskse, &loop);
3155 maskse.ss = maskss;
3156 gfc_conv_expr_val (&maskse, maskexpr);
3157 gfc_add_block_to_block (&body, &maskse.pre);
3159 gfc_start_block (&block);
3161 else
3162 gfc_init_block (&block);
3164 /* Compare with the current limit. */
3165 gfc_init_se (&arrayse, NULL);
3166 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3167 arrayse.ss = arrayss;
3168 gfc_conv_expr_val (&arrayse, arrayexpr);
3169 gfc_add_block_to_block (&block, &arrayse.pre);
3171 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3172 signed zeros. */
3173 if (HONOR_NANS (DECL_MODE (limit))
3174 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3176 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3177 arrayse.expr, limit);
3178 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3179 tmp = build3_v (COND_EXPR, tmp, ifbody,
3180 build_empty_stmt (input_location));
3181 gfc_add_expr_to_block (&block, tmp);
3183 else
3185 tmp = fold_build2_loc (input_location,
3186 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3187 type, arrayse.expr, limit);
3188 gfc_add_modify (&block, limit, tmp);
3191 gfc_add_block_to_block (&block, &arrayse.post);
3193 tmp = gfc_finish_block (&block);
3194 if (maskss)
3195 /* We enclose the above in if (mask) {...}. */
3196 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3197 build_empty_stmt (input_location));
3198 gfc_add_expr_to_block (&body, tmp);
3199 /* Avoid initializing loopvar[0] again, it should be left where
3200 it finished by the first loop. */
3201 loop.from[0] = loop.loopvar[0];
3203 gfc_trans_scalarizing_loops (&loop, &body);
3205 if (fast)
3207 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
3208 nan_cst, huge_cst);
3209 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
3210 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
3211 ifbody);
3212 gfc_add_expr_to_block (&loop.pre, tmp);
3214 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
3216 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
3217 huge_cst);
3218 gfc_add_modify (&loop.pre, limit, tmp);
3221 /* For a scalar mask, enclose the loop in an if statement. */
3222 if (maskexpr && maskss == NULL)
3224 tree else_stmt;
3226 gfc_init_se (&maskse, NULL);
3227 gfc_conv_expr_val (&maskse, maskexpr);
3228 gfc_init_block (&block);
3229 gfc_add_block_to_block (&block, &loop.pre);
3230 gfc_add_block_to_block (&block, &loop.post);
3231 tmp = gfc_finish_block (&block);
3233 if (HONOR_INFINITIES (DECL_MODE (limit)))
3234 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
3235 else
3236 else_stmt = build_empty_stmt (input_location);
3237 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
3238 gfc_add_expr_to_block (&block, tmp);
3239 gfc_add_block_to_block (&se->pre, &block);
3241 else
3243 gfc_add_block_to_block (&se->pre, &loop.pre);
3244 gfc_add_block_to_block (&se->pre, &loop.post);
3247 gfc_cleanup_loop (&loop);
3249 se->expr = limit;
3252 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
3253 static void
3254 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
3256 tree args[2];
3257 tree type;
3258 tree tmp;
3260 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3261 type = TREE_TYPE (args[0]);
3263 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3264 build_int_cst (type, 1), args[1]);
3265 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
3266 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
3267 build_int_cst (type, 0));
3268 type = gfc_typenode_for_spec (&expr->ts);
3269 se->expr = convert (type, tmp);
3273 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
3274 static void
3275 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
3277 tree args[2];
3279 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3281 /* Convert both arguments to the unsigned type of the same size. */
3282 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
3283 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
3285 /* If they have unequal type size, convert to the larger one. */
3286 if (TYPE_PRECISION (TREE_TYPE (args[0]))
3287 > TYPE_PRECISION (TREE_TYPE (args[1])))
3288 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
3289 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
3290 > TYPE_PRECISION (TREE_TYPE (args[0])))
3291 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
3293 /* Now, we compare them. */
3294 se->expr = fold_build2_loc (input_location, op, boolean_type_node,
3295 args[0], args[1]);
3299 /* Generate code to perform the specified operation. */
3300 static void
3301 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
3303 tree args[2];
3305 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3306 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
3307 args[0], args[1]);
3310 /* Bitwise not. */
3311 static void
3312 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
3314 tree arg;
3316 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3317 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
3318 TREE_TYPE (arg), arg);
3321 /* Set or clear a single bit. */
3322 static void
3323 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
3325 tree args[2];
3326 tree type;
3327 tree tmp;
3328 enum tree_code op;
3330 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3331 type = TREE_TYPE (args[0]);
3333 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3334 build_int_cst (type, 1), args[1]);
3335 if (set)
3336 op = BIT_IOR_EXPR;
3337 else
3339 op = BIT_AND_EXPR;
3340 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
3342 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
3345 /* Extract a sequence of bits.
3346 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
3347 static void
3348 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
3350 tree args[3];
3351 tree type;
3352 tree tmp;
3353 tree mask;
3355 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3356 type = TREE_TYPE (args[0]);
3358 mask = build_int_cst (type, -1);
3359 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
3360 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
3362 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
3364 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
3367 static void
3368 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
3369 bool arithmetic)
3371 tree args[2], type, num_bits, cond;
3373 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3375 args[0] = gfc_evaluate_now (args[0], &se->pre);
3376 args[1] = gfc_evaluate_now (args[1], &se->pre);
3377 type = TREE_TYPE (args[0]);
3379 if (!arithmetic)
3380 args[0] = fold_convert (unsigned_type_for (type), args[0]);
3381 else
3382 gcc_assert (right_shift);
3384 se->expr = fold_build2_loc (input_location,
3385 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
3386 TREE_TYPE (args[0]), args[0], args[1]);
3388 if (!arithmetic)
3389 se->expr = fold_convert (type, se->expr);
3391 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
3392 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
3393 special case. */
3394 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
3395 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
3396 args[1], num_bits);
3398 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
3399 build_int_cst (type, 0), se->expr);
3402 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
3404 : ((shift >= 0) ? i << shift : i >> -shift)
3405 where all shifts are logical shifts. */
3406 static void
3407 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
3409 tree args[2];
3410 tree type;
3411 tree utype;
3412 tree tmp;
3413 tree width;
3414 tree num_bits;
3415 tree cond;
3416 tree lshift;
3417 tree rshift;
3419 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3421 args[0] = gfc_evaluate_now (args[0], &se->pre);
3422 args[1] = gfc_evaluate_now (args[1], &se->pre);
3424 type = TREE_TYPE (args[0]);
3425 utype = unsigned_type_for (type);
3427 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
3428 args[1]);
3430 /* Left shift if positive. */
3431 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
3433 /* Right shift if negative.
3434 We convert to an unsigned type because we want a logical shift.
3435 The standard doesn't define the case of shifting negative
3436 numbers, and we try to be compatible with other compilers, most
3437 notably g77, here. */
3438 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
3439 utype, convert (utype, args[0]), width));
3441 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, args[1],
3442 build_int_cst (TREE_TYPE (args[1]), 0));
3443 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
3445 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
3446 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
3447 special case. */
3448 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
3449 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, width,
3450 num_bits);
3451 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
3452 build_int_cst (type, 0), tmp);
3456 /* Circular shift. AKA rotate or barrel shift. */
3458 static void
3459 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
3461 tree *args;
3462 tree type;
3463 tree tmp;
3464 tree lrot;
3465 tree rrot;
3466 tree zero;
3467 unsigned int num_args;
3469 num_args = gfc_intrinsic_argument_list_length (expr);
3470 args = XALLOCAVEC (tree, num_args);
3472 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3474 if (num_args == 3)
3476 /* Use a library function for the 3 parameter version. */
3477 tree int4type = gfc_get_int_type (4);
3479 type = TREE_TYPE (args[0]);
3480 /* We convert the first argument to at least 4 bytes, and
3481 convert back afterwards. This removes the need for library
3482 functions for all argument sizes, and function will be
3483 aligned to at least 32 bits, so there's no loss. */
3484 if (expr->ts.kind < 4)
3485 args[0] = convert (int4type, args[0]);
3487 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
3488 need loads of library functions. They cannot have values >
3489 BIT_SIZE (I) so the conversion is safe. */
3490 args[1] = convert (int4type, args[1]);
3491 args[2] = convert (int4type, args[2]);
3493 switch (expr->ts.kind)
3495 case 1:
3496 case 2:
3497 case 4:
3498 tmp = gfor_fndecl_math_ishftc4;
3499 break;
3500 case 8:
3501 tmp = gfor_fndecl_math_ishftc8;
3502 break;
3503 case 16:
3504 tmp = gfor_fndecl_math_ishftc16;
3505 break;
3506 default:
3507 gcc_unreachable ();
3509 se->expr = build_call_expr_loc (input_location,
3510 tmp, 3, args[0], args[1], args[2]);
3511 /* Convert the result back to the original type, if we extended
3512 the first argument's width above. */
3513 if (expr->ts.kind < 4)
3514 se->expr = convert (type, se->expr);
3516 return;
3518 type = TREE_TYPE (args[0]);
3520 /* Evaluate arguments only once. */
3521 args[0] = gfc_evaluate_now (args[0], &se->pre);
3522 args[1] = gfc_evaluate_now (args[1], &se->pre);
3524 /* Rotate left if positive. */
3525 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
3527 /* Rotate right if negative. */
3528 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
3529 args[1]);
3530 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
3532 zero = build_int_cst (TREE_TYPE (args[1]), 0);
3533 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, args[1],
3534 zero);
3535 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
3537 /* Do nothing if shift == 0. */
3538 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, args[1],
3539 zero);
3540 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
3541 rrot);
3545 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
3546 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
3548 The conditional expression is necessary because the result of LEADZ(0)
3549 is defined, but the result of __builtin_clz(0) is undefined for most
3550 targets.
3552 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
3553 difference in bit size between the argument of LEADZ and the C int. */
3555 static void
3556 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
3558 tree arg;
3559 tree arg_type;
3560 tree cond;
3561 tree result_type;
3562 tree leadz;
3563 tree bit_size;
3564 tree tmp;
3565 tree func;
3566 int s, argsize;
3568 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3569 argsize = TYPE_PRECISION (TREE_TYPE (arg));
3571 /* Which variant of __builtin_clz* should we call? */
3572 if (argsize <= INT_TYPE_SIZE)
3574 arg_type = unsigned_type_node;
3575 func = built_in_decls[BUILT_IN_CLZ];
3577 else if (argsize <= LONG_TYPE_SIZE)
3579 arg_type = long_unsigned_type_node;
3580 func = built_in_decls[BUILT_IN_CLZL];
3582 else if (argsize <= LONG_LONG_TYPE_SIZE)
3584 arg_type = long_long_unsigned_type_node;
3585 func = built_in_decls[BUILT_IN_CLZLL];
3587 else
3589 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
3590 arg_type = gfc_build_uint_type (argsize);
3591 func = NULL_TREE;
3594 /* Convert the actual argument twice: first, to the unsigned type of the
3595 same size; then, to the proper argument type for the built-in
3596 function. But the return type is of the default INTEGER kind. */
3597 arg = fold_convert (gfc_build_uint_type (argsize), arg);
3598 arg = fold_convert (arg_type, arg);
3599 arg = gfc_evaluate_now (arg, &se->pre);
3600 result_type = gfc_get_int_type (gfc_default_integer_kind);
3602 /* Compute LEADZ for the case i .ne. 0. */
3603 if (func)
3605 s = TYPE_PRECISION (arg_type) - argsize;
3606 tmp = fold_convert (result_type,
3607 build_call_expr_loc (input_location, func,
3608 1, arg));
3609 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
3610 tmp, build_int_cst (result_type, s));
3612 else
3614 /* We end up here if the argument type is larger than 'long long'.
3615 We generate this code:
3617 if (x & (ULL_MAX << ULL_SIZE) != 0)
3618 return clzll ((unsigned long long) (x >> ULLSIZE));
3619 else
3620 return ULL_SIZE + clzll ((unsigned long long) x);
3621 where ULL_MAX is the largest value that a ULL_MAX can hold
3622 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
3623 is the bit-size of the long long type (64 in this example). */
3624 tree ullsize, ullmax, tmp1, tmp2;
3626 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
3627 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
3628 long_long_unsigned_type_node,
3629 build_int_cst (long_long_unsigned_type_node,
3630 0));
3632 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
3633 fold_convert (arg_type, ullmax), ullsize);
3634 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
3635 arg, cond);
3636 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
3637 cond, build_int_cst (arg_type, 0));
3639 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
3640 arg, ullsize);
3641 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
3642 tmp1 = fold_convert (result_type,
3643 build_call_expr_loc (input_location,
3644 built_in_decls[BUILT_IN_CLZLL],
3645 1, tmp1));
3647 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
3648 tmp2 = fold_convert (result_type,
3649 build_call_expr_loc (input_location,
3650 built_in_decls[BUILT_IN_CLZLL],
3651 1, tmp2));
3652 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
3653 tmp2, ullsize);
3655 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
3656 cond, tmp1, tmp2);
3659 /* Build BIT_SIZE. */
3660 bit_size = build_int_cst (result_type, argsize);
3662 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
3663 arg, build_int_cst (arg_type, 0));
3664 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
3665 bit_size, leadz);
3669 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
3671 The conditional expression is necessary because the result of TRAILZ(0)
3672 is defined, but the result of __builtin_ctz(0) is undefined for most
3673 targets. */
3675 static void
3676 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
3678 tree arg;
3679 tree arg_type;
3680 tree cond;
3681 tree result_type;
3682 tree trailz;
3683 tree bit_size;
3684 tree func;
3685 int argsize;
3687 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3688 argsize = TYPE_PRECISION (TREE_TYPE (arg));
3690 /* Which variant of __builtin_ctz* should we call? */
3691 if (argsize <= INT_TYPE_SIZE)
3693 arg_type = unsigned_type_node;
3694 func = built_in_decls[BUILT_IN_CTZ];
3696 else if (argsize <= LONG_TYPE_SIZE)
3698 arg_type = long_unsigned_type_node;
3699 func = built_in_decls[BUILT_IN_CTZL];
3701 else if (argsize <= LONG_LONG_TYPE_SIZE)
3703 arg_type = long_long_unsigned_type_node;
3704 func = built_in_decls[BUILT_IN_CTZLL];
3706 else
3708 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
3709 arg_type = gfc_build_uint_type (argsize);
3710 func = NULL_TREE;
3713 /* Convert the actual argument twice: first, to the unsigned type of the
3714 same size; then, to the proper argument type for the built-in
3715 function. But the return type is of the default INTEGER kind. */
3716 arg = fold_convert (gfc_build_uint_type (argsize), arg);
3717 arg = fold_convert (arg_type, arg);
3718 arg = gfc_evaluate_now (arg, &se->pre);
3719 result_type = gfc_get_int_type (gfc_default_integer_kind);
3721 /* Compute TRAILZ for the case i .ne. 0. */
3722 if (func)
3723 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
3724 func, 1, arg));
3725 else
3727 /* We end up here if the argument type is larger than 'long long'.
3728 We generate this code:
3730 if ((x & ULL_MAX) == 0)
3731 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
3732 else
3733 return ctzll ((unsigned long long) x);
3735 where ULL_MAX is the largest value that a ULL_MAX can hold
3736 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
3737 is the bit-size of the long long type (64 in this example). */
3738 tree ullsize, ullmax, tmp1, tmp2;
3740 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
3741 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
3742 long_long_unsigned_type_node,
3743 build_int_cst (long_long_unsigned_type_node, 0));
3745 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
3746 fold_convert (arg_type, ullmax));
3747 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, cond,
3748 build_int_cst (arg_type, 0));
3750 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
3751 arg, ullsize);
3752 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
3753 tmp1 = fold_convert (result_type,
3754 build_call_expr_loc (input_location,
3755 built_in_decls[BUILT_IN_CTZLL],
3756 1, tmp1));
3757 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
3758 tmp1, ullsize);
3760 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
3761 tmp2 = fold_convert (result_type,
3762 build_call_expr_loc (input_location,
3763 built_in_decls[BUILT_IN_CTZLL],
3764 1, tmp2));
3766 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
3767 cond, tmp1, tmp2);
3770 /* Build BIT_SIZE. */
3771 bit_size = build_int_cst (result_type, argsize);
3773 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
3774 arg, build_int_cst (arg_type, 0));
3775 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
3776 bit_size, trailz);
3779 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
3780 for types larger than "long long", we call the long long built-in for
3781 the lower and higher bits and combine the result. */
3783 static void
3784 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
3786 tree arg;
3787 tree arg_type;
3788 tree result_type;
3789 tree func;
3790 int argsize;
3792 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3793 argsize = TYPE_PRECISION (TREE_TYPE (arg));
3794 result_type = gfc_get_int_type (gfc_default_integer_kind);
3796 /* Which variant of the builtin should we call? */
3797 if (argsize <= INT_TYPE_SIZE)
3799 arg_type = unsigned_type_node;
3800 func = built_in_decls[parity ? BUILT_IN_PARITY : BUILT_IN_POPCOUNT];
3802 else if (argsize <= LONG_TYPE_SIZE)
3804 arg_type = long_unsigned_type_node;
3805 func = built_in_decls[parity ? BUILT_IN_PARITYL : BUILT_IN_POPCOUNTL];
3807 else if (argsize <= LONG_LONG_TYPE_SIZE)
3809 arg_type = long_long_unsigned_type_node;
3810 func = built_in_decls[parity ? BUILT_IN_PARITYLL : BUILT_IN_POPCOUNTLL];
3812 else
3814 /* Our argument type is larger than 'long long', which mean none
3815 of the POPCOUNT builtins covers it. We thus call the 'long long'
3816 variant multiple times, and add the results. */
3817 tree utype, arg2, call1, call2;
3819 /* For now, we only cover the case where argsize is twice as large
3820 as 'long long'. */
3821 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
3823 func = built_in_decls[parity ? BUILT_IN_PARITYLL : BUILT_IN_POPCOUNTLL];
3825 /* Convert it to an integer, and store into a variable. */
3826 utype = gfc_build_uint_type (argsize);
3827 arg = fold_convert (utype, arg);
3828 arg = gfc_evaluate_now (arg, &se->pre);
3830 /* Call the builtin twice. */
3831 call1 = build_call_expr_loc (input_location, func, 1,
3832 fold_convert (long_long_unsigned_type_node,
3833 arg));
3835 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
3836 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
3837 call2 = build_call_expr_loc (input_location, func, 1,
3838 fold_convert (long_long_unsigned_type_node,
3839 arg2));
3841 /* Combine the results. */
3842 if (parity)
3843 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
3844 call1, call2);
3845 else
3846 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
3847 call1, call2);
3849 return;
3852 /* Convert the actual argument twice: first, to the unsigned type of the
3853 same size; then, to the proper argument type for the built-in
3854 function. */
3855 arg = fold_convert (gfc_build_uint_type (argsize), arg);
3856 arg = fold_convert (arg_type, arg);
3858 se->expr = fold_convert (result_type,
3859 build_call_expr_loc (input_location, func, 1, arg));
3863 /* Process an intrinsic with unspecified argument-types that has an optional
3864 argument (which could be of type character), e.g. EOSHIFT. For those, we
3865 need to append the string length of the optional argument if it is not
3866 present and the type is really character.
3867 primary specifies the position (starting at 1) of the non-optional argument
3868 specifying the type and optional gives the position of the optional
3869 argument in the arglist. */
3871 static void
3872 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
3873 unsigned primary, unsigned optional)
3875 gfc_actual_arglist* prim_arg;
3876 gfc_actual_arglist* opt_arg;
3877 unsigned cur_pos;
3878 gfc_actual_arglist* arg;
3879 gfc_symbol* sym;
3880 VEC(tree,gc) *append_args;
3882 /* Find the two arguments given as position. */
3883 cur_pos = 0;
3884 prim_arg = NULL;
3885 opt_arg = NULL;
3886 for (arg = expr->value.function.actual; arg; arg = arg->next)
3888 ++cur_pos;
3890 if (cur_pos == primary)
3891 prim_arg = arg;
3892 if (cur_pos == optional)
3893 opt_arg = arg;
3895 if (cur_pos >= primary && cur_pos >= optional)
3896 break;
3898 gcc_assert (prim_arg);
3899 gcc_assert (prim_arg->expr);
3900 gcc_assert (opt_arg);
3902 /* If we do have type CHARACTER and the optional argument is really absent,
3903 append a dummy 0 as string length. */
3904 append_args = NULL;
3905 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
3907 tree dummy;
3909 dummy = build_int_cst (gfc_charlen_type_node, 0);
3910 append_args = VEC_alloc (tree, gc, 1);
3911 VEC_quick_push (tree, append_args, dummy);
3914 /* Build the call itself. */
3915 sym = gfc_get_symbol_for_expr (expr);
3916 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
3917 append_args);
3918 gfc_free (sym);
3922 /* The length of a character string. */
3923 static void
3924 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
3926 tree len;
3927 tree type;
3928 tree decl;
3929 gfc_symbol *sym;
3930 gfc_se argse;
3931 gfc_expr *arg;
3932 gfc_ss *ss;
3934 gcc_assert (!se->ss);
3936 arg = expr->value.function.actual->expr;
3938 type = gfc_typenode_for_spec (&expr->ts);
3939 switch (arg->expr_type)
3941 case EXPR_CONSTANT:
3942 len = build_int_cst (NULL_TREE, arg->value.character.length);
3943 break;
3945 case EXPR_ARRAY:
3946 /* Obtain the string length from the function used by
3947 trans-array.c(gfc_trans_array_constructor). */
3948 len = NULL_TREE;
3949 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
3950 break;
3952 case EXPR_VARIABLE:
3953 if (arg->ref == NULL
3954 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
3956 /* This doesn't catch all cases.
3957 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
3958 and the surrounding thread. */
3959 sym = arg->symtree->n.sym;
3960 decl = gfc_get_symbol_decl (sym);
3961 if (decl == current_function_decl && sym->attr.function
3962 && (sym->result == sym))
3963 decl = gfc_get_fake_result_decl (sym, 0);
3965 len = sym->ts.u.cl->backend_decl;
3966 gcc_assert (len);
3967 break;
3970 /* Otherwise fall through. */
3972 default:
3973 /* Anybody stupid enough to do this deserves inefficient code. */
3974 ss = gfc_walk_expr (arg);
3975 gfc_init_se (&argse, se);
3976 if (ss == gfc_ss_terminator)
3977 gfc_conv_expr (&argse, arg);
3978 else
3979 gfc_conv_expr_descriptor (&argse, arg, ss);
3980 gfc_add_block_to_block (&se->pre, &argse.pre);
3981 gfc_add_block_to_block (&se->post, &argse.post);
3982 len = argse.string_length;
3983 break;
3985 se->expr = convert (type, len);
3988 /* The length of a character string not including trailing blanks. */
3989 static void
3990 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
3992 int kind = expr->value.function.actual->expr->ts.kind;
3993 tree args[2], type, fndecl;
3995 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3996 type = gfc_typenode_for_spec (&expr->ts);
3998 if (kind == 1)
3999 fndecl = gfor_fndecl_string_len_trim;
4000 else if (kind == 4)
4001 fndecl = gfor_fndecl_string_len_trim_char4;
4002 else
4003 gcc_unreachable ();
4005 se->expr = build_call_expr_loc (input_location,
4006 fndecl, 2, args[0], args[1]);
4007 se->expr = convert (type, se->expr);
4011 /* Returns the starting position of a substring within a string. */
4013 static void
4014 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
4015 tree function)
4017 tree logical4_type_node = gfc_get_logical_type (4);
4018 tree type;
4019 tree fndecl;
4020 tree *args;
4021 unsigned int num_args;
4023 args = XALLOCAVEC (tree, 5);
4025 /* Get number of arguments; characters count double due to the
4026 string length argument. Kind= is not passed to the library
4027 and thus ignored. */
4028 if (expr->value.function.actual->next->next->expr == NULL)
4029 num_args = 4;
4030 else
4031 num_args = 5;
4033 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4034 type = gfc_typenode_for_spec (&expr->ts);
4036 if (num_args == 4)
4037 args[4] = build_int_cst (logical4_type_node, 0);
4038 else
4039 args[4] = convert (logical4_type_node, args[4]);
4041 fndecl = build_addr (function, current_function_decl);
4042 se->expr = build_call_array_loc (input_location,
4043 TREE_TYPE (TREE_TYPE (function)), fndecl,
4044 5, args);
4045 se->expr = convert (type, se->expr);
4049 /* The ascii value for a single character. */
4050 static void
4051 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
4053 tree args[2], type, pchartype;
4055 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4056 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
4057 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
4058 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
4059 type = gfc_typenode_for_spec (&expr->ts);
4061 se->expr = build_fold_indirect_ref_loc (input_location,
4062 args[1]);
4063 se->expr = convert (type, se->expr);
4067 /* Intrinsic ISNAN calls __builtin_isnan. */
4069 static void
4070 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
4072 tree arg;
4074 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4075 se->expr = build_call_expr_loc (input_location,
4076 built_in_decls[BUILT_IN_ISNAN], 1, arg);
4077 STRIP_TYPE_NOPS (se->expr);
4078 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
4082 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
4083 their argument against a constant integer value. */
4085 static void
4086 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
4088 tree arg;
4090 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4091 se->expr = fold_build2_loc (input_location, EQ_EXPR,
4092 gfc_typenode_for_spec (&expr->ts),
4093 arg, build_int_cst (TREE_TYPE (arg), value));
4098 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
4100 static void
4101 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
4103 tree tsource;
4104 tree fsource;
4105 tree mask;
4106 tree type;
4107 tree len, len2;
4108 tree *args;
4109 unsigned int num_args;
4111 num_args = gfc_intrinsic_argument_list_length (expr);
4112 args = XALLOCAVEC (tree, num_args);
4114 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4115 if (expr->ts.type != BT_CHARACTER)
4117 tsource = args[0];
4118 fsource = args[1];
4119 mask = args[2];
4121 else
4123 /* We do the same as in the non-character case, but the argument
4124 list is different because of the string length arguments. We
4125 also have to set the string length for the result. */
4126 len = args[0];
4127 tsource = args[1];
4128 len2 = args[2];
4129 fsource = args[3];
4130 mask = args[4];
4132 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
4133 &se->pre);
4134 se->string_length = len;
4136 type = TREE_TYPE (tsource);
4137 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
4138 fold_convert (type, fsource));
4142 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
4144 static void
4145 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
4147 tree args[3], mask, type;
4149 gfc_conv_intrinsic_function_args (se, expr, args, 3);
4150 mask = gfc_evaluate_now (args[2], &se->pre);
4152 type = TREE_TYPE (args[0]);
4153 gcc_assert (TREE_TYPE (args[1]) == type);
4154 gcc_assert (TREE_TYPE (mask) == type);
4156 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
4157 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
4158 fold_build1_loc (input_location, BIT_NOT_EXPR,
4159 type, mask));
4160 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
4161 args[0], args[1]);
4165 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
4166 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
4168 static void
4169 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
4171 tree arg, allones, type, utype, res, cond, bitsize;
4172 int i;
4174 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4175 arg = gfc_evaluate_now (arg, &se->pre);
4177 type = gfc_get_int_type (expr->ts.kind);
4178 utype = unsigned_type_for (type);
4180 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
4181 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
4183 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
4184 build_int_cst (utype, 0));
4186 if (left)
4188 /* Left-justified mask. */
4189 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
4190 bitsize, arg);
4191 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
4192 fold_convert (utype, res));
4194 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
4195 smaller than type width. */
4196 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
4197 build_int_cst (TREE_TYPE (arg), 0));
4198 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
4199 build_int_cst (utype, 0), res);
4201 else
4203 /* Right-justified mask. */
4204 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
4205 fold_convert (utype, arg));
4206 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
4208 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
4209 strictly smaller than type width. */
4210 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4211 arg, bitsize);
4212 res = fold_build3_loc (input_location, COND_EXPR, utype,
4213 cond, allones, res);
4216 se->expr = fold_convert (type, res);
4220 /* FRACTION (s) is translated into frexp (s, &dummy_int). */
4221 static void
4222 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
4224 tree arg, type, tmp, frexp;
4226 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4228 type = gfc_typenode_for_spec (&expr->ts);
4229 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4230 tmp = gfc_create_var (integer_type_node, NULL);
4231 se->expr = build_call_expr_loc (input_location, frexp, 2,
4232 fold_convert (type, arg),
4233 gfc_build_addr_expr (NULL_TREE, tmp));
4234 se->expr = fold_convert (type, se->expr);
4238 /* NEAREST (s, dir) is translated into
4239 tmp = copysign (HUGE_VAL, dir);
4240 return nextafter (s, tmp);
4242 static void
4243 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
4245 tree args[2], type, tmp, nextafter, copysign, huge_val;
4247 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
4248 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
4250 type = gfc_typenode_for_spec (&expr->ts);
4251 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4253 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
4254 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
4255 fold_convert (type, args[1]));
4256 se->expr = build_call_expr_loc (input_location, nextafter, 2,
4257 fold_convert (type, args[0]), tmp);
4258 se->expr = fold_convert (type, se->expr);
4262 /* SPACING (s) is translated into
4263 int e;
4264 if (s == 0)
4265 res = tiny;
4266 else
4268 frexp (s, &e);
4269 e = e - prec;
4270 e = MAX_EXPR (e, emin);
4271 res = scalbn (1., e);
4273 return res;
4275 where prec is the precision of s, gfc_real_kinds[k].digits,
4276 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
4277 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
4279 static void
4280 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
4282 tree arg, type, prec, emin, tiny, res, e;
4283 tree cond, tmp, frexp, scalbn;
4284 int k;
4285 stmtblock_t block;
4287 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
4288 prec = build_int_cst (NULL_TREE, gfc_real_kinds[k].digits);
4289 emin = build_int_cst (NULL_TREE, gfc_real_kinds[k].min_exponent - 1);
4290 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
4292 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4293 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
4295 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4296 arg = gfc_evaluate_now (arg, &se->pre);
4298 type = gfc_typenode_for_spec (&expr->ts);
4299 e = gfc_create_var (integer_type_node, NULL);
4300 res = gfc_create_var (type, NULL);
4303 /* Build the block for s /= 0. */
4304 gfc_start_block (&block);
4305 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
4306 gfc_build_addr_expr (NULL_TREE, e));
4307 gfc_add_expr_to_block (&block, tmp);
4309 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
4310 prec);
4311 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
4312 integer_type_node, tmp, emin));
4314 tmp = build_call_expr_loc (input_location, scalbn, 2,
4315 build_real_from_int_cst (type, integer_one_node), e);
4316 gfc_add_modify (&block, res, tmp);
4318 /* Finish by building the IF statement. */
4319 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
4320 build_real_from_int_cst (type, integer_zero_node));
4321 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
4322 gfc_finish_block (&block));
4324 gfc_add_expr_to_block (&se->pre, tmp);
4325 se->expr = res;
4329 /* RRSPACING (s) is translated into
4330 int e;
4331 real x;
4332 x = fabs (s);
4333 if (x != 0)
4335 frexp (s, &e);
4336 x = scalbn (x, precision - e);
4338 return x;
4340 where precision is gfc_real_kinds[k].digits. */
4342 static void
4343 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
4345 tree arg, type, e, x, cond, stmt, tmp, frexp, scalbn, fabs;
4346 int prec, k;
4347 stmtblock_t block;
4349 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
4350 prec = gfc_real_kinds[k].digits;
4352 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4353 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
4354 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
4356 type = gfc_typenode_for_spec (&expr->ts);
4357 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4358 arg = gfc_evaluate_now (arg, &se->pre);
4360 e = gfc_create_var (integer_type_node, NULL);
4361 x = gfc_create_var (type, NULL);
4362 gfc_add_modify (&se->pre, x,
4363 build_call_expr_loc (input_location, fabs, 1, arg));
4366 gfc_start_block (&block);
4367 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
4368 gfc_build_addr_expr (NULL_TREE, e));
4369 gfc_add_expr_to_block (&block, tmp);
4371 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
4372 build_int_cst (NULL_TREE, prec), e);
4373 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
4374 gfc_add_modify (&block, x, tmp);
4375 stmt = gfc_finish_block (&block);
4377 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, x,
4378 build_real_from_int_cst (type, integer_zero_node));
4379 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
4380 gfc_add_expr_to_block (&se->pre, tmp);
4382 se->expr = fold_convert (type, x);
4386 /* SCALE (s, i) is translated into scalbn (s, i). */
4387 static void
4388 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
4390 tree args[2], type, scalbn;
4392 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
4394 type = gfc_typenode_for_spec (&expr->ts);
4395 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4396 se->expr = build_call_expr_loc (input_location, scalbn, 2,
4397 fold_convert (type, args[0]),
4398 fold_convert (integer_type_node, args[1]));
4399 se->expr = fold_convert (type, se->expr);
4403 /* SET_EXPONENT (s, i) is translated into
4404 scalbn (frexp (s, &dummy_int), i). */
4405 static void
4406 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
4408 tree args[2], type, tmp, frexp, scalbn;
4410 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4411 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
4413 type = gfc_typenode_for_spec (&expr->ts);
4414 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4416 tmp = gfc_create_var (integer_type_node, NULL);
4417 tmp = build_call_expr_loc (input_location, frexp, 2,
4418 fold_convert (type, args[0]),
4419 gfc_build_addr_expr (NULL_TREE, tmp));
4420 se->expr = build_call_expr_loc (input_location, scalbn, 2, tmp,
4421 fold_convert (integer_type_node, args[1]));
4422 se->expr = fold_convert (type, se->expr);
4426 static void
4427 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
4429 gfc_actual_arglist *actual;
4430 tree arg1;
4431 tree type;
4432 tree fncall0;
4433 tree fncall1;
4434 gfc_se argse;
4435 gfc_ss *ss;
4437 gfc_init_se (&argse, NULL);
4438 actual = expr->value.function.actual;
4440 ss = gfc_walk_expr (actual->expr);
4441 gcc_assert (ss != gfc_ss_terminator);
4442 argse.want_pointer = 1;
4443 argse.data_not_needed = 1;
4444 gfc_conv_expr_descriptor (&argse, actual->expr, ss);
4445 gfc_add_block_to_block (&se->pre, &argse.pre);
4446 gfc_add_block_to_block (&se->post, &argse.post);
4447 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
4449 /* Build the call to size0. */
4450 fncall0 = build_call_expr_loc (input_location,
4451 gfor_fndecl_size0, 1, arg1);
4453 actual = actual->next;
4455 if (actual->expr)
4457 gfc_init_se (&argse, NULL);
4458 gfc_conv_expr_type (&argse, actual->expr,
4459 gfc_array_index_type);
4460 gfc_add_block_to_block (&se->pre, &argse.pre);
4462 /* Unusually, for an intrinsic, size does not exclude
4463 an optional arg2, so we must test for it. */
4464 if (actual->expr->expr_type == EXPR_VARIABLE
4465 && actual->expr->symtree->n.sym->attr.dummy
4466 && actual->expr->symtree->n.sym->attr.optional)
4468 tree tmp;
4469 /* Build the call to size1. */
4470 fncall1 = build_call_expr_loc (input_location,
4471 gfor_fndecl_size1, 2,
4472 arg1, argse.expr);
4474 gfc_init_se (&argse, NULL);
4475 argse.want_pointer = 1;
4476 argse.data_not_needed = 1;
4477 gfc_conv_expr (&argse, actual->expr);
4478 gfc_add_block_to_block (&se->pre, &argse.pre);
4479 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
4480 argse.expr, null_pointer_node);
4481 tmp = gfc_evaluate_now (tmp, &se->pre);
4482 se->expr = fold_build3_loc (input_location, COND_EXPR,
4483 pvoid_type_node, tmp, fncall1, fncall0);
4485 else
4487 se->expr = NULL_TREE;
4488 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
4489 gfc_array_index_type,
4490 argse.expr, gfc_index_one_node);
4493 else if (expr->value.function.actual->expr->rank == 1)
4495 argse.expr = gfc_index_zero_node;
4496 se->expr = NULL_TREE;
4498 else
4499 se->expr = fncall0;
4501 if (se->expr == NULL_TREE)
4503 tree ubound, lbound;
4505 arg1 = build_fold_indirect_ref_loc (input_location,
4506 arg1);
4507 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
4508 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
4509 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
4510 gfc_array_index_type, ubound, lbound);
4511 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
4512 gfc_array_index_type,
4513 se->expr, gfc_index_one_node);
4514 se->expr = fold_build2_loc (input_location, MAX_EXPR,
4515 gfc_array_index_type, se->expr,
4516 gfc_index_zero_node);
4519 type = gfc_typenode_for_spec (&expr->ts);
4520 se->expr = convert (type, se->expr);
4524 /* Helper function to compute the size of a character variable,
4525 excluding the terminating null characters. The result has
4526 gfc_array_index_type type. */
4528 static tree
4529 size_of_string_in_bytes (int kind, tree string_length)
4531 tree bytesize;
4532 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
4534 bytesize = build_int_cst (gfc_array_index_type,
4535 gfc_character_kinds[i].bit_size / 8);
4537 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4538 bytesize,
4539 fold_convert (gfc_array_index_type, string_length));
4543 static void
4544 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
4546 gfc_expr *arg;
4547 gfc_ss *ss;
4548 gfc_se argse;
4549 tree source_bytes;
4550 tree type;
4551 tree tmp;
4552 tree lower;
4553 tree upper;
4554 int n;
4556 arg = expr->value.function.actual->expr;
4558 gfc_init_se (&argse, NULL);
4559 ss = gfc_walk_expr (arg);
4561 if (ss == gfc_ss_terminator)
4563 if (arg->ts.type == BT_CLASS)
4564 gfc_add_data_component (arg);
4566 gfc_conv_expr_reference (&argse, arg);
4568 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
4569 argse.expr));
4571 /* Obtain the source word length. */
4572 if (arg->ts.type == BT_CHARACTER)
4573 se->expr = size_of_string_in_bytes (arg->ts.kind,
4574 argse.string_length);
4575 else
4576 se->expr = fold_convert (gfc_array_index_type, size_in_bytes (type));
4578 else
4580 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
4581 argse.want_pointer = 0;
4582 gfc_conv_expr_descriptor (&argse, arg, ss);
4583 type = gfc_get_element_type (TREE_TYPE (argse.expr));
4585 /* Obtain the argument's word length. */
4586 if (arg->ts.type == BT_CHARACTER)
4587 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
4588 else
4589 tmp = fold_convert (gfc_array_index_type,
4590 size_in_bytes (type));
4591 gfc_add_modify (&argse.pre, source_bytes, tmp);
4593 /* Obtain the size of the array in bytes. */
4594 for (n = 0; n < arg->rank; n++)
4596 tree idx;
4597 idx = gfc_rank_cst[n];
4598 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
4599 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
4600 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4601 gfc_array_index_type, upper, lower);
4602 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4603 gfc_array_index_type, tmp, gfc_index_one_node);
4604 tmp = fold_build2_loc (input_location, MULT_EXPR,
4605 gfc_array_index_type, tmp, source_bytes);
4606 gfc_add_modify (&argse.pre, source_bytes, tmp);
4608 se->expr = source_bytes;
4611 gfc_add_block_to_block (&se->pre, &argse.pre);
4615 static void
4616 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
4618 gfc_expr *arg;
4619 gfc_ss *ss;
4620 gfc_se argse,eight;
4621 tree type, result_type, tmp;
4623 arg = expr->value.function.actual->expr;
4624 gfc_init_se (&eight, NULL);
4625 gfc_conv_expr (&eight, gfc_get_int_expr (expr->ts.kind, NULL, 8));
4627 gfc_init_se (&argse, NULL);
4628 ss = gfc_walk_expr (arg);
4629 result_type = gfc_get_int_type (expr->ts.kind);
4631 if (ss == gfc_ss_terminator)
4633 if (arg->ts.type == BT_CLASS)
4635 gfc_add_vptr_component (arg);
4636 gfc_add_size_component (arg);
4637 gfc_conv_expr (&argse, arg);
4638 tmp = fold_convert (result_type, argse.expr);
4639 goto done;
4642 gfc_conv_expr_reference (&argse, arg);
4643 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
4644 argse.expr));
4646 else
4648 argse.want_pointer = 0;
4649 gfc_conv_expr_descriptor (&argse, arg, ss);
4650 type = gfc_get_element_type (TREE_TYPE (argse.expr));
4653 /* Obtain the argument's word length. */
4654 if (arg->ts.type == BT_CHARACTER)
4655 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
4656 else
4657 tmp = fold_convert (result_type, size_in_bytes (type));
4659 done:
4660 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
4661 eight.expr);
4662 gfc_add_block_to_block (&se->pre, &argse.pre);
4666 /* Intrinsic string comparison functions. */
4668 static void
4669 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
4671 tree args[4];
4673 gfc_conv_intrinsic_function_args (se, expr, args, 4);
4675 se->expr
4676 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
4677 expr->value.function.actual->expr->ts.kind,
4678 op);
4679 se->expr = fold_build2_loc (input_location, op,
4680 gfc_typenode_for_spec (&expr->ts), se->expr,
4681 build_int_cst (TREE_TYPE (se->expr), 0));
4684 /* Generate a call to the adjustl/adjustr library function. */
4685 static void
4686 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
4688 tree args[3];
4689 tree len;
4690 tree type;
4691 tree var;
4692 tree tmp;
4694 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
4695 len = args[1];
4697 type = TREE_TYPE (args[2]);
4698 var = gfc_conv_string_tmp (se, type, len);
4699 args[0] = var;
4701 tmp = build_call_expr_loc (input_location,
4702 fndecl, 3, args[0], args[1], args[2]);
4703 gfc_add_expr_to_block (&se->pre, tmp);
4704 se->expr = var;
4705 se->string_length = len;
4709 /* Generate code for the TRANSFER intrinsic:
4710 For scalar results:
4711 DEST = TRANSFER (SOURCE, MOLD)
4712 where:
4713 typeof<DEST> = typeof<MOLD>
4714 and:
4715 MOLD is scalar.
4717 For array results:
4718 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
4719 where:
4720 typeof<DEST> = typeof<MOLD>
4721 and:
4722 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
4723 sizeof (DEST(0) * SIZE). */
4724 static void
4725 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
4727 tree tmp;
4728 tree tmpdecl;
4729 tree ptr;
4730 tree extent;
4731 tree source;
4732 tree source_type;
4733 tree source_bytes;
4734 tree mold_type;
4735 tree dest_word_len;
4736 tree size_words;
4737 tree size_bytes;
4738 tree upper;
4739 tree lower;
4740 tree stmt;
4741 gfc_actual_arglist *arg;
4742 gfc_se argse;
4743 gfc_ss *ss;
4744 gfc_ss_info *info;
4745 stmtblock_t block;
4746 int n;
4747 bool scalar_mold;
4749 info = NULL;
4750 if (se->loop)
4751 info = &se->ss->data.info;
4753 /* Convert SOURCE. The output from this stage is:-
4754 source_bytes = length of the source in bytes
4755 source = pointer to the source data. */
4756 arg = expr->value.function.actual;
4758 /* Ensure double transfer through LOGICAL preserves all
4759 the needed bits. */
4760 if (arg->expr->expr_type == EXPR_FUNCTION
4761 && arg->expr->value.function.esym == NULL
4762 && arg->expr->value.function.isym != NULL
4763 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
4764 && arg->expr->ts.type == BT_LOGICAL
4765 && expr->ts.type != arg->expr->ts.type)
4766 arg->expr->value.function.name = "__transfer_in_transfer";
4768 gfc_init_se (&argse, NULL);
4769 ss = gfc_walk_expr (arg->expr);
4771 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
4773 /* Obtain the pointer to source and the length of source in bytes. */
4774 if (ss == gfc_ss_terminator)
4776 gfc_conv_expr_reference (&argse, arg->expr);
4777 source = argse.expr;
4779 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
4780 argse.expr));
4782 /* Obtain the source word length. */
4783 if (arg->expr->ts.type == BT_CHARACTER)
4784 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
4785 argse.string_length);
4786 else
4787 tmp = fold_convert (gfc_array_index_type,
4788 size_in_bytes (source_type));
4790 else
4792 argse.want_pointer = 0;
4793 gfc_conv_expr_descriptor (&argse, arg->expr, ss);
4794 source = gfc_conv_descriptor_data_get (argse.expr);
4795 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
4797 /* Repack the source if not a full variable array. */
4798 if (arg->expr->expr_type == EXPR_VARIABLE
4799 && arg->expr->ref->u.ar.type != AR_FULL)
4801 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
4803 if (gfc_option.warn_array_temp)
4804 gfc_warning ("Creating array temporary at %L", &expr->where);
4806 source = build_call_expr_loc (input_location,
4807 gfor_fndecl_in_pack, 1, tmp);
4808 source = gfc_evaluate_now (source, &argse.pre);
4810 /* Free the temporary. */
4811 gfc_start_block (&block);
4812 tmp = gfc_call_free (convert (pvoid_type_node, source));
4813 gfc_add_expr_to_block (&block, tmp);
4814 stmt = gfc_finish_block (&block);
4816 /* Clean up if it was repacked. */
4817 gfc_init_block (&block);
4818 tmp = gfc_conv_array_data (argse.expr);
4819 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
4820 source, tmp);
4821 tmp = build3_v (COND_EXPR, tmp, stmt,
4822 build_empty_stmt (input_location));
4823 gfc_add_expr_to_block (&block, tmp);
4824 gfc_add_block_to_block (&block, &se->post);
4825 gfc_init_block (&se->post);
4826 gfc_add_block_to_block (&se->post, &block);
4829 /* Obtain the source word length. */
4830 if (arg->expr->ts.type == BT_CHARACTER)
4831 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
4832 argse.string_length);
4833 else
4834 tmp = fold_convert (gfc_array_index_type,
4835 size_in_bytes (source_type));
4837 /* Obtain the size of the array in bytes. */
4838 extent = gfc_create_var (gfc_array_index_type, NULL);
4839 for (n = 0; n < arg->expr->rank; n++)
4841 tree idx;
4842 idx = gfc_rank_cst[n];
4843 gfc_add_modify (&argse.pre, source_bytes, tmp);
4844 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
4845 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
4846 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4847 gfc_array_index_type, upper, lower);
4848 gfc_add_modify (&argse.pre, extent, tmp);
4849 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4850 gfc_array_index_type, extent,
4851 gfc_index_one_node);
4852 tmp = fold_build2_loc (input_location, MULT_EXPR,
4853 gfc_array_index_type, tmp, source_bytes);
4857 gfc_add_modify (&argse.pre, source_bytes, tmp);
4858 gfc_add_block_to_block (&se->pre, &argse.pre);
4859 gfc_add_block_to_block (&se->post, &argse.post);
4861 /* Now convert MOLD. The outputs are:
4862 mold_type = the TREE type of MOLD
4863 dest_word_len = destination word length in bytes. */
4864 arg = arg->next;
4866 gfc_init_se (&argse, NULL);
4867 ss = gfc_walk_expr (arg->expr);
4869 scalar_mold = arg->expr->rank == 0;
4871 if (ss == gfc_ss_terminator)
4873 gfc_conv_expr_reference (&argse, arg->expr);
4874 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
4875 argse.expr));
4877 else
4879 gfc_init_se (&argse, NULL);
4880 argse.want_pointer = 0;
4881 gfc_conv_expr_descriptor (&argse, arg->expr, ss);
4882 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
4885 gfc_add_block_to_block (&se->pre, &argse.pre);
4886 gfc_add_block_to_block (&se->post, &argse.post);
4888 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
4890 /* If this TRANSFER is nested in another TRANSFER, use a type
4891 that preserves all bits. */
4892 if (arg->expr->ts.type == BT_LOGICAL)
4893 mold_type = gfc_get_int_type (arg->expr->ts.kind);
4896 if (arg->expr->ts.type == BT_CHARACTER)
4898 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
4899 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
4901 else
4902 tmp = fold_convert (gfc_array_index_type,
4903 size_in_bytes (mold_type));
4905 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
4906 gfc_add_modify (&se->pre, dest_word_len, tmp);
4908 /* Finally convert SIZE, if it is present. */
4909 arg = arg->next;
4910 size_words = gfc_create_var (gfc_array_index_type, NULL);
4912 if (arg->expr)
4914 gfc_init_se (&argse, NULL);
4915 gfc_conv_expr_reference (&argse, arg->expr);
4916 tmp = convert (gfc_array_index_type,
4917 build_fold_indirect_ref_loc (input_location,
4918 argse.expr));
4919 gfc_add_block_to_block (&se->pre, &argse.pre);
4920 gfc_add_block_to_block (&se->post, &argse.post);
4922 else
4923 tmp = NULL_TREE;
4925 /* Separate array and scalar results. */
4926 if (scalar_mold && tmp == NULL_TREE)
4927 goto scalar_transfer;
4929 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
4930 if (tmp != NULL_TREE)
4931 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4932 tmp, dest_word_len);
4933 else
4934 tmp = source_bytes;
4936 gfc_add_modify (&se->pre, size_bytes, tmp);
4937 gfc_add_modify (&se->pre, size_words,
4938 fold_build2_loc (input_location, CEIL_DIV_EXPR,
4939 gfc_array_index_type,
4940 size_bytes, dest_word_len));
4942 /* Evaluate the bounds of the result. If the loop range exists, we have
4943 to check if it is too large. If so, we modify loop->to be consistent
4944 with min(size, size(source)). Otherwise, size is made consistent with
4945 the loop range, so that the right number of bytes is transferred.*/
4946 n = se->loop->order[0];
4947 if (se->loop->to[n] != NULL_TREE)
4949 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4950 se->loop->to[n], se->loop->from[n]);
4951 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4952 tmp, gfc_index_one_node);
4953 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
4954 tmp, size_words);
4955 gfc_add_modify (&se->pre, size_words, tmp);
4956 gfc_add_modify (&se->pre, size_bytes,
4957 fold_build2_loc (input_location, MULT_EXPR,
4958 gfc_array_index_type,
4959 size_words, dest_word_len));
4960 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4961 size_words, se->loop->from[n]);
4962 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4963 upper, gfc_index_one_node);
4965 else
4967 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4968 size_words, gfc_index_one_node);
4969 se->loop->from[n] = gfc_index_zero_node;
4972 se->loop->to[n] = upper;
4974 /* Build a destination descriptor, using the pointer, source, as the
4975 data field. */
4976 gfc_trans_create_temp_array (&se->pre, &se->post, se->loop,
4977 info, mold_type, NULL_TREE, false, true, false,
4978 &expr->where);
4980 /* Cast the pointer to the result. */
4981 tmp = gfc_conv_descriptor_data_get (info->descriptor);
4982 tmp = fold_convert (pvoid_type_node, tmp);
4984 /* Use memcpy to do the transfer. */
4985 tmp = build_call_expr_loc (input_location,
4986 built_in_decls[BUILT_IN_MEMCPY],
4988 tmp,
4989 fold_convert (pvoid_type_node, source),
4990 fold_build2_loc (input_location, MIN_EXPR,
4991 gfc_array_index_type,
4992 size_bytes, source_bytes));
4993 gfc_add_expr_to_block (&se->pre, tmp);
4995 se->expr = info->descriptor;
4996 if (expr->ts.type == BT_CHARACTER)
4997 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
4999 return;
5001 /* Deal with scalar results. */
5002 scalar_transfer:
5003 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
5004 dest_word_len, source_bytes);
5005 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
5006 extent, gfc_index_zero_node);
5008 if (expr->ts.type == BT_CHARACTER)
5010 tree direct;
5011 tree indirect;
5013 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
5014 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
5015 "transfer");
5017 /* If source is longer than the destination, use a pointer to
5018 the source directly. */
5019 gfc_init_block (&block);
5020 gfc_add_modify (&block, tmpdecl, ptr);
5021 direct = gfc_finish_block (&block);
5023 /* Otherwise, allocate a string with the length of the destination
5024 and copy the source into it. */
5025 gfc_init_block (&block);
5026 tmp = gfc_get_pchar_type (expr->ts.kind);
5027 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
5028 gfc_add_modify (&block, tmpdecl,
5029 fold_convert (TREE_TYPE (ptr), tmp));
5030 tmp = build_call_expr_loc (input_location,
5031 built_in_decls[BUILT_IN_MEMCPY], 3,
5032 fold_convert (pvoid_type_node, tmpdecl),
5033 fold_convert (pvoid_type_node, ptr),
5034 extent);
5035 gfc_add_expr_to_block (&block, tmp);
5036 indirect = gfc_finish_block (&block);
5038 /* Wrap it up with the condition. */
5039 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
5040 dest_word_len, source_bytes);
5041 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
5042 gfc_add_expr_to_block (&se->pre, tmp);
5044 se->expr = tmpdecl;
5045 se->string_length = dest_word_len;
5047 else
5049 tmpdecl = gfc_create_var (mold_type, "transfer");
5051 ptr = convert (build_pointer_type (mold_type), source);
5053 /* Use memcpy to do the transfer. */
5054 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
5055 tmp = build_call_expr_loc (input_location,
5056 built_in_decls[BUILT_IN_MEMCPY], 3,
5057 fold_convert (pvoid_type_node, tmp),
5058 fold_convert (pvoid_type_node, ptr),
5059 extent);
5060 gfc_add_expr_to_block (&se->pre, tmp);
5062 se->expr = tmpdecl;
5067 /* Generate code for the ALLOCATED intrinsic.
5068 Generate inline code that directly check the address of the argument. */
5070 static void
5071 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
5073 gfc_actual_arglist *arg1;
5074 gfc_se arg1se;
5075 gfc_ss *ss1;
5076 tree tmp;
5078 gfc_init_se (&arg1se, NULL);
5079 arg1 = expr->value.function.actual;
5080 ss1 = gfc_walk_expr (arg1->expr);
5082 if (ss1 == gfc_ss_terminator)
5084 /* Allocatable scalar. */
5085 arg1se.want_pointer = 1;
5086 if (arg1->expr->ts.type == BT_CLASS)
5087 gfc_add_data_component (arg1->expr);
5088 gfc_conv_expr (&arg1se, arg1->expr);
5089 tmp = arg1se.expr;
5091 else
5093 /* Allocatable array. */
5094 arg1se.descriptor_only = 1;
5095 gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1);
5096 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
5099 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
5100 fold_convert (TREE_TYPE (tmp), null_pointer_node));
5101 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
5105 /* Generate code for the ASSOCIATED intrinsic.
5106 If both POINTER and TARGET are arrays, generate a call to library function
5107 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
5108 In other cases, generate inline code that directly compare the address of
5109 POINTER with the address of TARGET. */
5111 static void
5112 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
5114 gfc_actual_arglist *arg1;
5115 gfc_actual_arglist *arg2;
5116 gfc_se arg1se;
5117 gfc_se arg2se;
5118 tree tmp2;
5119 tree tmp;
5120 tree nonzero_charlen;
5121 tree nonzero_arraylen;
5122 gfc_ss *ss1, *ss2;
5124 gfc_init_se (&arg1se, NULL);
5125 gfc_init_se (&arg2se, NULL);
5126 arg1 = expr->value.function.actual;
5127 if (arg1->expr->ts.type == BT_CLASS)
5128 gfc_add_data_component (arg1->expr);
5129 arg2 = arg1->next;
5130 ss1 = gfc_walk_expr (arg1->expr);
5132 if (!arg2->expr)
5134 /* No optional target. */
5135 if (ss1 == gfc_ss_terminator)
5137 /* A pointer to a scalar. */
5138 arg1se.want_pointer = 1;
5139 gfc_conv_expr (&arg1se, arg1->expr);
5140 tmp2 = arg1se.expr;
5142 else
5144 /* A pointer to an array. */
5145 gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1);
5146 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
5148 gfc_add_block_to_block (&se->pre, &arg1se.pre);
5149 gfc_add_block_to_block (&se->post, &arg1se.post);
5150 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp2,
5151 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
5152 se->expr = tmp;
5154 else
5156 /* An optional target. */
5157 if (arg2->expr->ts.type == BT_CLASS)
5158 gfc_add_data_component (arg2->expr);
5159 ss2 = gfc_walk_expr (arg2->expr);
5161 nonzero_charlen = NULL_TREE;
5162 if (arg1->expr->ts.type == BT_CHARACTER)
5163 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
5164 boolean_type_node,
5165 arg1->expr->ts.u.cl->backend_decl,
5166 integer_zero_node);
5168 if (ss1 == gfc_ss_terminator)
5170 /* A pointer to a scalar. */
5171 gcc_assert (ss2 == gfc_ss_terminator);
5172 arg1se.want_pointer = 1;
5173 gfc_conv_expr (&arg1se, arg1->expr);
5174 arg2se.want_pointer = 1;
5175 gfc_conv_expr (&arg2se, arg2->expr);
5176 gfc_add_block_to_block (&se->pre, &arg1se.pre);
5177 gfc_add_block_to_block (&se->post, &arg1se.post);
5178 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5179 arg1se.expr, arg2se.expr);
5180 tmp2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5181 arg1se.expr, null_pointer_node);
5182 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5183 boolean_type_node, tmp, tmp2);
5185 else
5187 /* An array pointer of zero length is not associated if target is
5188 present. */
5189 arg1se.descriptor_only = 1;
5190 gfc_conv_expr_lhs (&arg1se, arg1->expr);
5191 tmp = gfc_conv_descriptor_stride_get (arg1se.expr,
5192 gfc_rank_cst[arg1->expr->rank - 1]);
5193 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
5194 boolean_type_node, tmp,
5195 build_int_cst (TREE_TYPE (tmp), 0));
5197 /* A pointer to an array, call library function _gfor_associated. */
5198 gcc_assert (ss2 != gfc_ss_terminator);
5199 arg1se.want_pointer = 1;
5200 gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1);
5202 arg2se.want_pointer = 1;
5203 gfc_conv_expr_descriptor (&arg2se, arg2->expr, ss2);
5204 gfc_add_block_to_block (&se->pre, &arg2se.pre);
5205 gfc_add_block_to_block (&se->post, &arg2se.post);
5206 se->expr = build_call_expr_loc (input_location,
5207 gfor_fndecl_associated, 2,
5208 arg1se.expr, arg2se.expr);
5209 se->expr = convert (boolean_type_node, se->expr);
5210 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5211 boolean_type_node, se->expr,
5212 nonzero_arraylen);
5215 /* If target is present zero character length pointers cannot
5216 be associated. */
5217 if (nonzero_charlen != NULL_TREE)
5218 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5219 boolean_type_node,
5220 se->expr, nonzero_charlen);
5223 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
5227 /* Generate code for the SAME_TYPE_AS intrinsic.
5228 Generate inline code that directly checks the vindices. */
5230 static void
5231 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
5233 gfc_expr *a, *b;
5234 gfc_se se1, se2;
5235 tree tmp;
5237 gfc_init_se (&se1, NULL);
5238 gfc_init_se (&se2, NULL);
5240 a = expr->value.function.actual->expr;
5241 b = expr->value.function.actual->next->expr;
5243 if (a->ts.type == BT_CLASS)
5245 gfc_add_vptr_component (a);
5246 gfc_add_hash_component (a);
5248 else if (a->ts.type == BT_DERIVED)
5249 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
5250 a->ts.u.derived->hash_value);
5252 if (b->ts.type == BT_CLASS)
5254 gfc_add_vptr_component (b);
5255 gfc_add_hash_component (b);
5257 else if (b->ts.type == BT_DERIVED)
5258 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
5259 b->ts.u.derived->hash_value);
5261 gfc_conv_expr (&se1, a);
5262 gfc_conv_expr (&se2, b);
5264 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5265 se1.expr, fold_convert (TREE_TYPE (se1.expr), se2.expr));
5266 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
5270 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
5272 static void
5273 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
5275 tree args[2];
5277 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5278 se->expr = build_call_expr_loc (input_location,
5279 gfor_fndecl_sc_kind, 2, args[0], args[1]);
5280 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
5284 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
5286 static void
5287 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
5289 tree arg, type;
5291 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
5293 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
5294 type = gfc_get_int_type (4);
5295 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
5297 /* Convert it to the required type. */
5298 type = gfc_typenode_for_spec (&expr->ts);
5299 se->expr = build_call_expr_loc (input_location,
5300 gfor_fndecl_si_kind, 1, arg);
5301 se->expr = fold_convert (type, se->expr);
5305 /* Generate code for SELECTED_REAL_KIND (P, R) intrinsic function. */
5307 static void
5308 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
5310 gfc_actual_arglist *actual;
5311 tree type;
5312 gfc_se argse;
5313 VEC(tree,gc) *args = NULL;
5315 for (actual = expr->value.function.actual; actual; actual = actual->next)
5317 gfc_init_se (&argse, se);
5319 /* Pass a NULL pointer for an absent arg. */
5320 if (actual->expr == NULL)
5321 argse.expr = null_pointer_node;
5322 else
5324 gfc_typespec ts;
5325 gfc_clear_ts (&ts);
5327 if (actual->expr->ts.kind != gfc_c_int_kind)
5329 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
5330 ts.type = BT_INTEGER;
5331 ts.kind = gfc_c_int_kind;
5332 gfc_convert_type (actual->expr, &ts, 2);
5334 gfc_conv_expr_reference (&argse, actual->expr);
5337 gfc_add_block_to_block (&se->pre, &argse.pre);
5338 gfc_add_block_to_block (&se->post, &argse.post);
5339 VEC_safe_push (tree, gc, args, argse.expr);
5342 /* Convert it to the required type. */
5343 type = gfc_typenode_for_spec (&expr->ts);
5344 se->expr = build_call_expr_loc_vec (input_location,
5345 gfor_fndecl_sr_kind, args);
5346 se->expr = fold_convert (type, se->expr);
5350 /* Generate code for TRIM (A) intrinsic function. */
5352 static void
5353 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
5355 tree var;
5356 tree len;
5357 tree addr;
5358 tree tmp;
5359 tree cond;
5360 tree fndecl;
5361 tree function;
5362 tree *args;
5363 unsigned int num_args;
5365 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
5366 args = XALLOCAVEC (tree, num_args);
5368 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
5369 addr = gfc_build_addr_expr (ppvoid_type_node, var);
5370 len = gfc_create_var (gfc_charlen_type_node, "len");
5372 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
5373 args[0] = gfc_build_addr_expr (NULL_TREE, len);
5374 args[1] = addr;
5376 if (expr->ts.kind == 1)
5377 function = gfor_fndecl_string_trim;
5378 else if (expr->ts.kind == 4)
5379 function = gfor_fndecl_string_trim_char4;
5380 else
5381 gcc_unreachable ();
5383 fndecl = build_addr (function, current_function_decl);
5384 tmp = build_call_array_loc (input_location,
5385 TREE_TYPE (TREE_TYPE (function)), fndecl,
5386 num_args, args);
5387 gfc_add_expr_to_block (&se->pre, tmp);
5389 /* Free the temporary afterwards, if necessary. */
5390 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
5391 len, build_int_cst (TREE_TYPE (len), 0));
5392 tmp = gfc_call_free (var);
5393 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
5394 gfc_add_expr_to_block (&se->post, tmp);
5396 se->expr = var;
5397 se->string_length = len;
5401 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
5403 static void
5404 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
5406 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
5407 tree type, cond, tmp, count, exit_label, n, max, largest;
5408 tree size;
5409 stmtblock_t block, body;
5410 int i;
5412 /* We store in charsize the size of a character. */
5413 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
5414 size = build_int_cst (size_type_node, gfc_character_kinds[i].bit_size / 8);
5416 /* Get the arguments. */
5417 gfc_conv_intrinsic_function_args (se, expr, args, 3);
5418 slen = fold_convert (size_type_node, gfc_evaluate_now (args[0], &se->pre));
5419 src = args[1];
5420 ncopies = gfc_evaluate_now (args[2], &se->pre);
5421 ncopies_type = TREE_TYPE (ncopies);
5423 /* Check that NCOPIES is not negative. */
5424 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, ncopies,
5425 build_int_cst (ncopies_type, 0));
5426 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
5427 "Argument NCOPIES of REPEAT intrinsic is negative "
5428 "(its value is %lld)",
5429 fold_convert (long_integer_type_node, ncopies));
5431 /* If the source length is zero, any non negative value of NCOPIES
5432 is valid, and nothing happens. */
5433 n = gfc_create_var (ncopies_type, "ncopies");
5434 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
5435 build_int_cst (size_type_node, 0));
5436 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
5437 build_int_cst (ncopies_type, 0), ncopies);
5438 gfc_add_modify (&se->pre, n, tmp);
5439 ncopies = n;
5441 /* Check that ncopies is not too large: ncopies should be less than
5442 (or equal to) MAX / slen, where MAX is the maximal integer of
5443 the gfc_charlen_type_node type. If slen == 0, we need a special
5444 case to avoid the division by zero. */
5445 i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
5446 max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_charlen_int_kind);
5447 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node,
5448 fold_convert (size_type_node, max), slen);
5449 largest = TYPE_PRECISION (size_type_node) > TYPE_PRECISION (ncopies_type)
5450 ? size_type_node : ncopies_type;
5451 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
5452 fold_convert (largest, ncopies),
5453 fold_convert (largest, max));
5454 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
5455 build_int_cst (size_type_node, 0));
5456 cond = fold_build3_loc (input_location, COND_EXPR, boolean_type_node, tmp,
5457 boolean_false_node, cond);
5458 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
5459 "Argument NCOPIES of REPEAT intrinsic is too large");
5461 /* Compute the destination length. */
5462 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
5463 fold_convert (gfc_charlen_type_node, slen),
5464 fold_convert (gfc_charlen_type_node, ncopies));
5465 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
5466 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
5468 /* Generate the code to do the repeat operation:
5469 for (i = 0; i < ncopies; i++)
5470 memmove (dest + (i * slen * size), src, slen*size); */
5471 gfc_start_block (&block);
5472 count = gfc_create_var (ncopies_type, "count");
5473 gfc_add_modify (&block, count, build_int_cst (ncopies_type, 0));
5474 exit_label = gfc_build_label_decl (NULL_TREE);
5476 /* Start the loop body. */
5477 gfc_start_block (&body);
5479 /* Exit the loop if count >= ncopies. */
5480 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, count,
5481 ncopies);
5482 tmp = build1_v (GOTO_EXPR, exit_label);
5483 TREE_USED (exit_label) = 1;
5484 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
5485 build_empty_stmt (input_location));
5486 gfc_add_expr_to_block (&body, tmp);
5488 /* Call memmove (dest + (i*slen*size), src, slen*size). */
5489 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
5490 fold_convert (gfc_charlen_type_node, slen),
5491 fold_convert (gfc_charlen_type_node, count));
5492 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
5493 tmp, fold_convert (gfc_charlen_type_node, size));
5494 tmp = fold_build2_loc (input_location, POINTER_PLUS_EXPR, pvoid_type_node,
5495 fold_convert (pvoid_type_node, dest),
5496 fold_convert (sizetype, tmp));
5497 tmp = build_call_expr_loc (input_location,
5498 built_in_decls[BUILT_IN_MEMMOVE], 3, tmp, src,
5499 fold_build2_loc (input_location, MULT_EXPR,
5500 size_type_node, slen,
5501 fold_convert (size_type_node,
5502 size)));
5503 gfc_add_expr_to_block (&body, tmp);
5505 /* Increment count. */
5506 tmp = fold_build2_loc (input_location, PLUS_EXPR, ncopies_type,
5507 count, build_int_cst (TREE_TYPE (count), 1));
5508 gfc_add_modify (&body, count, tmp);
5510 /* Build the loop. */
5511 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
5512 gfc_add_expr_to_block (&block, tmp);
5514 /* Add the exit label. */
5515 tmp = build1_v (LABEL_EXPR, exit_label);
5516 gfc_add_expr_to_block (&block, tmp);
5518 /* Finish the block. */
5519 tmp = gfc_finish_block (&block);
5520 gfc_add_expr_to_block (&se->pre, tmp);
5522 /* Set the result value. */
5523 se->expr = dest;
5524 se->string_length = dlen;
5528 /* Generate code for the IARGC intrinsic. */
5530 static void
5531 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
5533 tree tmp;
5534 tree fndecl;
5535 tree type;
5537 /* Call the library function. This always returns an INTEGER(4). */
5538 fndecl = gfor_fndecl_iargc;
5539 tmp = build_call_expr_loc (input_location,
5540 fndecl, 0);
5542 /* Convert it to the required type. */
5543 type = gfc_typenode_for_spec (&expr->ts);
5544 tmp = fold_convert (type, tmp);
5546 se->expr = tmp;
5550 /* The loc intrinsic returns the address of its argument as
5551 gfc_index_integer_kind integer. */
5553 static void
5554 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
5556 tree temp_var;
5557 gfc_expr *arg_expr;
5558 gfc_ss *ss;
5560 gcc_assert (!se->ss);
5562 arg_expr = expr->value.function.actual->expr;
5563 ss = gfc_walk_expr (arg_expr);
5564 if (ss == gfc_ss_terminator)
5565 gfc_conv_expr_reference (se, arg_expr);
5566 else
5567 gfc_conv_array_parameter (se, arg_expr, ss, true, NULL, NULL, NULL);
5568 se->expr= convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
5570 /* Create a temporary variable for loc return value. Without this,
5571 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
5572 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
5573 gfc_add_modify (&se->pre, temp_var, se->expr);
5574 se->expr = temp_var;
5577 /* Generate code for an intrinsic function. Some map directly to library
5578 calls, others get special handling. In some cases the name of the function
5579 used depends on the type specifiers. */
5581 void
5582 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
5584 const char *name;
5585 int lib, kind;
5586 tree fndecl;
5588 name = &expr->value.function.name[2];
5590 if (expr->rank > 0)
5592 lib = gfc_is_intrinsic_libcall (expr);
5593 if (lib != 0)
5595 if (lib == 1)
5596 se->ignore_optional = 1;
5598 switch (expr->value.function.isym->id)
5600 case GFC_ISYM_EOSHIFT:
5601 case GFC_ISYM_PACK:
5602 case GFC_ISYM_RESHAPE:
5603 /* For all of those the first argument specifies the type and the
5604 third is optional. */
5605 conv_generic_with_optional_char_arg (se, expr, 1, 3);
5606 break;
5608 default:
5609 gfc_conv_intrinsic_funcall (se, expr);
5610 break;
5613 return;
5617 switch (expr->value.function.isym->id)
5619 case GFC_ISYM_NONE:
5620 gcc_unreachable ();
5622 case GFC_ISYM_REPEAT:
5623 gfc_conv_intrinsic_repeat (se, expr);
5624 break;
5626 case GFC_ISYM_TRIM:
5627 gfc_conv_intrinsic_trim (se, expr);
5628 break;
5630 case GFC_ISYM_SC_KIND:
5631 gfc_conv_intrinsic_sc_kind (se, expr);
5632 break;
5634 case GFC_ISYM_SI_KIND:
5635 gfc_conv_intrinsic_si_kind (se, expr);
5636 break;
5638 case GFC_ISYM_SR_KIND:
5639 gfc_conv_intrinsic_sr_kind (se, expr);
5640 break;
5642 case GFC_ISYM_EXPONENT:
5643 gfc_conv_intrinsic_exponent (se, expr);
5644 break;
5646 case GFC_ISYM_SCAN:
5647 kind = expr->value.function.actual->expr->ts.kind;
5648 if (kind == 1)
5649 fndecl = gfor_fndecl_string_scan;
5650 else if (kind == 4)
5651 fndecl = gfor_fndecl_string_scan_char4;
5652 else
5653 gcc_unreachable ();
5655 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
5656 break;
5658 case GFC_ISYM_VERIFY:
5659 kind = expr->value.function.actual->expr->ts.kind;
5660 if (kind == 1)
5661 fndecl = gfor_fndecl_string_verify;
5662 else if (kind == 4)
5663 fndecl = gfor_fndecl_string_verify_char4;
5664 else
5665 gcc_unreachable ();
5667 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
5668 break;
5670 case GFC_ISYM_ALLOCATED:
5671 gfc_conv_allocated (se, expr);
5672 break;
5674 case GFC_ISYM_ASSOCIATED:
5675 gfc_conv_associated(se, expr);
5676 break;
5678 case GFC_ISYM_SAME_TYPE_AS:
5679 gfc_conv_same_type_as (se, expr);
5680 break;
5682 case GFC_ISYM_ABS:
5683 gfc_conv_intrinsic_abs (se, expr);
5684 break;
5686 case GFC_ISYM_ADJUSTL:
5687 if (expr->ts.kind == 1)
5688 fndecl = gfor_fndecl_adjustl;
5689 else if (expr->ts.kind == 4)
5690 fndecl = gfor_fndecl_adjustl_char4;
5691 else
5692 gcc_unreachable ();
5694 gfc_conv_intrinsic_adjust (se, expr, fndecl);
5695 break;
5697 case GFC_ISYM_ADJUSTR:
5698 if (expr->ts.kind == 1)
5699 fndecl = gfor_fndecl_adjustr;
5700 else if (expr->ts.kind == 4)
5701 fndecl = gfor_fndecl_adjustr_char4;
5702 else
5703 gcc_unreachable ();
5705 gfc_conv_intrinsic_adjust (se, expr, fndecl);
5706 break;
5708 case GFC_ISYM_AIMAG:
5709 gfc_conv_intrinsic_imagpart (se, expr);
5710 break;
5712 case GFC_ISYM_AINT:
5713 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
5714 break;
5716 case GFC_ISYM_ALL:
5717 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
5718 break;
5720 case GFC_ISYM_ANINT:
5721 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
5722 break;
5724 case GFC_ISYM_AND:
5725 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
5726 break;
5728 case GFC_ISYM_ANY:
5729 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
5730 break;
5732 case GFC_ISYM_BTEST:
5733 gfc_conv_intrinsic_btest (se, expr);
5734 break;
5736 case GFC_ISYM_BGE:
5737 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
5738 break;
5740 case GFC_ISYM_BGT:
5741 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
5742 break;
5744 case GFC_ISYM_BLE:
5745 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
5746 break;
5748 case GFC_ISYM_BLT:
5749 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
5750 break;
5752 case GFC_ISYM_ACHAR:
5753 case GFC_ISYM_CHAR:
5754 gfc_conv_intrinsic_char (se, expr);
5755 break;
5757 case GFC_ISYM_CONVERSION:
5758 case GFC_ISYM_REAL:
5759 case GFC_ISYM_LOGICAL:
5760 case GFC_ISYM_DBLE:
5761 gfc_conv_intrinsic_conversion (se, expr);
5762 break;
5764 /* Integer conversions are handled separately to make sure we get the
5765 correct rounding mode. */
5766 case GFC_ISYM_INT:
5767 case GFC_ISYM_INT2:
5768 case GFC_ISYM_INT8:
5769 case GFC_ISYM_LONG:
5770 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
5771 break;
5773 case GFC_ISYM_NINT:
5774 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
5775 break;
5777 case GFC_ISYM_CEILING:
5778 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
5779 break;
5781 case GFC_ISYM_FLOOR:
5782 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
5783 break;
5785 case GFC_ISYM_MOD:
5786 gfc_conv_intrinsic_mod (se, expr, 0);
5787 break;
5789 case GFC_ISYM_MODULO:
5790 gfc_conv_intrinsic_mod (se, expr, 1);
5791 break;
5793 case GFC_ISYM_CMPLX:
5794 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
5795 break;
5797 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
5798 gfc_conv_intrinsic_iargc (se, expr);
5799 break;
5801 case GFC_ISYM_COMPLEX:
5802 gfc_conv_intrinsic_cmplx (se, expr, 1);
5803 break;
5805 case GFC_ISYM_CONJG:
5806 gfc_conv_intrinsic_conjg (se, expr);
5807 break;
5809 case GFC_ISYM_COUNT:
5810 gfc_conv_intrinsic_count (se, expr);
5811 break;
5813 case GFC_ISYM_CTIME:
5814 gfc_conv_intrinsic_ctime (se, expr);
5815 break;
5817 case GFC_ISYM_DIM:
5818 gfc_conv_intrinsic_dim (se, expr);
5819 break;
5821 case GFC_ISYM_DOT_PRODUCT:
5822 gfc_conv_intrinsic_dot_product (se, expr);
5823 break;
5825 case GFC_ISYM_DPROD:
5826 gfc_conv_intrinsic_dprod (se, expr);
5827 break;
5829 case GFC_ISYM_DSHIFTL:
5830 gfc_conv_intrinsic_dshift (se, expr, true);
5831 break;
5833 case GFC_ISYM_DSHIFTR:
5834 gfc_conv_intrinsic_dshift (se, expr, false);
5835 break;
5837 case GFC_ISYM_FDATE:
5838 gfc_conv_intrinsic_fdate (se, expr);
5839 break;
5841 case GFC_ISYM_FRACTION:
5842 gfc_conv_intrinsic_fraction (se, expr);
5843 break;
5845 case GFC_ISYM_IALL:
5846 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
5847 break;
5849 case GFC_ISYM_IAND:
5850 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
5851 break;
5853 case GFC_ISYM_IANY:
5854 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
5855 break;
5857 case GFC_ISYM_IBCLR:
5858 gfc_conv_intrinsic_singlebitop (se, expr, 0);
5859 break;
5861 case GFC_ISYM_IBITS:
5862 gfc_conv_intrinsic_ibits (se, expr);
5863 break;
5865 case GFC_ISYM_IBSET:
5866 gfc_conv_intrinsic_singlebitop (se, expr, 1);
5867 break;
5869 case GFC_ISYM_IACHAR:
5870 case GFC_ISYM_ICHAR:
5871 /* We assume ASCII character sequence. */
5872 gfc_conv_intrinsic_ichar (se, expr);
5873 break;
5875 case GFC_ISYM_IARGC:
5876 gfc_conv_intrinsic_iargc (se, expr);
5877 break;
5879 case GFC_ISYM_IEOR:
5880 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
5881 break;
5883 case GFC_ISYM_INDEX:
5884 kind = expr->value.function.actual->expr->ts.kind;
5885 if (kind == 1)
5886 fndecl = gfor_fndecl_string_index;
5887 else if (kind == 4)
5888 fndecl = gfor_fndecl_string_index_char4;
5889 else
5890 gcc_unreachable ();
5892 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
5893 break;
5895 case GFC_ISYM_IOR:
5896 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
5897 break;
5899 case GFC_ISYM_IPARITY:
5900 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
5901 break;
5903 case GFC_ISYM_IS_IOSTAT_END:
5904 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
5905 break;
5907 case GFC_ISYM_IS_IOSTAT_EOR:
5908 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
5909 break;
5911 case GFC_ISYM_ISNAN:
5912 gfc_conv_intrinsic_isnan (se, expr);
5913 break;
5915 case GFC_ISYM_LSHIFT:
5916 gfc_conv_intrinsic_shift (se, expr, false, false);
5917 break;
5919 case GFC_ISYM_RSHIFT:
5920 gfc_conv_intrinsic_shift (se, expr, true, true);
5921 break;
5923 case GFC_ISYM_SHIFTA:
5924 gfc_conv_intrinsic_shift (se, expr, true, true);
5925 break;
5927 case GFC_ISYM_SHIFTL:
5928 gfc_conv_intrinsic_shift (se, expr, false, false);
5929 break;
5931 case GFC_ISYM_SHIFTR:
5932 gfc_conv_intrinsic_shift (se, expr, true, false);
5933 break;
5935 case GFC_ISYM_ISHFT:
5936 gfc_conv_intrinsic_ishft (se, expr);
5937 break;
5939 case GFC_ISYM_ISHFTC:
5940 gfc_conv_intrinsic_ishftc (se, expr);
5941 break;
5943 case GFC_ISYM_LEADZ:
5944 gfc_conv_intrinsic_leadz (se, expr);
5945 break;
5947 case GFC_ISYM_TRAILZ:
5948 gfc_conv_intrinsic_trailz (se, expr);
5949 break;
5951 case GFC_ISYM_POPCNT:
5952 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
5953 break;
5955 case GFC_ISYM_POPPAR:
5956 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
5957 break;
5959 case GFC_ISYM_LBOUND:
5960 gfc_conv_intrinsic_bound (se, expr, 0);
5961 break;
5963 case GFC_ISYM_TRANSPOSE:
5964 /* The scalarizer has already been set up for reversed dimension access
5965 order ; now we just get the argument value normally. */
5966 gfc_conv_expr (se, expr->value.function.actual->expr);
5967 break;
5969 case GFC_ISYM_LEN:
5970 gfc_conv_intrinsic_len (se, expr);
5971 break;
5973 case GFC_ISYM_LEN_TRIM:
5974 gfc_conv_intrinsic_len_trim (se, expr);
5975 break;
5977 case GFC_ISYM_LGE:
5978 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
5979 break;
5981 case GFC_ISYM_LGT:
5982 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
5983 break;
5985 case GFC_ISYM_LLE:
5986 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
5987 break;
5989 case GFC_ISYM_LLT:
5990 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
5991 break;
5993 case GFC_ISYM_MASKL:
5994 gfc_conv_intrinsic_mask (se, expr, 1);
5995 break;
5997 case GFC_ISYM_MASKR:
5998 gfc_conv_intrinsic_mask (se, expr, 0);
5999 break;
6001 case GFC_ISYM_MAX:
6002 if (expr->ts.type == BT_CHARACTER)
6003 gfc_conv_intrinsic_minmax_char (se, expr, 1);
6004 else
6005 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
6006 break;
6008 case GFC_ISYM_MAXLOC:
6009 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
6010 break;
6012 case GFC_ISYM_MAXVAL:
6013 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
6014 break;
6016 case GFC_ISYM_MERGE:
6017 gfc_conv_intrinsic_merge (se, expr);
6018 break;
6020 case GFC_ISYM_MERGE_BITS:
6021 gfc_conv_intrinsic_merge_bits (se, expr);
6022 break;
6024 case GFC_ISYM_MIN:
6025 if (expr->ts.type == BT_CHARACTER)
6026 gfc_conv_intrinsic_minmax_char (se, expr, -1);
6027 else
6028 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
6029 break;
6031 case GFC_ISYM_MINLOC:
6032 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
6033 break;
6035 case GFC_ISYM_MINVAL:
6036 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
6037 break;
6039 case GFC_ISYM_NEAREST:
6040 gfc_conv_intrinsic_nearest (se, expr);
6041 break;
6043 case GFC_ISYM_NORM2:
6044 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
6045 break;
6047 case GFC_ISYM_NOT:
6048 gfc_conv_intrinsic_not (se, expr);
6049 break;
6051 case GFC_ISYM_OR:
6052 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
6053 break;
6055 case GFC_ISYM_PARITY:
6056 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
6057 break;
6059 case GFC_ISYM_PRESENT:
6060 gfc_conv_intrinsic_present (se, expr);
6061 break;
6063 case GFC_ISYM_PRODUCT:
6064 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
6065 break;
6067 case GFC_ISYM_RRSPACING:
6068 gfc_conv_intrinsic_rrspacing (se, expr);
6069 break;
6071 case GFC_ISYM_SET_EXPONENT:
6072 gfc_conv_intrinsic_set_exponent (se, expr);
6073 break;
6075 case GFC_ISYM_SCALE:
6076 gfc_conv_intrinsic_scale (se, expr);
6077 break;
6079 case GFC_ISYM_SIGN:
6080 gfc_conv_intrinsic_sign (se, expr);
6081 break;
6083 case GFC_ISYM_SIZE:
6084 gfc_conv_intrinsic_size (se, expr);
6085 break;
6087 case GFC_ISYM_SIZEOF:
6088 case GFC_ISYM_C_SIZEOF:
6089 gfc_conv_intrinsic_sizeof (se, expr);
6090 break;
6092 case GFC_ISYM_STORAGE_SIZE:
6093 gfc_conv_intrinsic_storage_size (se, expr);
6094 break;
6096 case GFC_ISYM_SPACING:
6097 gfc_conv_intrinsic_spacing (se, expr);
6098 break;
6100 case GFC_ISYM_SUM:
6101 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
6102 break;
6104 case GFC_ISYM_TRANSFER:
6105 if (se->ss && se->ss->useflags)
6106 /* Access the previously obtained result. */
6107 gfc_conv_tmp_array_ref (se);
6108 else
6109 gfc_conv_intrinsic_transfer (se, expr);
6110 break;
6112 case GFC_ISYM_TTYNAM:
6113 gfc_conv_intrinsic_ttynam (se, expr);
6114 break;
6116 case GFC_ISYM_UBOUND:
6117 gfc_conv_intrinsic_bound (se, expr, 1);
6118 break;
6120 case GFC_ISYM_XOR:
6121 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
6122 break;
6124 case GFC_ISYM_LOC:
6125 gfc_conv_intrinsic_loc (se, expr);
6126 break;
6128 case GFC_ISYM_THIS_IMAGE:
6129 trans_this_image (se, expr);
6130 break;
6132 case GFC_ISYM_NUM_IMAGES:
6133 trans_num_images (se);
6134 break;
6136 case GFC_ISYM_ACCESS:
6137 case GFC_ISYM_CHDIR:
6138 case GFC_ISYM_CHMOD:
6139 case GFC_ISYM_DTIME:
6140 case GFC_ISYM_ETIME:
6141 case GFC_ISYM_EXTENDS_TYPE_OF:
6142 case GFC_ISYM_FGET:
6143 case GFC_ISYM_FGETC:
6144 case GFC_ISYM_FNUM:
6145 case GFC_ISYM_FPUT:
6146 case GFC_ISYM_FPUTC:
6147 case GFC_ISYM_FSTAT:
6148 case GFC_ISYM_FTELL:
6149 case GFC_ISYM_GETCWD:
6150 case GFC_ISYM_GETGID:
6151 case GFC_ISYM_GETPID:
6152 case GFC_ISYM_GETUID:
6153 case GFC_ISYM_HOSTNM:
6154 case GFC_ISYM_KILL:
6155 case GFC_ISYM_IERRNO:
6156 case GFC_ISYM_IRAND:
6157 case GFC_ISYM_ISATTY:
6158 case GFC_ISYM_JN2:
6159 case GFC_ISYM_LINK:
6160 case GFC_ISYM_LSTAT:
6161 case GFC_ISYM_MALLOC:
6162 case GFC_ISYM_MATMUL:
6163 case GFC_ISYM_MCLOCK:
6164 case GFC_ISYM_MCLOCK8:
6165 case GFC_ISYM_RAND:
6166 case GFC_ISYM_RENAME:
6167 case GFC_ISYM_SECOND:
6168 case GFC_ISYM_SECNDS:
6169 case GFC_ISYM_SIGNAL:
6170 case GFC_ISYM_STAT:
6171 case GFC_ISYM_SYMLNK:
6172 case GFC_ISYM_SYSTEM:
6173 case GFC_ISYM_TIME:
6174 case GFC_ISYM_TIME8:
6175 case GFC_ISYM_UMASK:
6176 case GFC_ISYM_UNLINK:
6177 case GFC_ISYM_YN2:
6178 gfc_conv_intrinsic_funcall (se, expr);
6179 break;
6181 case GFC_ISYM_EOSHIFT:
6182 case GFC_ISYM_PACK:
6183 case GFC_ISYM_RESHAPE:
6184 /* For those, expr->rank should always be >0 and thus the if above the
6185 switch should have matched. */
6186 gcc_unreachable ();
6187 break;
6189 default:
6190 gfc_conv_intrinsic_lib_function (se, expr);
6191 break;
6196 static gfc_ss *
6197 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
6199 gfc_ss *arg_ss, *tmp_ss;
6200 gfc_actual_arglist *arg;
6202 arg = expr->value.function.actual;
6204 gcc_assert (arg->expr);
6206 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
6207 gcc_assert (arg_ss != gfc_ss_terminator);
6209 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
6211 if (tmp_ss->type != GFC_SS_SCALAR
6212 && tmp_ss->type != GFC_SS_REFERENCE)
6214 int tmp_dim;
6215 gfc_ss_info *info;
6217 info = &tmp_ss->data.info;
6218 gcc_assert (info->dimen == 2);
6220 /* We just invert dimensions. */
6221 tmp_dim = info->dim[0];
6222 info->dim[0] = info->dim[1];
6223 info->dim[1] = tmp_dim;
6226 /* Stop when tmp_ss points to the last valid element of the chain... */
6227 if (tmp_ss->next == gfc_ss_terminator)
6228 break;
6231 /* ... so that we can attach the rest of the chain to it. */
6232 tmp_ss->next = ss;
6234 return arg_ss;
6238 static gfc_ss *
6239 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
6242 switch (expr->value.function.isym->id)
6244 case GFC_ISYM_TRANSPOSE:
6245 return walk_inline_intrinsic_transpose (ss, expr);
6247 default:
6248 gcc_unreachable ();
6250 gcc_unreachable ();
6254 /* This generates code to execute before entering the scalarization loop.
6255 Currently does nothing. */
6257 void
6258 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
6260 switch (ss->expr->value.function.isym->id)
6262 case GFC_ISYM_UBOUND:
6263 case GFC_ISYM_LBOUND:
6264 break;
6266 default:
6267 gcc_unreachable ();
6272 /* UBOUND and LBOUND intrinsics with one parameter are expanded into code
6273 inside the scalarization loop. */
6275 static gfc_ss *
6276 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
6278 gfc_ss *newss;
6280 /* The two argument version returns a scalar. */
6281 if (expr->value.function.actual->next->expr)
6282 return ss;
6284 newss = gfc_get_ss ();
6285 newss->type = GFC_SS_INTRINSIC;
6286 newss->expr = expr;
6287 newss->next = ss;
6288 newss->data.info.dimen = 1;
6290 return newss;
6294 /* Walk an intrinsic array libcall. */
6296 static gfc_ss *
6297 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
6299 gfc_ss *newss;
6300 int n;
6302 gcc_assert (expr->rank > 0);
6304 newss = gfc_get_ss ();
6305 newss->type = GFC_SS_FUNCTION;
6306 newss->expr = expr;
6307 newss->next = ss;
6308 newss->data.info.dimen = expr->rank;
6309 for (n = 0; n < newss->data.info.dimen; n++)
6310 newss->data.info.dim[n] = n;
6312 return newss;
6316 /* Return whether the function call expression EXPR will be expanded
6317 inline by gfc_conv_intrinsic_function. */
6319 bool
6320 gfc_inline_intrinsic_function_p (gfc_expr *expr)
6322 if (!expr->value.function.isym)
6323 return false;
6325 switch (expr->value.function.isym->id)
6327 case GFC_ISYM_TRANSPOSE:
6328 return true;
6330 default:
6331 return false;
6336 /* Returns nonzero if the specified intrinsic function call maps directly to
6337 an external library call. Should only be used for functions that return
6338 arrays. */
6341 gfc_is_intrinsic_libcall (gfc_expr * expr)
6343 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
6344 gcc_assert (expr->rank > 0);
6346 if (gfc_inline_intrinsic_function_p (expr))
6347 return 0;
6349 switch (expr->value.function.isym->id)
6351 case GFC_ISYM_ALL:
6352 case GFC_ISYM_ANY:
6353 case GFC_ISYM_COUNT:
6354 case GFC_ISYM_JN2:
6355 case GFC_ISYM_IANY:
6356 case GFC_ISYM_IALL:
6357 case GFC_ISYM_IPARITY:
6358 case GFC_ISYM_MATMUL:
6359 case GFC_ISYM_MAXLOC:
6360 case GFC_ISYM_MAXVAL:
6361 case GFC_ISYM_MINLOC:
6362 case GFC_ISYM_MINVAL:
6363 case GFC_ISYM_NORM2:
6364 case GFC_ISYM_PARITY:
6365 case GFC_ISYM_PRODUCT:
6366 case GFC_ISYM_SUM:
6367 case GFC_ISYM_SHAPE:
6368 case GFC_ISYM_SPREAD:
6369 case GFC_ISYM_YN2:
6370 /* Ignore absent optional parameters. */
6371 return 1;
6373 case GFC_ISYM_RESHAPE:
6374 case GFC_ISYM_CSHIFT:
6375 case GFC_ISYM_EOSHIFT:
6376 case GFC_ISYM_PACK:
6377 case GFC_ISYM_UNPACK:
6378 /* Pass absent optional parameters. */
6379 return 2;
6381 default:
6382 return 0;
6386 /* Walk an intrinsic function. */
6387 gfc_ss *
6388 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
6389 gfc_intrinsic_sym * isym)
6391 gcc_assert (isym);
6393 if (isym->elemental)
6394 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
6395 GFC_SS_SCALAR);
6397 if (expr->rank == 0)
6398 return ss;
6400 if (gfc_inline_intrinsic_function_p (expr))
6401 return walk_inline_intrinsic_function (ss, expr);
6403 if (gfc_is_intrinsic_libcall (expr))
6404 return gfc_walk_intrinsic_libfunc (ss, expr);
6406 /* Special cases. */
6407 switch (isym->id)
6409 case GFC_ISYM_LBOUND:
6410 case GFC_ISYM_UBOUND:
6411 return gfc_walk_intrinsic_bound (ss, expr);
6413 case GFC_ISYM_TRANSFER:
6414 return gfc_walk_intrinsic_libfunc (ss, expr);
6416 default:
6417 /* This probably meant someone forgot to add an intrinsic to the above
6418 list(s) when they implemented it, or something's gone horribly
6419 wrong. */
6420 gcc_unreachable ();
6425 tree
6426 gfc_conv_intrinsic_move_alloc (gfc_code *code)
6428 if (code->ext.actual->expr->rank == 0)
6430 /* Scalar arguments: Generate pointer assignments. */
6431 gfc_expr *from, *to;
6432 stmtblock_t block;
6433 tree tmp;
6435 from = code->ext.actual->expr;
6436 to = code->ext.actual->next->expr;
6438 gfc_start_block (&block);
6440 if (to->ts.type == BT_CLASS)
6441 tmp = gfc_trans_class_assign (to, from, EXEC_POINTER_ASSIGN);
6442 else
6443 tmp = gfc_trans_pointer_assignment (to, from);
6444 gfc_add_expr_to_block (&block, tmp);
6446 if (from->ts.type == BT_CLASS)
6447 tmp = gfc_trans_class_assign (from, gfc_get_null_expr (NULL),
6448 EXEC_POINTER_ASSIGN);
6449 else
6450 tmp = gfc_trans_pointer_assignment (from,
6451 gfc_get_null_expr (NULL));
6452 gfc_add_expr_to_block (&block, tmp);
6454 return gfc_finish_block (&block);
6456 else
6457 /* Array arguments: Generate library code. */
6458 return gfc_trans_call (code, false, NULL_TREE, NULL_TREE, false);
6462 #include "gt-fortran-trans-intrinsic.h"