Update ChangeLogs for wide-int work.
[gcc.git] / gcc / fortran / trans-intrinsic.c
1 /* Intrinsic translation
2 Copyright (C) 2002-2014 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22 /* trans-intrinsic.c-- generate GENERIC trees for calls to intrinsics. */
23
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h" /* For UNITS_PER_WORD. */
28 #include "tree.h"
29 #include "stringpool.h"
30 #include "tree-nested.h"
31 #include "stor-layout.h"
32 #include "ggc.h"
33 #include "diagnostic-core.h" /* For internal_error. */
34 #include "toplev.h" /* For rest_of_decl_compilation. */
35 #include "flags.h"
36 #include "gfortran.h"
37 #include "arith.h"
38 #include "intrinsic.h"
39 #include "trans.h"
40 #include "trans-const.h"
41 #include "trans-types.h"
42 #include "trans-array.h"
43 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
44 #include "trans-stmt.h"
45 #include "tree-nested.h"
46 #include "wide-int.h"
47
48 /* This maps Fortran intrinsic math functions to external library or GCC
49 builtin functions. */
50 typedef struct GTY(()) gfc_intrinsic_map_t {
51 /* The explicit enum is required to work around inadequacies in the
52 garbage collection/gengtype parsing mechanism. */
53 enum gfc_isym_id id;
54
55 /* Enum value from the "language-independent", aka C-centric, part
56 of gcc, or END_BUILTINS of no such value set. */
57 enum built_in_function float_built_in;
58 enum built_in_function double_built_in;
59 enum built_in_function long_double_built_in;
60 enum built_in_function complex_float_built_in;
61 enum built_in_function complex_double_built_in;
62 enum built_in_function complex_long_double_built_in;
63
64 /* True if the naming pattern is to prepend "c" for complex and
65 append "f" for kind=4. False if the naming pattern is to
66 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
67 bool libm_name;
68
69 /* True if a complex version of the function exists. */
70 bool complex_available;
71
72 /* True if the function should be marked const. */
73 bool is_constant;
74
75 /* The base library name of this function. */
76 const char *name;
77
78 /* Cache decls created for the various operand types. */
79 tree real4_decl;
80 tree real8_decl;
81 tree real10_decl;
82 tree real16_decl;
83 tree complex4_decl;
84 tree complex8_decl;
85 tree complex10_decl;
86 tree complex16_decl;
87 }
88 gfc_intrinsic_map_t;
89
90 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
91 defines complex variants of all of the entries in mathbuiltins.def
92 except for atan2. */
93 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
94 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
95 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
96 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
97 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
98
99 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
100 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
101 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
102 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
103 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
104
105 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
106 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
107 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
108 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
109 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
110
111 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
112 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
113 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
114 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
115 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
116
117 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
118 {
119 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
120 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
121 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
122 #include "mathbuiltins.def"
123
124 /* Functions in libgfortran. */
125 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
126
127 /* End the list. */
128 LIB_FUNCTION (NONE, NULL, false)
129
130 };
131 #undef OTHER_BUILTIN
132 #undef LIB_FUNCTION
133 #undef DEFINE_MATH_BUILTIN
134 #undef DEFINE_MATH_BUILTIN_C
135
136
137 enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
138
139
140 /* Find the correct variant of a given builtin from its argument. */
141 static tree
142 builtin_decl_for_precision (enum built_in_function base_built_in,
143 int precision)
144 {
145 enum built_in_function i = END_BUILTINS;
146
147 gfc_intrinsic_map_t *m;
148 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
149 ;
150
151 if (precision == TYPE_PRECISION (float_type_node))
152 i = m->float_built_in;
153 else if (precision == TYPE_PRECISION (double_type_node))
154 i = m->double_built_in;
155 else if (precision == TYPE_PRECISION (long_double_type_node))
156 i = m->long_double_built_in;
157 else if (precision == TYPE_PRECISION (float128_type_node))
158 {
159 /* Special treatment, because it is not exactly a built-in, but
160 a library function. */
161 return m->real16_decl;
162 }
163
164 return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
165 }
166
167
168 tree
169 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
170 int kind)
171 {
172 int i = gfc_validate_kind (BT_REAL, kind, false);
173
174 if (gfc_real_kinds[i].c_float128)
175 {
176 /* For __float128, the story is a bit different, because we return
177 a decl to a library function rather than a built-in. */
178 gfc_intrinsic_map_t *m;
179 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
180 ;
181
182 return m->real16_decl;
183 }
184
185 return builtin_decl_for_precision (double_built_in,
186 gfc_real_kinds[i].mode_precision);
187 }
188
189
190 /* Evaluate the arguments to an intrinsic function. The value
191 of NARGS may be less than the actual number of arguments in EXPR
192 to allow optional "KIND" arguments that are not included in the
193 generated code to be ignored. */
194
195 static void
196 gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
197 tree *argarray, int nargs)
198 {
199 gfc_actual_arglist *actual;
200 gfc_expr *e;
201 gfc_intrinsic_arg *formal;
202 gfc_se argse;
203 int curr_arg;
204
205 formal = expr->value.function.isym->formal;
206 actual = expr->value.function.actual;
207
208 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
209 actual = actual->next,
210 formal = formal ? formal->next : NULL)
211 {
212 gcc_assert (actual);
213 e = actual->expr;
214 /* Skip omitted optional arguments. */
215 if (!e)
216 {
217 --curr_arg;
218 continue;
219 }
220
221 /* Evaluate the parameter. This will substitute scalarized
222 references automatically. */
223 gfc_init_se (&argse, se);
224
225 if (e->ts.type == BT_CHARACTER)
226 {
227 gfc_conv_expr (&argse, e);
228 gfc_conv_string_parameter (&argse);
229 argarray[curr_arg++] = argse.string_length;
230 gcc_assert (curr_arg < nargs);
231 }
232 else
233 gfc_conv_expr_val (&argse, e);
234
235 /* If an optional argument is itself an optional dummy argument,
236 check its presence and substitute a null if absent. */
237 if (e->expr_type == EXPR_VARIABLE
238 && e->symtree->n.sym->attr.optional
239 && formal
240 && formal->optional)
241 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
242
243 gfc_add_block_to_block (&se->pre, &argse.pre);
244 gfc_add_block_to_block (&se->post, &argse.post);
245 argarray[curr_arg] = argse.expr;
246 }
247 }
248
249 /* Count the number of actual arguments to the intrinsic function EXPR
250 including any "hidden" string length arguments. */
251
252 static unsigned int
253 gfc_intrinsic_argument_list_length (gfc_expr *expr)
254 {
255 int n = 0;
256 gfc_actual_arglist *actual;
257
258 for (actual = expr->value.function.actual; actual; actual = actual->next)
259 {
260 if (!actual->expr)
261 continue;
262
263 if (actual->expr->ts.type == BT_CHARACTER)
264 n += 2;
265 else
266 n++;
267 }
268
269 return n;
270 }
271
272
273 /* Conversions between different types are output by the frontend as
274 intrinsic functions. We implement these directly with inline code. */
275
276 static void
277 gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
278 {
279 tree type;
280 tree *args;
281 int nargs;
282
283 nargs = gfc_intrinsic_argument_list_length (expr);
284 args = XALLOCAVEC (tree, nargs);
285
286 /* Evaluate all the arguments passed. Whilst we're only interested in the
287 first one here, there are other parts of the front-end that assume this
288 and will trigger an ICE if it's not the case. */
289 type = gfc_typenode_for_spec (&expr->ts);
290 gcc_assert (expr->value.function.actual->expr);
291 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
292
293 /* Conversion between character kinds involves a call to a library
294 function. */
295 if (expr->ts.type == BT_CHARACTER)
296 {
297 tree fndecl, var, addr, tmp;
298
299 if (expr->ts.kind == 1
300 && expr->value.function.actual->expr->ts.kind == 4)
301 fndecl = gfor_fndecl_convert_char4_to_char1;
302 else if (expr->ts.kind == 4
303 && expr->value.function.actual->expr->ts.kind == 1)
304 fndecl = gfor_fndecl_convert_char1_to_char4;
305 else
306 gcc_unreachable ();
307
308 /* Create the variable storing the converted value. */
309 type = gfc_get_pchar_type (expr->ts.kind);
310 var = gfc_create_var (type, "str");
311 addr = gfc_build_addr_expr (build_pointer_type (type), var);
312
313 /* Call the library function that will perform the conversion. */
314 gcc_assert (nargs >= 2);
315 tmp = build_call_expr_loc (input_location,
316 fndecl, 3, addr, args[0], args[1]);
317 gfc_add_expr_to_block (&se->pre, tmp);
318
319 /* Free the temporary afterwards. */
320 tmp = gfc_call_free (var);
321 gfc_add_expr_to_block (&se->post, tmp);
322
323 se->expr = var;
324 se->string_length = args[0];
325
326 return;
327 }
328
329 /* Conversion from complex to non-complex involves taking the real
330 component of the value. */
331 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
332 && expr->ts.type != BT_COMPLEX)
333 {
334 tree artype;
335
336 artype = TREE_TYPE (TREE_TYPE (args[0]));
337 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
338 args[0]);
339 }
340
341 se->expr = convert (type, args[0]);
342 }
343
344 /* This is needed because the gcc backend only implements
345 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
346 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
347 Similarly for CEILING. */
348
349 static tree
350 build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
351 {
352 tree tmp;
353 tree cond;
354 tree argtype;
355 tree intval;
356
357 argtype = TREE_TYPE (arg);
358 arg = gfc_evaluate_now (arg, pblock);
359
360 intval = convert (type, arg);
361 intval = gfc_evaluate_now (intval, pblock);
362
363 tmp = convert (argtype, intval);
364 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
365 boolean_type_node, tmp, arg);
366
367 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
368 intval, build_int_cst (type, 1));
369 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
370 return tmp;
371 }
372
373
374 /* Round to nearest integer, away from zero. */
375
376 static tree
377 build_round_expr (tree arg, tree restype)
378 {
379 tree argtype;
380 tree fn;
381 int argprec, resprec;
382
383 argtype = TREE_TYPE (arg);
384 argprec = TYPE_PRECISION (argtype);
385 resprec = TYPE_PRECISION (restype);
386
387 /* Depending on the type of the result, choose the int intrinsic
388 (iround, available only as a builtin, therefore cannot use it for
389 __float128), long int intrinsic (lround family) or long long
390 intrinsic (llround). We might also need to convert the result
391 afterwards. */
392 if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
393 fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
394 else if (resprec <= LONG_TYPE_SIZE)
395 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
396 else if (resprec <= LONG_LONG_TYPE_SIZE)
397 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
398 else
399 gcc_unreachable ();
400
401 return fold_convert (restype, build_call_expr_loc (input_location,
402 fn, 1, arg));
403 }
404
405
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. */
409
410 static tree
411 build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
412 enum rounding_mode op)
413 {
414 switch (op)
415 {
416 case RND_FLOOR:
417 return build_fixbound_expr (pblock, arg, type, 0);
418 break;
419
420 case RND_CEIL:
421 return build_fixbound_expr (pblock, arg, type, 1);
422 break;
423
424 case RND_ROUND:
425 return build_round_expr (arg, type);
426 break;
427
428 case RND_TRUNC:
429 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
430 break;
431
432 default:
433 gcc_unreachable ();
434 }
435 }
436
437
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
445 */
446
447 static void
448 gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
449 {
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;
459
460 kind = expr->ts.kind;
461 nargs = gfc_intrinsic_argument_list_length (expr);
462
463 decl = NULL_TREE;
464 /* We have builtin functions for some cases. */
465 switch (op)
466 {
467 case RND_ROUND:
468 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
469 break;
470
471 case RND_TRUNC:
472 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
473 break;
474
475 default:
476 gcc_unreachable ();
477 }
478
479 /* Evaluate the argument. */
480 gcc_assert (expr->value.function.actual->expr);
481 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
482
483 /* Use a builtin function if one exists. */
484 if (decl != NULL_TREE)
485 {
486 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
487 return;
488 }
489
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);
494
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);
503
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);
511
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);
517 }
518
519
520 /* Convert to an integer using the specified rounding mode. */
521
522 static void
523 gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
524 {
525 tree type;
526 tree *args;
527 int nargs;
528
529 nargs = gfc_intrinsic_argument_list_length (expr);
530 args = XALLOCAVEC (tree, nargs);
531
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);
537
538 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
539 {
540 /* Conversion to a different integer kind. */
541 se->expr = convert (type, args[0]);
542 }
543 else
544 {
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)
549 {
550 tree artype;
551
552 artype = TREE_TYPE (TREE_TYPE (args[0]));
553 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
554 args[0]);
555 }
556
557 se->expr = build_fix_expr (&se->pre, args[0], type, op);
558 }
559 }
560
561
562 /* Get the imaginary component of a value. */
563
564 static void
565 gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
566 {
567 tree arg;
568
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);
572 }
573
574
575 /* Get the complex conjugate of a value. */
576
577 static void
578 gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
579 {
580 tree arg;
581
582 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
583 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
584 }
585
586
587
588 static tree
589 define_quad_builtin (const char *name, tree type, bool is_const)
590 {
591 tree fndecl;
592 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
593 type);
594
595 /* Mark the decl as external. */
596 DECL_EXTERNAL (fndecl) = 1;
597 TREE_PUBLIC (fndecl) = 1;
598
599 /* Mark it __attribute__((const)). */
600 TREE_READONLY (fndecl) = is_const;
601
602 rest_of_decl_compilation (fndecl, 1, 0);
603
604 return fndecl;
605 }
606
607
608
609 /* Initialize function decls for library functions. The external functions
610 are created as required. Builtin functions are added here. */
611
612 void
613 gfc_build_intrinsic_lib_fndecls (void)
614 {
615 gfc_intrinsic_map_t *m;
616 tree quad_decls[END_BUILTINS + 1];
617
618 if (gfc_real16_is_float128)
619 {
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. */
623
624 tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
625 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
626
627 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
628
629 type = float128_type_node;
630 complex_type = complex_float128_type_node;
631 /* type (*) (type) */
632 func_1 = build_function_type_list (type, type, NULL_TREE);
633 /* int (*) (type) */
634 func_iround = build_function_type_list (integer_type_node,
635 type, NULL_TREE);
636 /* long (*) (type) */
637 func_lround = build_function_type_list (long_integer_type_node,
638 type, NULL_TREE);
639 /* long long (*) (type) */
640 func_llround = build_function_type_list (long_long_integer_type_node,
641 type, NULL_TREE);
642 /* type (*) (type, type) */
643 func_2 = build_function_type_list (type, type, type, NULL_TREE);
644 /* type (*) (type, &int) */
645 func_frexp
646 = build_function_type_list (type,
647 type,
648 build_pointer_type (integer_type_node),
649 NULL_TREE);
650 /* type (*) (type, int) */
651 func_scalbn = build_function_type_list (type,
652 type, integer_type_node, NULL_TREE);
653 /* type (*) (complex type) */
654 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
655 /* complex type (*) (complex type, complex type) */
656 func_cpow
657 = build_function_type_list (complex_type,
658 complex_type, complex_type, NULL_TREE);
659
660 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
661 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
662 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
663
664 /* Only these built-ins are actually needed here. These are used directly
665 from the code, when calling builtin_decl_for_precision() or
666 builtin_decl_for_float_type(). The others are all constructed by
667 gfc_get_intrinsic_lib_fndecl(). */
668 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
669 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
670
671 #include "mathbuiltins.def"
672
673 #undef OTHER_BUILTIN
674 #undef LIB_FUNCTION
675 #undef DEFINE_MATH_BUILTIN
676 #undef DEFINE_MATH_BUILTIN_C
677
678 }
679
680 /* Add GCC builtin functions. */
681 for (m = gfc_intrinsic_map;
682 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
683 {
684 if (m->float_built_in != END_BUILTINS)
685 m->real4_decl = builtin_decl_explicit (m->float_built_in);
686 if (m->complex_float_built_in != END_BUILTINS)
687 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
688 if (m->double_built_in != END_BUILTINS)
689 m->real8_decl = builtin_decl_explicit (m->double_built_in);
690 if (m->complex_double_built_in != END_BUILTINS)
691 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
692
693 /* If real(kind=10) exists, it is always long double. */
694 if (m->long_double_built_in != END_BUILTINS)
695 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
696 if (m->complex_long_double_built_in != END_BUILTINS)
697 m->complex10_decl
698 = builtin_decl_explicit (m->complex_long_double_built_in);
699
700 if (!gfc_real16_is_float128)
701 {
702 if (m->long_double_built_in != END_BUILTINS)
703 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
704 if (m->complex_long_double_built_in != END_BUILTINS)
705 m->complex16_decl
706 = builtin_decl_explicit (m->complex_long_double_built_in);
707 }
708 else if (quad_decls[m->double_built_in] != NULL_TREE)
709 {
710 /* Quad-precision function calls are constructed when first
711 needed by builtin_decl_for_precision(), except for those
712 that will be used directly (define by OTHER_BUILTIN). */
713 m->real16_decl = quad_decls[m->double_built_in];
714 }
715 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
716 {
717 /* Same thing for the complex ones. */
718 m->complex16_decl = quad_decls[m->double_built_in];
719 }
720 }
721 }
722
723
724 /* Create a fndecl for a simple intrinsic library function. */
725
726 static tree
727 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
728 {
729 tree type;
730 vec<tree, va_gc> *argtypes;
731 tree fndecl;
732 gfc_actual_arglist *actual;
733 tree *pdecl;
734 gfc_typespec *ts;
735 char name[GFC_MAX_SYMBOL_LEN + 3];
736
737 ts = &expr->ts;
738 if (ts->type == BT_REAL)
739 {
740 switch (ts->kind)
741 {
742 case 4:
743 pdecl = &m->real4_decl;
744 break;
745 case 8:
746 pdecl = &m->real8_decl;
747 break;
748 case 10:
749 pdecl = &m->real10_decl;
750 break;
751 case 16:
752 pdecl = &m->real16_decl;
753 break;
754 default:
755 gcc_unreachable ();
756 }
757 }
758 else if (ts->type == BT_COMPLEX)
759 {
760 gcc_assert (m->complex_available);
761
762 switch (ts->kind)
763 {
764 case 4:
765 pdecl = &m->complex4_decl;
766 break;
767 case 8:
768 pdecl = &m->complex8_decl;
769 break;
770 case 10:
771 pdecl = &m->complex10_decl;
772 break;
773 case 16:
774 pdecl = &m->complex16_decl;
775 break;
776 default:
777 gcc_unreachable ();
778 }
779 }
780 else
781 gcc_unreachable ();
782
783 if (*pdecl)
784 return *pdecl;
785
786 if (m->libm_name)
787 {
788 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
789 if (gfc_real_kinds[n].c_float)
790 snprintf (name, sizeof (name), "%s%s%s",
791 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
792 else if (gfc_real_kinds[n].c_double)
793 snprintf (name, sizeof (name), "%s%s",
794 ts->type == BT_COMPLEX ? "c" : "", m->name);
795 else if (gfc_real_kinds[n].c_long_double)
796 snprintf (name, sizeof (name), "%s%s%s",
797 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
798 else if (gfc_real_kinds[n].c_float128)
799 snprintf (name, sizeof (name), "%s%s%s",
800 ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
801 else
802 gcc_unreachable ();
803 }
804 else
805 {
806 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
807 ts->type == BT_COMPLEX ? 'c' : 'r',
808 ts->kind);
809 }
810
811 argtypes = NULL;
812 for (actual = expr->value.function.actual; actual; actual = actual->next)
813 {
814 type = gfc_typenode_for_spec (&actual->expr->ts);
815 vec_safe_push (argtypes, type);
816 }
817 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
818 fndecl = build_decl (input_location,
819 FUNCTION_DECL, get_identifier (name), type);
820
821 /* Mark the decl as external. */
822 DECL_EXTERNAL (fndecl) = 1;
823 TREE_PUBLIC (fndecl) = 1;
824
825 /* Mark it __attribute__((const)), if possible. */
826 TREE_READONLY (fndecl) = m->is_constant;
827
828 rest_of_decl_compilation (fndecl, 1, 0);
829
830 (*pdecl) = fndecl;
831 return fndecl;
832 }
833
834
835 /* Convert an intrinsic function into an external or builtin call. */
836
837 static void
838 gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
839 {
840 gfc_intrinsic_map_t *m;
841 tree fndecl;
842 tree rettype;
843 tree *args;
844 unsigned int num_args;
845 gfc_isym_id id;
846
847 id = expr->value.function.isym->id;
848 /* Find the entry for this function. */
849 for (m = gfc_intrinsic_map;
850 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
851 {
852 if (id == m->id)
853 break;
854 }
855
856 if (m->id == GFC_ISYM_NONE)
857 {
858 internal_error ("Intrinsic function %s(%d) not recognized",
859 expr->value.function.name, id);
860 }
861
862 /* Get the decl and generate the call. */
863 num_args = gfc_intrinsic_argument_list_length (expr);
864 args = XALLOCAVEC (tree, num_args);
865
866 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
867 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
868 rettype = TREE_TYPE (TREE_TYPE (fndecl));
869
870 fndecl = build_addr (fndecl, current_function_decl);
871 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
872 }
873
874
875 /* If bounds-checking is enabled, create code to verify at runtime that the
876 string lengths for both expressions are the same (needed for e.g. MERGE).
877 If bounds-checking is not enabled, does nothing. */
878
879 void
880 gfc_trans_same_strlen_check (const char* intr_name, locus* where,
881 tree a, tree b, stmtblock_t* target)
882 {
883 tree cond;
884 tree name;
885
886 /* If bounds-checking is disabled, do nothing. */
887 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
888 return;
889
890 /* Compare the two string lengths. */
891 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, a, b);
892
893 /* Output the runtime-check. */
894 name = gfc_build_cstring_const (intr_name);
895 name = gfc_build_addr_expr (pchar_type_node, name);
896 gfc_trans_runtime_check (true, false, cond, target, where,
897 "Unequal character lengths (%ld/%ld) in %s",
898 fold_convert (long_integer_type_node, a),
899 fold_convert (long_integer_type_node, b), name);
900 }
901
902
903 /* The EXPONENT(s) intrinsic function is translated into
904 int ret;
905 frexp (s, &ret);
906 return ret;
907 */
908
909 static void
910 gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
911 {
912 tree arg, type, res, tmp, frexp;
913
914 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
915 expr->value.function.actual->expr->ts.kind);
916
917 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
918
919 res = gfc_create_var (integer_type_node, NULL);
920 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
921 gfc_build_addr_expr (NULL_TREE, res));
922 gfc_add_expr_to_block (&se->pre, tmp);
923
924 type = gfc_typenode_for_spec (&expr->ts);
925 se->expr = fold_convert (type, res);
926 }
927
928
929 static void
930 trans_this_image (gfc_se * se, gfc_expr *expr)
931 {
932 stmtblock_t loop;
933 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
934 lbound, ubound, extent, ml;
935 gfc_se argse;
936 int rank, corank;
937
938 /* The case -fcoarray=single is handled elsewhere. */
939 gcc_assert (gfc_option.coarray != GFC_FCOARRAY_SINGLE);
940
941 /* Argument-free version: THIS_IMAGE(). */
942 if (expr->value.function.actual->expr == NULL)
943 {
944 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
945 integer_zero_node);
946 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
947 tmp);
948 return;
949 }
950
951 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
952
953 type = gfc_get_int_type (gfc_default_integer_kind);
954 corank = gfc_get_corank (expr->value.function.actual->expr);
955 rank = expr->value.function.actual->expr->rank;
956
957 /* Obtain the descriptor of the COARRAY. */
958 gfc_init_se (&argse, NULL);
959 argse.want_coarray = 1;
960 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
961 gfc_add_block_to_block (&se->pre, &argse.pre);
962 gfc_add_block_to_block (&se->post, &argse.post);
963 desc = argse.expr;
964
965 if (se->ss)
966 {
967 /* Create an implicit second parameter from the loop variable. */
968 gcc_assert (!expr->value.function.actual->next->expr);
969 gcc_assert (corank > 0);
970 gcc_assert (se->loop->dimen == 1);
971 gcc_assert (se->ss->info->expr == expr);
972
973 dim_arg = se->loop->loopvar[0];
974 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
975 gfc_array_index_type, dim_arg,
976 build_int_cst (TREE_TYPE (dim_arg), 1));
977 gfc_advance_se_ss_chain (se);
978 }
979 else
980 {
981 /* Use the passed DIM= argument. */
982 gcc_assert (expr->value.function.actual->next->expr);
983 gfc_init_se (&argse, NULL);
984 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
985 gfc_array_index_type);
986 gfc_add_block_to_block (&se->pre, &argse.pre);
987 dim_arg = argse.expr;
988
989 if (INTEGER_CST_P (dim_arg))
990 {
991 if (wi::ltu_p (dim_arg, 1)
992 || wi::gtu_p (dim_arg, GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
993 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
994 "dimension index", expr->value.function.isym->name,
995 &expr->where);
996 }
997 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
998 {
999 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
1000 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1001 dim_arg,
1002 build_int_cst (TREE_TYPE (dim_arg), 1));
1003 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
1004 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1005 dim_arg, tmp);
1006 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1007 boolean_type_node, cond, tmp);
1008 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1009 gfc_msg_fault);
1010 }
1011 }
1012
1013 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
1014 one always has a dim_arg argument.
1015
1016 m = this_image() - 1
1017 if (corank == 1)
1018 {
1019 sub(1) = m + lcobound(corank)
1020 return;
1021 }
1022 i = rank
1023 min_var = min (rank + corank - 2, rank + dim_arg - 1)
1024 for (;;)
1025 {
1026 extent = gfc_extent(i)
1027 ml = m
1028 m = m/extent
1029 if (i >= min_var)
1030 goto exit_label
1031 i++
1032 }
1033 exit_label:
1034 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
1035 : m + lcobound(corank)
1036 */
1037
1038 /* this_image () - 1. */
1039 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
1040 integer_zero_node);
1041 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
1042 fold_convert (type, tmp), build_int_cst (type, 1));
1043 if (corank == 1)
1044 {
1045 /* sub(1) = m + lcobound(corank). */
1046 lbound = gfc_conv_descriptor_lbound_get (desc,
1047 build_int_cst (TREE_TYPE (gfc_array_index_type),
1048 corank+rank-1));
1049 lbound = fold_convert (type, lbound);
1050 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
1051
1052 se->expr = tmp;
1053 return;
1054 }
1055
1056 m = gfc_create_var (type, NULL);
1057 ml = gfc_create_var (type, NULL);
1058 loop_var = gfc_create_var (integer_type_node, NULL);
1059 min_var = gfc_create_var (integer_type_node, NULL);
1060
1061 /* m = this_image () - 1. */
1062 gfc_add_modify (&se->pre, m, tmp);
1063
1064 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
1065 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
1066 fold_convert (integer_type_node, dim_arg),
1067 build_int_cst (integer_type_node, rank - 1));
1068 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
1069 build_int_cst (integer_type_node, rank + corank - 2),
1070 tmp);
1071 gfc_add_modify (&se->pre, min_var, tmp);
1072
1073 /* i = rank. */
1074 tmp = build_int_cst (integer_type_node, rank);
1075 gfc_add_modify (&se->pre, loop_var, tmp);
1076
1077 exit_label = gfc_build_label_decl (NULL_TREE);
1078 TREE_USED (exit_label) = 1;
1079
1080 /* Loop body. */
1081 gfc_init_block (&loop);
1082
1083 /* ml = m. */
1084 gfc_add_modify (&loop, ml, m);
1085
1086 /* extent = ... */
1087 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
1088 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
1089 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1090 extent = fold_convert (type, extent);
1091
1092 /* m = m/extent. */
1093 gfc_add_modify (&loop, m,
1094 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
1095 m, extent));
1096
1097 /* Exit condition: if (i >= min_var) goto exit_label. */
1098 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, loop_var,
1099 min_var);
1100 tmp = build1_v (GOTO_EXPR, exit_label);
1101 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
1102 build_empty_stmt (input_location));
1103 gfc_add_expr_to_block (&loop, tmp);
1104
1105 /* Increment loop variable: i++. */
1106 gfc_add_modify (&loop, loop_var,
1107 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
1108 loop_var,
1109 build_int_cst (integer_type_node, 1)));
1110
1111 /* Making the loop... actually loop! */
1112 tmp = gfc_finish_block (&loop);
1113 tmp = build1_v (LOOP_EXPR, tmp);
1114 gfc_add_expr_to_block (&se->pre, tmp);
1115
1116 /* The exit label. */
1117 tmp = build1_v (LABEL_EXPR, exit_label);
1118 gfc_add_expr_to_block (&se->pre, tmp);
1119
1120 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
1121 : m + lcobound(corank) */
1122
1123 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, dim_arg,
1124 build_int_cst (TREE_TYPE (dim_arg), corank));
1125
1126 lbound = gfc_conv_descriptor_lbound_get (desc,
1127 fold_build2_loc (input_location, PLUS_EXPR,
1128 gfc_array_index_type, dim_arg,
1129 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
1130 lbound = fold_convert (type, lbound);
1131
1132 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
1133 fold_build2_loc (input_location, MULT_EXPR, type,
1134 m, extent));
1135 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
1136
1137 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
1138 fold_build2_loc (input_location, PLUS_EXPR, type,
1139 m, lbound));
1140 }
1141
1142
1143 static void
1144 trans_image_index (gfc_se * se, gfc_expr *expr)
1145 {
1146 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
1147 tmp, invalid_bound;
1148 gfc_se argse, subse;
1149 int rank, corank, codim;
1150
1151 type = gfc_get_int_type (gfc_default_integer_kind);
1152 corank = gfc_get_corank (expr->value.function.actual->expr);
1153 rank = expr->value.function.actual->expr->rank;
1154
1155 /* Obtain the descriptor of the COARRAY. */
1156 gfc_init_se (&argse, NULL);
1157 argse.want_coarray = 1;
1158 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
1159 gfc_add_block_to_block (&se->pre, &argse.pre);
1160 gfc_add_block_to_block (&se->post, &argse.post);
1161 desc = argse.expr;
1162
1163 /* Obtain a handle to the SUB argument. */
1164 gfc_init_se (&subse, NULL);
1165 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
1166 gfc_add_block_to_block (&se->pre, &subse.pre);
1167 gfc_add_block_to_block (&se->post, &subse.post);
1168 subdesc = build_fold_indirect_ref_loc (input_location,
1169 gfc_conv_descriptor_data_get (subse.expr));
1170
1171 /* Fortran 2008 does not require that the values remain in the cobounds,
1172 thus we need explicitly check this - and return 0 if they are exceeded. */
1173
1174 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
1175 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
1176 invalid_bound = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1177 fold_convert (gfc_array_index_type, tmp),
1178 lbound);
1179
1180 for (codim = corank + rank - 2; codim >= rank; codim--)
1181 {
1182 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1183 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
1184 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
1185 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1186 fold_convert (gfc_array_index_type, tmp),
1187 lbound);
1188 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1189 boolean_type_node, invalid_bound, cond);
1190 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1191 fold_convert (gfc_array_index_type, tmp),
1192 ubound);
1193 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1194 boolean_type_node, invalid_bound, cond);
1195 }
1196
1197 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
1198
1199 /* See Fortran 2008, C.10 for the following algorithm. */
1200
1201 /* coindex = sub(corank) - lcobound(n). */
1202 coindex = fold_convert (gfc_array_index_type,
1203 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
1204 NULL));
1205 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
1206 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1207 fold_convert (gfc_array_index_type, coindex),
1208 lbound);
1209
1210 for (codim = corank + rank - 2; codim >= rank; codim--)
1211 {
1212 tree extent, ubound;
1213
1214 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
1215 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1216 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
1217 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1218
1219 /* coindex *= extent. */
1220 coindex = fold_build2_loc (input_location, MULT_EXPR,
1221 gfc_array_index_type, coindex, extent);
1222
1223 /* coindex += sub(codim). */
1224 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
1225 coindex = fold_build2_loc (input_location, PLUS_EXPR,
1226 gfc_array_index_type, coindex,
1227 fold_convert (gfc_array_index_type, tmp));
1228
1229 /* coindex -= lbound(codim). */
1230 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1231 coindex = fold_build2_loc (input_location, MINUS_EXPR,
1232 gfc_array_index_type, coindex, lbound);
1233 }
1234
1235 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
1236 fold_convert(type, coindex),
1237 build_int_cst (type, 1));
1238
1239 /* Return 0 if "coindex" exceeds num_images(). */
1240
1241 if (gfc_option.coarray == GFC_FCOARRAY_SINGLE)
1242 num_images = build_int_cst (type, 1);
1243 else
1244 {
1245 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
1246 integer_zero_node,
1247 build_int_cst (integer_type_node, -1));
1248 num_images = fold_convert (type, tmp);
1249 }
1250
1251 tmp = gfc_create_var (type, NULL);
1252 gfc_add_modify (&se->pre, tmp, coindex);
1253
1254 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, tmp,
1255 num_images);
1256 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
1257 cond,
1258 fold_convert (boolean_type_node, invalid_bound));
1259 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
1260 build_int_cst (type, 0), tmp);
1261 }
1262
1263
1264 static void
1265 trans_num_images (gfc_se * se)
1266 {
1267 tree tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
1268 integer_zero_node,
1269 build_int_cst (integer_type_node, -1));
1270 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
1271 }
1272
1273
1274 static void
1275 gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
1276 {
1277 gfc_se argse;
1278
1279 gfc_init_se (&argse, NULL);
1280 argse.data_not_needed = 1;
1281 argse.descriptor_only = 1;
1282
1283 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
1284 gfc_add_block_to_block (&se->pre, &argse.pre);
1285 gfc_add_block_to_block (&se->post, &argse.post);
1286
1287 se->expr = gfc_conv_descriptor_rank (argse.expr);
1288 }
1289
1290
1291 /* Evaluate a single upper or lower bound. */
1292 /* TODO: bound intrinsic generates way too much unnecessary code. */
1293
1294 static void
1295 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
1296 {
1297 gfc_actual_arglist *arg;
1298 gfc_actual_arglist *arg2;
1299 tree desc;
1300 tree type;
1301 tree bound;
1302 tree tmp;
1303 tree cond, cond1, cond3, cond4, size;
1304 tree ubound;
1305 tree lbound;
1306 gfc_se argse;
1307 gfc_array_spec * as;
1308 bool assumed_rank_lb_one;
1309
1310 arg = expr->value.function.actual;
1311 arg2 = arg->next;
1312
1313 if (se->ss)
1314 {
1315 /* Create an implicit second parameter from the loop variable. */
1316 gcc_assert (!arg2->expr);
1317 gcc_assert (se->loop->dimen == 1);
1318 gcc_assert (se->ss->info->expr == expr);
1319 gfc_advance_se_ss_chain (se);
1320 bound = se->loop->loopvar[0];
1321 bound = fold_build2_loc (input_location, MINUS_EXPR,
1322 gfc_array_index_type, bound,
1323 se->loop->from[0]);
1324 }
1325 else
1326 {
1327 /* use the passed argument. */
1328 gcc_assert (arg2->expr);
1329 gfc_init_se (&argse, NULL);
1330 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
1331 gfc_add_block_to_block (&se->pre, &argse.pre);
1332 bound = argse.expr;
1333 /* Convert from one based to zero based. */
1334 bound = fold_build2_loc (input_location, MINUS_EXPR,
1335 gfc_array_index_type, bound,
1336 gfc_index_one_node);
1337 }
1338
1339 /* TODO: don't re-evaluate the descriptor on each iteration. */
1340 /* Get a descriptor for the first parameter. */
1341 gfc_init_se (&argse, NULL);
1342 gfc_conv_expr_descriptor (&argse, arg->expr);
1343 gfc_add_block_to_block (&se->pre, &argse.pre);
1344 gfc_add_block_to_block (&se->post, &argse.post);
1345
1346 desc = argse.expr;
1347
1348 as = gfc_get_full_arrayspec_from_expr (arg->expr);
1349
1350 if (INTEGER_CST_P (bound))
1351 {
1352 if (((!as || as->type != AS_ASSUMED_RANK)
1353 && wi::geu_p (bound, GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
1354 || wi::gtu_p (bound, GFC_MAX_DIMENSIONS))
1355 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
1356 "dimension index", upper ? "UBOUND" : "LBOUND",
1357 &expr->where);
1358 }
1359
1360 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
1361 {
1362 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1363 {
1364 bound = gfc_evaluate_now (bound, &se->pre);
1365 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1366 bound, build_int_cst (TREE_TYPE (bound), 0));
1367 if (as && as->type == AS_ASSUMED_RANK)
1368 tmp = gfc_conv_descriptor_rank (desc);
1369 else
1370 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
1371 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1372 bound, fold_convert(TREE_TYPE (bound), tmp));
1373 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1374 boolean_type_node, cond, tmp);
1375 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1376 gfc_msg_fault);
1377 }
1378 }
1379
1380 /* Take care of the lbound shift for assumed-rank arrays, which are
1381 nonallocatable and nonpointers. Those has a lbound of 1. */
1382 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
1383 && ((arg->expr->ts.type != BT_CLASS
1384 && !arg->expr->symtree->n.sym->attr.allocatable
1385 && !arg->expr->symtree->n.sym->attr.pointer)
1386 || (arg->expr->ts.type == BT_CLASS
1387 && !CLASS_DATA (arg->expr)->attr.allocatable
1388 && !CLASS_DATA (arg->expr)->attr.class_pointer));
1389
1390 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
1391 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
1392
1393 /* 13.14.53: Result value for LBOUND
1394
1395 Case (i): For an array section or for an array expression other than a
1396 whole array or array structure component, LBOUND(ARRAY, DIM)
1397 has the value 1. For a whole array or array structure
1398 component, LBOUND(ARRAY, DIM) has the value:
1399 (a) equal to the lower bound for subscript DIM of ARRAY if
1400 dimension DIM of ARRAY does not have extent zero
1401 or if ARRAY is an assumed-size array of rank DIM,
1402 or (b) 1 otherwise.
1403
1404 13.14.113: Result value for UBOUND
1405
1406 Case (i): For an array section or for an array expression other than a
1407 whole array or array structure component, UBOUND(ARRAY, DIM)
1408 has the value equal to the number of elements in the given
1409 dimension; otherwise, it has a value equal to the upper bound
1410 for subscript DIM of ARRAY if dimension DIM of ARRAY does
1411 not have size zero and has value zero if dimension DIM has
1412 size zero. */
1413
1414 if (!upper && assumed_rank_lb_one)
1415 se->expr = gfc_index_one_node;
1416 else if (as)
1417 {
1418 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
1419
1420 cond1 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1421 ubound, lbound);
1422 cond3 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1423 stride, gfc_index_zero_node);
1424 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1425 boolean_type_node, cond3, cond1);
1426 cond4 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1427 stride, gfc_index_zero_node);
1428
1429 if (upper)
1430 {
1431 tree cond5;
1432 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1433 boolean_type_node, cond3, cond4);
1434 cond5 = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1435 gfc_index_one_node, lbound);
1436 cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1437 boolean_type_node, cond4, cond5);
1438
1439 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1440 boolean_type_node, cond, cond5);
1441
1442 if (assumed_rank_lb_one)
1443 {
1444 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1445 gfc_array_index_type, ubound, lbound);
1446 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1447 gfc_array_index_type, tmp, gfc_index_one_node);
1448 }
1449 else
1450 tmp = ubound;
1451
1452 se->expr = fold_build3_loc (input_location, COND_EXPR,
1453 gfc_array_index_type, cond,
1454 tmp, gfc_index_zero_node);
1455 }
1456 else
1457 {
1458 if (as->type == AS_ASSUMED_SIZE)
1459 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1460 bound, build_int_cst (TREE_TYPE (bound),
1461 arg->expr->rank - 1));
1462 else
1463 cond = boolean_false_node;
1464
1465 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1466 boolean_type_node, cond3, cond4);
1467 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1468 boolean_type_node, cond, cond1);
1469
1470 se->expr = fold_build3_loc (input_location, COND_EXPR,
1471 gfc_array_index_type, cond,
1472 lbound, gfc_index_one_node);
1473 }
1474 }
1475 else
1476 {
1477 if (upper)
1478 {
1479 size = fold_build2_loc (input_location, MINUS_EXPR,
1480 gfc_array_index_type, ubound, lbound);
1481 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
1482 gfc_array_index_type, size,
1483 gfc_index_one_node);
1484 se->expr = fold_build2_loc (input_location, MAX_EXPR,
1485 gfc_array_index_type, se->expr,
1486 gfc_index_zero_node);
1487 }
1488 else
1489 se->expr = gfc_index_one_node;
1490 }
1491
1492 type = gfc_typenode_for_spec (&expr->ts);
1493 se->expr = convert (type, se->expr);
1494 }
1495
1496
1497 static void
1498 conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
1499 {
1500 gfc_actual_arglist *arg;
1501 gfc_actual_arglist *arg2;
1502 gfc_se argse;
1503 tree bound, resbound, resbound2, desc, cond, tmp;
1504 tree type;
1505 int corank;
1506
1507 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
1508 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
1509 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
1510
1511 arg = expr->value.function.actual;
1512 arg2 = arg->next;
1513
1514 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
1515 corank = gfc_get_corank (arg->expr);
1516
1517 gfc_init_se (&argse, NULL);
1518 argse.want_coarray = 1;
1519
1520 gfc_conv_expr_descriptor (&argse, arg->expr);
1521 gfc_add_block_to_block (&se->pre, &argse.pre);
1522 gfc_add_block_to_block (&se->post, &argse.post);
1523 desc = argse.expr;
1524
1525 if (se->ss)
1526 {
1527 /* Create an implicit second parameter from the loop variable. */
1528 gcc_assert (!arg2->expr);
1529 gcc_assert (corank > 0);
1530 gcc_assert (se->loop->dimen == 1);
1531 gcc_assert (se->ss->info->expr == expr);
1532
1533 bound = se->loop->loopvar[0];
1534 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1535 bound, gfc_rank_cst[arg->expr->rank]);
1536 gfc_advance_se_ss_chain (se);
1537 }
1538 else
1539 {
1540 /* use the passed argument. */
1541 gcc_assert (arg2->expr);
1542 gfc_init_se (&argse, NULL);
1543 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
1544 gfc_add_block_to_block (&se->pre, &argse.pre);
1545 bound = argse.expr;
1546
1547 if (INTEGER_CST_P (bound))
1548 {
1549 if (wi::ltu_p (bound, 1)
1550 || wi::gtu_p (bound, GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
1551 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
1552 "dimension index", expr->value.function.isym->name,
1553 &expr->where);
1554 }
1555 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1556 {
1557 bound = gfc_evaluate_now (bound, &se->pre);
1558 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1559 bound, build_int_cst (TREE_TYPE (bound), 1));
1560 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
1561 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1562 bound, tmp);
1563 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1564 boolean_type_node, cond, tmp);
1565 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1566 gfc_msg_fault);
1567 }
1568
1569
1570 /* Subtract 1 to get to zero based and add dimensions. */
1571 switch (arg->expr->rank)
1572 {
1573 case 0:
1574 bound = fold_build2_loc (input_location, MINUS_EXPR,
1575 gfc_array_index_type, bound,
1576 gfc_index_one_node);
1577 case 1:
1578 break;
1579 default:
1580 bound = fold_build2_loc (input_location, PLUS_EXPR,
1581 gfc_array_index_type, bound,
1582 gfc_rank_cst[arg->expr->rank - 1]);
1583 }
1584 }
1585
1586 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
1587
1588 /* Handle UCOBOUND with special handling of the last codimension. */
1589 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
1590 {
1591 /* Last codimension: For -fcoarray=single just return
1592 the lcobound - otherwise add
1593 ceiling (real (num_images ()) / real (size)) - 1
1594 = (num_images () + size - 1) / size - 1
1595 = (num_images - 1) / size(),
1596 where size is the product of the extent of all but the last
1597 codimension. */
1598
1599 if (gfc_option.coarray != GFC_FCOARRAY_SINGLE && corank > 1)
1600 {
1601 tree cosize;
1602
1603 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
1604 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
1605 2, integer_zero_node,
1606 build_int_cst (integer_type_node, -1));
1607 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1608 gfc_array_index_type,
1609 fold_convert (gfc_array_index_type, tmp),
1610 build_int_cst (gfc_array_index_type, 1));
1611 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1612 gfc_array_index_type, tmp,
1613 fold_convert (gfc_array_index_type, cosize));
1614 resbound = fold_build2_loc (input_location, PLUS_EXPR,
1615 gfc_array_index_type, resbound, tmp);
1616 }
1617 else if (gfc_option.coarray != GFC_FCOARRAY_SINGLE)
1618 {
1619 /* ubound = lbound + num_images() - 1. */
1620 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
1621 2, integer_zero_node,
1622 build_int_cst (integer_type_node, -1));
1623 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1624 gfc_array_index_type,
1625 fold_convert (gfc_array_index_type, tmp),
1626 build_int_cst (gfc_array_index_type, 1));
1627 resbound = fold_build2_loc (input_location, PLUS_EXPR,
1628 gfc_array_index_type, resbound, tmp);
1629 }
1630
1631 if (corank > 1)
1632 {
1633 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1634 bound,
1635 build_int_cst (TREE_TYPE (bound),
1636 arg->expr->rank + corank - 1));
1637
1638 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
1639 se->expr = fold_build3_loc (input_location, COND_EXPR,
1640 gfc_array_index_type, cond,
1641 resbound, resbound2);
1642 }
1643 else
1644 se->expr = resbound;
1645 }
1646 else
1647 se->expr = resbound;
1648
1649 type = gfc_typenode_for_spec (&expr->ts);
1650 se->expr = convert (type, se->expr);
1651 }
1652
1653
1654 static void
1655 conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
1656 {
1657 gfc_actual_arglist *array_arg;
1658 gfc_actual_arglist *dim_arg;
1659 gfc_se argse;
1660 tree desc, tmp;
1661
1662 array_arg = expr->value.function.actual;
1663 dim_arg = array_arg->next;
1664
1665 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
1666
1667 gfc_init_se (&argse, NULL);
1668 gfc_conv_expr_descriptor (&argse, array_arg->expr);
1669 gfc_add_block_to_block (&se->pre, &argse.pre);
1670 gfc_add_block_to_block (&se->post, &argse.post);
1671 desc = argse.expr;
1672
1673 gcc_assert (dim_arg->expr);
1674 gfc_init_se (&argse, NULL);
1675 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
1676 gfc_add_block_to_block (&se->pre, &argse.pre);
1677 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1678 argse.expr, gfc_index_one_node);
1679 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
1680 }
1681
1682
1683 static void
1684 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
1685 {
1686 tree arg, cabs;
1687
1688 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
1689
1690 switch (expr->value.function.actual->expr->ts.type)
1691 {
1692 case BT_INTEGER:
1693 case BT_REAL:
1694 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
1695 arg);
1696 break;
1697
1698 case BT_COMPLEX:
1699 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
1700 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
1701 break;
1702
1703 default:
1704 gcc_unreachable ();
1705 }
1706 }
1707
1708
1709 /* Create a complex value from one or two real components. */
1710
1711 static void
1712 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
1713 {
1714 tree real;
1715 tree imag;
1716 tree type;
1717 tree *args;
1718 unsigned int num_args;
1719
1720 num_args = gfc_intrinsic_argument_list_length (expr);
1721 args = XALLOCAVEC (tree, num_args);
1722
1723 type = gfc_typenode_for_spec (&expr->ts);
1724 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
1725 real = convert (TREE_TYPE (type), args[0]);
1726 if (both)
1727 imag = convert (TREE_TYPE (type), args[1]);
1728 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
1729 {
1730 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
1731 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
1732 imag = convert (TREE_TYPE (type), imag);
1733 }
1734 else
1735 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
1736
1737 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
1738 }
1739
1740
1741 /* Remainder function MOD(A, P) = A - INT(A / P) * P
1742 MODULO(A, P) = A - FLOOR (A / P) * P
1743
1744 The obvious algorithms above are numerically instable for large
1745 arguments, hence these intrinsics are instead implemented via calls
1746 to the fmod family of functions. It is the responsibility of the
1747 user to ensure that the second argument is non-zero. */
1748
1749 static void
1750 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
1751 {
1752 tree type;
1753 tree tmp;
1754 tree test;
1755 tree test2;
1756 tree fmod;
1757 tree zero;
1758 tree args[2];
1759
1760 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1761
1762 switch (expr->ts.type)
1763 {
1764 case BT_INTEGER:
1765 /* Integer case is easy, we've got a builtin op. */
1766 type = TREE_TYPE (args[0]);
1767
1768 if (modulo)
1769 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
1770 args[0], args[1]);
1771 else
1772 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
1773 args[0], args[1]);
1774 break;
1775
1776 case BT_REAL:
1777 fmod = NULL_TREE;
1778 /* Check if we have a builtin fmod. */
1779 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
1780
1781 /* The builtin should always be available. */
1782 gcc_assert (fmod != NULL_TREE);
1783
1784 tmp = build_addr (fmod, current_function_decl);
1785 se->expr = build_call_array_loc (input_location,
1786 TREE_TYPE (TREE_TYPE (fmod)),
1787 tmp, 2, args);
1788 if (modulo == 0)
1789 return;
1790
1791 type = TREE_TYPE (args[0]);
1792
1793 args[0] = gfc_evaluate_now (args[0], &se->pre);
1794 args[1] = gfc_evaluate_now (args[1], &se->pre);
1795
1796 /* Definition:
1797 modulo = arg - floor (arg/arg2) * arg2
1798
1799 In order to calculate the result accurately, we use the fmod
1800 function as follows.
1801
1802 res = fmod (arg, arg2);
1803 if (res)
1804 {
1805 if ((arg < 0) xor (arg2 < 0))
1806 res += arg2;
1807 }
1808 else
1809 res = copysign (0., arg2);
1810
1811 => As two nested ternary exprs:
1812
1813 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
1814 : copysign (0., arg2);
1815
1816 */
1817
1818 zero = gfc_build_const (type, integer_zero_node);
1819 tmp = gfc_evaluate_now (se->expr, &se->pre);
1820 if (!flag_signed_zeros)
1821 {
1822 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1823 args[0], zero);
1824 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1825 args[1], zero);
1826 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
1827 boolean_type_node, test, test2);
1828 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1829 tmp, zero);
1830 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1831 boolean_type_node, test, test2);
1832 test = gfc_evaluate_now (test, &se->pre);
1833 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
1834 fold_build2_loc (input_location,
1835 PLUS_EXPR,
1836 type, tmp, args[1]),
1837 tmp);
1838 }
1839 else
1840 {
1841 tree expr1, copysign, cscall;
1842 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
1843 expr->ts.kind);
1844 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1845 args[0], zero);
1846 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1847 args[1], zero);
1848 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
1849 boolean_type_node, test, test2);
1850 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
1851 fold_build2_loc (input_location,
1852 PLUS_EXPR,
1853 type, tmp, args[1]),
1854 tmp);
1855 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1856 tmp, zero);
1857 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
1858 args[1]);
1859 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
1860 expr1, cscall);
1861 }
1862 return;
1863
1864 default:
1865 gcc_unreachable ();
1866 }
1867 }
1868
1869 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
1870 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
1871 where the right shifts are logical (i.e. 0's are shifted in).
1872 Because SHIFT_EXPR's want shifts strictly smaller than the integral
1873 type width, we have to special-case both S == 0 and S == BITSIZE(J):
1874 DSHIFTL(I,J,0) = I
1875 DSHIFTL(I,J,BITSIZE) = J
1876 DSHIFTR(I,J,0) = J
1877 DSHIFTR(I,J,BITSIZE) = I. */
1878
1879 static void
1880 gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
1881 {
1882 tree type, utype, stype, arg1, arg2, shift, res, left, right;
1883 tree args[3], cond, tmp;
1884 int bitsize;
1885
1886 gfc_conv_intrinsic_function_args (se, expr, args, 3);
1887
1888 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
1889 type = TREE_TYPE (args[0]);
1890 bitsize = TYPE_PRECISION (type);
1891 utype = unsigned_type_for (type);
1892 stype = TREE_TYPE (args[2]);
1893
1894 arg1 = gfc_evaluate_now (args[0], &se->pre);
1895 arg2 = gfc_evaluate_now (args[1], &se->pre);
1896 shift = gfc_evaluate_now (args[2], &se->pre);
1897
1898 /* The generic case. */
1899 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
1900 build_int_cst (stype, bitsize), shift);
1901 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
1902 arg1, dshiftl ? shift : tmp);
1903
1904 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
1905 fold_convert (utype, arg2), dshiftl ? tmp : shift);
1906 right = fold_convert (type, right);
1907
1908 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
1909
1910 /* Special cases. */
1911 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
1912 build_int_cst (stype, 0));
1913 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
1914 dshiftl ? arg1 : arg2, res);
1915
1916 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
1917 build_int_cst (stype, bitsize));
1918 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
1919 dshiftl ? arg2 : arg1, res);
1920
1921 se->expr = res;
1922 }
1923
1924
1925 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
1926
1927 static void
1928 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
1929 {
1930 tree val;
1931 tree tmp;
1932 tree type;
1933 tree zero;
1934 tree args[2];
1935
1936 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1937 type = TREE_TYPE (args[0]);
1938
1939 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
1940 val = gfc_evaluate_now (val, &se->pre);
1941
1942 zero = gfc_build_const (type, integer_zero_node);
1943 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, val, zero);
1944 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
1945 }
1946
1947
1948 /* SIGN(A, B) is absolute value of A times sign of B.
1949 The real value versions use library functions to ensure the correct
1950 handling of negative zero. Integer case implemented as:
1951 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
1952 */
1953
1954 static void
1955 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
1956 {
1957 tree tmp;
1958 tree type;
1959 tree args[2];
1960
1961 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1962 if (expr->ts.type == BT_REAL)
1963 {
1964 tree abs;
1965
1966 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
1967 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
1968
1969 /* We explicitly have to ignore the minus sign. We do so by using
1970 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
1971 if (!gfc_option.flag_sign_zero
1972 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
1973 {
1974 tree cond, zero;
1975 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
1976 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1977 args[1], zero);
1978 se->expr = fold_build3_loc (input_location, COND_EXPR,
1979 TREE_TYPE (args[0]), cond,
1980 build_call_expr_loc (input_location, abs, 1,
1981 args[0]),
1982 build_call_expr_loc (input_location, tmp, 2,
1983 args[0], args[1]));
1984 }
1985 else
1986 se->expr = build_call_expr_loc (input_location, tmp, 2,
1987 args[0], args[1]);
1988 return;
1989 }
1990
1991 /* Having excluded floating point types, we know we are now dealing
1992 with signed integer types. */
1993 type = TREE_TYPE (args[0]);
1994
1995 /* Args[0] is used multiple times below. */
1996 args[0] = gfc_evaluate_now (args[0], &se->pre);
1997
1998 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
1999 the signs of A and B are the same, and of all ones if they differ. */
2000 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
2001 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
2002 build_int_cst (type, TYPE_PRECISION (type) - 1));
2003 tmp = gfc_evaluate_now (tmp, &se->pre);
2004
2005 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
2006 is all ones (i.e. -1). */
2007 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
2008 fold_build2_loc (input_location, PLUS_EXPR,
2009 type, args[0], tmp), tmp);
2010 }
2011
2012
2013 /* Test for the presence of an optional argument. */
2014
2015 static void
2016 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
2017 {
2018 gfc_expr *arg;
2019
2020 arg = expr->value.function.actual->expr;
2021 gcc_assert (arg->expr_type == EXPR_VARIABLE);
2022 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
2023 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
2024 }
2025
2026
2027 /* Calculate the double precision product of two single precision values. */
2028
2029 static void
2030 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
2031 {
2032 tree type;
2033 tree args[2];
2034
2035 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2036
2037 /* Convert the args to double precision before multiplying. */
2038 type = gfc_typenode_for_spec (&expr->ts);
2039 args[0] = convert (type, args[0]);
2040 args[1] = convert (type, args[1]);
2041 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
2042 args[1]);
2043 }
2044
2045
2046 /* Return a length one character string containing an ascii character. */
2047
2048 static void
2049 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
2050 {
2051 tree arg[2];
2052 tree var;
2053 tree type;
2054 unsigned int num_args;
2055
2056 num_args = gfc_intrinsic_argument_list_length (expr);
2057 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
2058
2059 type = gfc_get_char_type (expr->ts.kind);
2060 var = gfc_create_var (type, "char");
2061
2062 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
2063 gfc_add_modify (&se->pre, var, arg[0]);
2064 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
2065 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
2066 }
2067
2068
2069 static void
2070 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
2071 {
2072 tree var;
2073 tree len;
2074 tree tmp;
2075 tree cond;
2076 tree fndecl;
2077 tree *args;
2078 unsigned int num_args;
2079
2080 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2081 args = XALLOCAVEC (tree, num_args);
2082
2083 var = gfc_create_var (pchar_type_node, "pstr");
2084 len = gfc_create_var (gfc_charlen_type_node, "len");
2085
2086 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2087 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2088 args[1] = gfc_build_addr_expr (NULL_TREE, len);
2089
2090 fndecl = build_addr (gfor_fndecl_ctime, current_function_decl);
2091 tmp = build_call_array_loc (input_location,
2092 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
2093 fndecl, num_args, args);
2094 gfc_add_expr_to_block (&se->pre, tmp);
2095
2096 /* Free the temporary afterwards, if necessary. */
2097 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2098 len, build_int_cst (TREE_TYPE (len), 0));
2099 tmp = gfc_call_free (var);
2100 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2101 gfc_add_expr_to_block (&se->post, tmp);
2102
2103 se->expr = var;
2104 se->string_length = len;
2105 }
2106
2107
2108 static void
2109 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
2110 {
2111 tree var;
2112 tree len;
2113 tree tmp;
2114 tree cond;
2115 tree fndecl;
2116 tree *args;
2117 unsigned int num_args;
2118
2119 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2120 args = XALLOCAVEC (tree, num_args);
2121
2122 var = gfc_create_var (pchar_type_node, "pstr");
2123 len = gfc_create_var (gfc_charlen_type_node, "len");
2124
2125 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2126 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2127 args[1] = gfc_build_addr_expr (NULL_TREE, len);
2128
2129 fndecl = build_addr (gfor_fndecl_fdate, current_function_decl);
2130 tmp = build_call_array_loc (input_location,
2131 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
2132 fndecl, num_args, args);
2133 gfc_add_expr_to_block (&se->pre, tmp);
2134
2135 /* Free the temporary afterwards, if necessary. */
2136 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2137 len, build_int_cst (TREE_TYPE (len), 0));
2138 tmp = gfc_call_free (var);
2139 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2140 gfc_add_expr_to_block (&se->post, tmp);
2141
2142 se->expr = var;
2143 se->string_length = len;
2144 }
2145
2146
2147 /* Return a character string containing the tty name. */
2148
2149 static void
2150 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
2151 {
2152 tree var;
2153 tree len;
2154 tree tmp;
2155 tree cond;
2156 tree fndecl;
2157 tree *args;
2158 unsigned int num_args;
2159
2160 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
2161 args = XALLOCAVEC (tree, num_args);
2162
2163 var = gfc_create_var (pchar_type_node, "pstr");
2164 len = gfc_create_var (gfc_charlen_type_node, "len");
2165
2166 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
2167 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2168 args[1] = gfc_build_addr_expr (NULL_TREE, len);
2169
2170 fndecl = build_addr (gfor_fndecl_ttynam, current_function_decl);
2171 tmp = build_call_array_loc (input_location,
2172 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
2173 fndecl, num_args, args);
2174 gfc_add_expr_to_block (&se->pre, tmp);
2175
2176 /* Free the temporary afterwards, if necessary. */
2177 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2178 len, build_int_cst (TREE_TYPE (len), 0));
2179 tmp = gfc_call_free (var);
2180 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2181 gfc_add_expr_to_block (&se->post, tmp);
2182
2183 se->expr = var;
2184 se->string_length = len;
2185 }
2186
2187
2188 /* Get the minimum/maximum value of all the parameters.
2189 minmax (a1, a2, a3, ...)
2190 {
2191 mvar = a1;
2192 if (a2 .op. mvar || isnan (mvar))
2193 mvar = a2;
2194 if (a3 .op. mvar || isnan (mvar))
2195 mvar = a3;
2196 ...
2197 return mvar
2198 }
2199 */
2200
2201 /* TODO: Mismatching types can occur when specific names are used.
2202 These should be handled during resolution. */
2203 static void
2204 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
2205 {
2206 tree tmp;
2207 tree mvar;
2208 tree val;
2209 tree thencase;
2210 tree *args;
2211 tree type;
2212 gfc_actual_arglist *argexpr;
2213 unsigned int i, nargs;
2214
2215 nargs = gfc_intrinsic_argument_list_length (expr);
2216 args = XALLOCAVEC (tree, nargs);
2217
2218 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
2219 type = gfc_typenode_for_spec (&expr->ts);
2220
2221 argexpr = expr->value.function.actual;
2222 if (TREE_TYPE (args[0]) != type)
2223 args[0] = convert (type, args[0]);
2224 /* Only evaluate the argument once. */
2225 if (TREE_CODE (args[0]) != VAR_DECL && !TREE_CONSTANT (args[0]))
2226 args[0] = gfc_evaluate_now (args[0], &se->pre);
2227
2228 mvar = gfc_create_var (type, "M");
2229 gfc_add_modify (&se->pre, mvar, args[0]);
2230 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
2231 {
2232 tree cond, isnan;
2233
2234 val = args[i];
2235
2236 /* Handle absent optional arguments by ignoring the comparison. */
2237 if (argexpr->expr->expr_type == EXPR_VARIABLE
2238 && argexpr->expr->symtree->n.sym->attr.optional
2239 && TREE_CODE (val) == INDIRECT_REF)
2240 cond = fold_build2_loc (input_location,
2241 NE_EXPR, boolean_type_node,
2242 TREE_OPERAND (val, 0),
2243 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
2244 else
2245 {
2246 cond = NULL_TREE;
2247
2248 /* Only evaluate the argument once. */
2249 if (TREE_CODE (val) != VAR_DECL && !TREE_CONSTANT (val))
2250 val = gfc_evaluate_now (val, &se->pre);
2251 }
2252
2253 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
2254
2255 tmp = fold_build2_loc (input_location, op, boolean_type_node,
2256 convert (type, val), mvar);
2257
2258 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
2259 __builtin_isnan might be made dependent on that module being loaded,
2260 to help performance of programs that don't rely on IEEE semantics. */
2261 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
2262 {
2263 isnan = build_call_expr_loc (input_location,
2264 builtin_decl_explicit (BUILT_IN_ISNAN),
2265 1, mvar);
2266 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2267 boolean_type_node, tmp,
2268 fold_convert (boolean_type_node, isnan));
2269 }
2270 tmp = build3_v (COND_EXPR, tmp, thencase,
2271 build_empty_stmt (input_location));
2272
2273 if (cond != NULL_TREE)
2274 tmp = build3_v (COND_EXPR, cond, tmp,
2275 build_empty_stmt (input_location));
2276
2277 gfc_add_expr_to_block (&se->pre, tmp);
2278 argexpr = argexpr->next;
2279 }
2280 se->expr = mvar;
2281 }
2282
2283
2284 /* Generate library calls for MIN and MAX intrinsics for character
2285 variables. */
2286 static void
2287 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
2288 {
2289 tree *args;
2290 tree var, len, fndecl, tmp, cond, function;
2291 unsigned int nargs;
2292
2293 nargs = gfc_intrinsic_argument_list_length (expr);
2294 args = XALLOCAVEC (tree, nargs + 4);
2295 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
2296
2297 /* Create the result variables. */
2298 len = gfc_create_var (gfc_charlen_type_node, "len");
2299 args[0] = gfc_build_addr_expr (NULL_TREE, len);
2300 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
2301 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
2302 args[2] = build_int_cst (integer_type_node, op);
2303 args[3] = build_int_cst (integer_type_node, nargs / 2);
2304
2305 if (expr->ts.kind == 1)
2306 function = gfor_fndecl_string_minmax;
2307 else if (expr->ts.kind == 4)
2308 function = gfor_fndecl_string_minmax_char4;
2309 else
2310 gcc_unreachable ();
2311
2312 /* Make the function call. */
2313 fndecl = build_addr (function, current_function_decl);
2314 tmp = build_call_array_loc (input_location,
2315 TREE_TYPE (TREE_TYPE (function)), fndecl,
2316 nargs + 4, args);
2317 gfc_add_expr_to_block (&se->pre, tmp);
2318
2319 /* Free the temporary afterwards, if necessary. */
2320 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2321 len, build_int_cst (TREE_TYPE (len), 0));
2322 tmp = gfc_call_free (var);
2323 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2324 gfc_add_expr_to_block (&se->post, tmp);
2325
2326 se->expr = var;
2327 se->string_length = len;
2328 }
2329
2330
2331 /* Create a symbol node for this intrinsic. The symbol from the frontend
2332 has the generic name. */
2333
2334 static gfc_symbol *
2335 gfc_get_symbol_for_expr (gfc_expr * expr)
2336 {
2337 gfc_symbol *sym;
2338
2339 /* TODO: Add symbols for intrinsic function to the global namespace. */
2340 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
2341 sym = gfc_new_symbol (expr->value.function.name, NULL);
2342
2343 sym->ts = expr->ts;
2344 sym->attr.external = 1;
2345 sym->attr.function = 1;
2346 sym->attr.always_explicit = 1;
2347 sym->attr.proc = PROC_INTRINSIC;
2348 sym->attr.flavor = FL_PROCEDURE;
2349 sym->result = sym;
2350 if (expr->rank > 0)
2351 {
2352 sym->attr.dimension = 1;
2353 sym->as = gfc_get_array_spec ();
2354 sym->as->type = AS_ASSUMED_SHAPE;
2355 sym->as->rank = expr->rank;
2356 }
2357
2358 gfc_copy_formal_args_intr (sym, expr->value.function.isym);
2359
2360 return sym;
2361 }
2362
2363 /* Generate a call to an external intrinsic function. */
2364 static void
2365 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
2366 {
2367 gfc_symbol *sym;
2368 vec<tree, va_gc> *append_args;
2369
2370 gcc_assert (!se->ss || se->ss->info->expr == expr);
2371
2372 if (se->ss)
2373 gcc_assert (expr->rank > 0);
2374 else
2375 gcc_assert (expr->rank == 0);
2376
2377 sym = gfc_get_symbol_for_expr (expr);
2378
2379 /* Calls to libgfortran_matmul need to be appended special arguments,
2380 to be able to call the BLAS ?gemm functions if required and possible. */
2381 append_args = NULL;
2382 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
2383 && sym->ts.type != BT_LOGICAL)
2384 {
2385 tree cint = gfc_get_int_type (gfc_c_int_kind);
2386
2387 if (gfc_option.flag_external_blas
2388 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
2389 && (sym->ts.kind == 4 || sym->ts.kind == 8))
2390 {
2391 tree gemm_fndecl;
2392
2393 if (sym->ts.type == BT_REAL)
2394 {
2395 if (sym->ts.kind == 4)
2396 gemm_fndecl = gfor_fndecl_sgemm;
2397 else
2398 gemm_fndecl = gfor_fndecl_dgemm;
2399 }
2400 else
2401 {
2402 if (sym->ts.kind == 4)
2403 gemm_fndecl = gfor_fndecl_cgemm;
2404 else
2405 gemm_fndecl = gfor_fndecl_zgemm;
2406 }
2407
2408 vec_alloc (append_args, 3);
2409 append_args->quick_push (build_int_cst (cint, 1));
2410 append_args->quick_push (build_int_cst (cint,
2411 gfc_option.blas_matmul_limit));
2412 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
2413 gemm_fndecl));
2414 }
2415 else
2416 {
2417 vec_alloc (append_args, 3);
2418 append_args->quick_push (build_int_cst (cint, 0));
2419 append_args->quick_push (build_int_cst (cint, 0));
2420 append_args->quick_push (null_pointer_node);
2421 }
2422 }
2423
2424 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
2425 append_args);
2426 gfc_free_symbol (sym);
2427 }
2428
2429 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
2430 Implemented as
2431 any(a)
2432 {
2433 forall (i=...)
2434 if (a[i] != 0)
2435 return 1
2436 end forall
2437 return 0
2438 }
2439 all(a)
2440 {
2441 forall (i=...)
2442 if (a[i] == 0)
2443 return 0
2444 end forall
2445 return 1
2446 }
2447 */
2448 static void
2449 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
2450 {
2451 tree resvar;
2452 stmtblock_t block;
2453 stmtblock_t body;
2454 tree type;
2455 tree tmp;
2456 tree found;
2457 gfc_loopinfo loop;
2458 gfc_actual_arglist *actual;
2459 gfc_ss *arrayss;
2460 gfc_se arrayse;
2461 tree exit_label;
2462
2463 if (se->ss)
2464 {
2465 gfc_conv_intrinsic_funcall (se, expr);
2466 return;
2467 }
2468
2469 actual = expr->value.function.actual;
2470 type = gfc_typenode_for_spec (&expr->ts);
2471 /* Initialize the result. */
2472 resvar = gfc_create_var (type, "test");
2473 if (op == EQ_EXPR)
2474 tmp = convert (type, boolean_true_node);
2475 else
2476 tmp = convert (type, boolean_false_node);
2477 gfc_add_modify (&se->pre, resvar, tmp);
2478
2479 /* Walk the arguments. */
2480 arrayss = gfc_walk_expr (actual->expr);
2481 gcc_assert (arrayss != gfc_ss_terminator);
2482
2483 /* Initialize the scalarizer. */
2484 gfc_init_loopinfo (&loop);
2485 exit_label = gfc_build_label_decl (NULL_TREE);
2486 TREE_USED (exit_label) = 1;
2487 gfc_add_ss_to_loop (&loop, arrayss);
2488
2489 /* Initialize the loop. */
2490 gfc_conv_ss_startstride (&loop);
2491 gfc_conv_loop_setup (&loop, &expr->where);
2492
2493 gfc_mark_ss_chain_used (arrayss, 1);
2494 /* Generate the loop body. */
2495 gfc_start_scalarized_body (&loop, &body);
2496
2497 /* If the condition matches then set the return value. */
2498 gfc_start_block (&block);
2499 if (op == EQ_EXPR)
2500 tmp = convert (type, boolean_false_node);
2501 else
2502 tmp = convert (type, boolean_true_node);
2503 gfc_add_modify (&block, resvar, tmp);
2504
2505 /* And break out of the loop. */
2506 tmp = build1_v (GOTO_EXPR, exit_label);
2507 gfc_add_expr_to_block (&block, tmp);
2508
2509 found = gfc_finish_block (&block);
2510
2511 /* Check this element. */
2512 gfc_init_se (&arrayse, NULL);
2513 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2514 arrayse.ss = arrayss;
2515 gfc_conv_expr_val (&arrayse, actual->expr);
2516
2517 gfc_add_block_to_block (&body, &arrayse.pre);
2518 tmp = fold_build2_loc (input_location, op, boolean_type_node, arrayse.expr,
2519 build_int_cst (TREE_TYPE (arrayse.expr), 0));
2520 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
2521 gfc_add_expr_to_block (&body, tmp);
2522 gfc_add_block_to_block (&body, &arrayse.post);
2523
2524 gfc_trans_scalarizing_loops (&loop, &body);
2525
2526 /* Add the exit label. */
2527 tmp = build1_v (LABEL_EXPR, exit_label);
2528 gfc_add_expr_to_block (&loop.pre, tmp);
2529
2530 gfc_add_block_to_block (&se->pre, &loop.pre);
2531 gfc_add_block_to_block (&se->pre, &loop.post);
2532 gfc_cleanup_loop (&loop);
2533
2534 se->expr = resvar;
2535 }
2536
2537 /* COUNT(A) = Number of true elements in A. */
2538 static void
2539 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
2540 {
2541 tree resvar;
2542 tree type;
2543 stmtblock_t body;
2544 tree tmp;
2545 gfc_loopinfo loop;
2546 gfc_actual_arglist *actual;
2547 gfc_ss *arrayss;
2548 gfc_se arrayse;
2549
2550 if (se->ss)
2551 {
2552 gfc_conv_intrinsic_funcall (se, expr);
2553 return;
2554 }
2555
2556 actual = expr->value.function.actual;
2557
2558 type = gfc_typenode_for_spec (&expr->ts);
2559 /* Initialize the result. */
2560 resvar = gfc_create_var (type, "count");
2561 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
2562
2563 /* Walk the arguments. */
2564 arrayss = gfc_walk_expr (actual->expr);
2565 gcc_assert (arrayss != gfc_ss_terminator);
2566
2567 /* Initialize the scalarizer. */
2568 gfc_init_loopinfo (&loop);
2569 gfc_add_ss_to_loop (&loop, arrayss);
2570
2571 /* Initialize the loop. */
2572 gfc_conv_ss_startstride (&loop);
2573 gfc_conv_loop_setup (&loop, &expr->where);
2574
2575 gfc_mark_ss_chain_used (arrayss, 1);
2576 /* Generate the loop body. */
2577 gfc_start_scalarized_body (&loop, &body);
2578
2579 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
2580 resvar, build_int_cst (TREE_TYPE (resvar), 1));
2581 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
2582
2583 gfc_init_se (&arrayse, NULL);
2584 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2585 arrayse.ss = arrayss;
2586 gfc_conv_expr_val (&arrayse, actual->expr);
2587 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
2588 build_empty_stmt (input_location));
2589
2590 gfc_add_block_to_block (&body, &arrayse.pre);
2591 gfc_add_expr_to_block (&body, tmp);
2592 gfc_add_block_to_block (&body, &arrayse.post);
2593
2594 gfc_trans_scalarizing_loops (&loop, &body);
2595
2596 gfc_add_block_to_block (&se->pre, &loop.pre);
2597 gfc_add_block_to_block (&se->pre, &loop.post);
2598 gfc_cleanup_loop (&loop);
2599
2600 se->expr = resvar;
2601 }
2602
2603
2604 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
2605 struct and return the corresponding loopinfo. */
2606
2607 static gfc_loopinfo *
2608 enter_nested_loop (gfc_se *se)
2609 {
2610 se->ss = se->ss->nested_ss;
2611 gcc_assert (se->ss == se->ss->loop->ss);
2612
2613 return se->ss->loop;
2614 }
2615
2616
2617 /* Inline implementation of the sum and product intrinsics. */
2618 static void
2619 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
2620 bool norm2)
2621 {
2622 tree resvar;
2623 tree scale = NULL_TREE;
2624 tree type;
2625 stmtblock_t body;
2626 stmtblock_t block;
2627 tree tmp;
2628 gfc_loopinfo loop, *ploop;
2629 gfc_actual_arglist *arg_array, *arg_mask;
2630 gfc_ss *arrayss = NULL;
2631 gfc_ss *maskss = NULL;
2632 gfc_se arrayse;
2633 gfc_se maskse;
2634 gfc_se *parent_se;
2635 gfc_expr *arrayexpr;
2636 gfc_expr *maskexpr;
2637
2638 if (expr->rank > 0)
2639 {
2640 gcc_assert (gfc_inline_intrinsic_function_p (expr));
2641 parent_se = se;
2642 }
2643 else
2644 parent_se = NULL;
2645
2646 type = gfc_typenode_for_spec (&expr->ts);
2647 /* Initialize the result. */
2648 resvar = gfc_create_var (type, "val");
2649 if (norm2)
2650 {
2651 /* result = 0.0;
2652 scale = 1.0. */
2653 scale = gfc_create_var (type, "scale");
2654 gfc_add_modify (&se->pre, scale,
2655 gfc_build_const (type, integer_one_node));
2656 tmp = gfc_build_const (type, integer_zero_node);
2657 }
2658 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
2659 tmp = gfc_build_const (type, integer_zero_node);
2660 else if (op == NE_EXPR)
2661 /* PARITY. */
2662 tmp = convert (type, boolean_false_node);
2663 else if (op == BIT_AND_EXPR)
2664 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
2665 type, integer_one_node));
2666 else
2667 tmp = gfc_build_const (type, integer_one_node);
2668
2669 gfc_add_modify (&se->pre, resvar, tmp);
2670
2671 arg_array = expr->value.function.actual;
2672
2673 arrayexpr = arg_array->expr;
2674
2675 if (op == NE_EXPR || norm2)
2676 /* PARITY and NORM2. */
2677 maskexpr = NULL;
2678 else
2679 {
2680 arg_mask = arg_array->next->next;
2681 gcc_assert (arg_mask != NULL);
2682 maskexpr = arg_mask->expr;
2683 }
2684
2685 if (expr->rank == 0)
2686 {
2687 /* Walk the arguments. */
2688 arrayss = gfc_walk_expr (arrayexpr);
2689 gcc_assert (arrayss != gfc_ss_terminator);
2690
2691 if (maskexpr && maskexpr->rank > 0)
2692 {
2693 maskss = gfc_walk_expr (maskexpr);
2694 gcc_assert (maskss != gfc_ss_terminator);
2695 }
2696 else
2697 maskss = NULL;
2698
2699 /* Initialize the scalarizer. */
2700 gfc_init_loopinfo (&loop);
2701 gfc_add_ss_to_loop (&loop, arrayss);
2702 if (maskexpr && maskexpr->rank > 0)
2703 gfc_add_ss_to_loop (&loop, maskss);
2704
2705 /* Initialize the loop. */
2706 gfc_conv_ss_startstride (&loop);
2707 gfc_conv_loop_setup (&loop, &expr->where);
2708
2709 gfc_mark_ss_chain_used (arrayss, 1);
2710 if (maskexpr && maskexpr->rank > 0)
2711 gfc_mark_ss_chain_used (maskss, 1);
2712
2713 ploop = &loop;
2714 }
2715 else
2716 /* All the work has been done in the parent loops. */
2717 ploop = enter_nested_loop (se);
2718
2719 gcc_assert (ploop);
2720
2721 /* Generate the loop body. */
2722 gfc_start_scalarized_body (ploop, &body);
2723
2724 /* If we have a mask, only add this element if the mask is set. */
2725 if (maskexpr && maskexpr->rank > 0)
2726 {
2727 gfc_init_se (&maskse, parent_se);
2728 gfc_copy_loopinfo_to_se (&maskse, ploop);
2729 if (expr->rank == 0)
2730 maskse.ss = maskss;
2731 gfc_conv_expr_val (&maskse, maskexpr);
2732 gfc_add_block_to_block (&body, &maskse.pre);
2733
2734 gfc_start_block (&block);
2735 }
2736 else
2737 gfc_init_block (&block);
2738
2739 /* Do the actual summation/product. */
2740 gfc_init_se (&arrayse, parent_se);
2741 gfc_copy_loopinfo_to_se (&arrayse, ploop);
2742 if (expr->rank == 0)
2743 arrayse.ss = arrayss;
2744 gfc_conv_expr_val (&arrayse, arrayexpr);
2745 gfc_add_block_to_block (&block, &arrayse.pre);
2746
2747 if (norm2)
2748 {
2749 /* if (x (i) != 0.0)
2750 {
2751 absX = abs(x(i))
2752 if (absX > scale)
2753 {
2754 val = scale/absX;
2755 result = 1.0 + result * val * val;
2756 scale = absX;
2757 }
2758 else
2759 {
2760 val = absX/scale;
2761 result += val * val;
2762 }
2763 } */
2764 tree res1, res2, cond, absX, val;
2765 stmtblock_t ifblock1, ifblock2, ifblock3;
2766
2767 gfc_init_block (&ifblock1);
2768
2769 absX = gfc_create_var (type, "absX");
2770 gfc_add_modify (&ifblock1, absX,
2771 fold_build1_loc (input_location, ABS_EXPR, type,
2772 arrayse.expr));
2773 val = gfc_create_var (type, "val");
2774 gfc_add_expr_to_block (&ifblock1, val);
2775
2776 gfc_init_block (&ifblock2);
2777 gfc_add_modify (&ifblock2, val,
2778 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
2779 absX));
2780 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
2781 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
2782 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
2783 gfc_build_const (type, integer_one_node));
2784 gfc_add_modify (&ifblock2, resvar, res1);
2785 gfc_add_modify (&ifblock2, scale, absX);
2786 res1 = gfc_finish_block (&ifblock2);
2787
2788 gfc_init_block (&ifblock3);
2789 gfc_add_modify (&ifblock3, val,
2790 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
2791 scale));
2792 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
2793 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
2794 gfc_add_modify (&ifblock3, resvar, res2);
2795 res2 = gfc_finish_block (&ifblock3);
2796
2797 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2798 absX, scale);
2799 tmp = build3_v (COND_EXPR, cond, res1, res2);
2800 gfc_add_expr_to_block (&ifblock1, tmp);
2801 tmp = gfc_finish_block (&ifblock1);
2802
2803 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
2804 arrayse.expr,
2805 gfc_build_const (type, integer_zero_node));
2806
2807 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2808 gfc_add_expr_to_block (&block, tmp);
2809 }
2810 else
2811 {
2812 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
2813 gfc_add_modify (&block, resvar, tmp);
2814 }
2815
2816 gfc_add_block_to_block (&block, &arrayse.post);
2817
2818 if (maskexpr && maskexpr->rank > 0)
2819 {
2820 /* We enclose the above in if (mask) {...} . */
2821
2822 tmp = gfc_finish_block (&block);
2823 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2824 build_empty_stmt (input_location));
2825 }
2826 else
2827 tmp = gfc_finish_block (&block);
2828 gfc_add_expr_to_block (&body, tmp);
2829
2830 gfc_trans_scalarizing_loops (ploop, &body);
2831
2832 /* For a scalar mask, enclose the loop in an if statement. */
2833 if (maskexpr && maskexpr->rank == 0)
2834 {
2835 gfc_init_block (&block);
2836 gfc_add_block_to_block (&block, &ploop->pre);
2837 gfc_add_block_to_block (&block, &ploop->post);
2838 tmp = gfc_finish_block (&block);
2839
2840 if (expr->rank > 0)
2841 {
2842 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
2843 build_empty_stmt (input_location));
2844 gfc_advance_se_ss_chain (se);
2845 }
2846 else
2847 {
2848 gcc_assert (expr->rank == 0);
2849 gfc_init_se (&maskse, NULL);
2850 gfc_conv_expr_val (&maskse, maskexpr);
2851 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2852 build_empty_stmt (input_location));
2853 }
2854
2855 gfc_add_expr_to_block (&block, tmp);
2856 gfc_add_block_to_block (&se->pre, &block);
2857 gcc_assert (se->post.head == NULL);
2858 }
2859 else
2860 {
2861 gfc_add_block_to_block (&se->pre, &ploop->pre);
2862 gfc_add_block_to_block (&se->pre, &ploop->post);
2863 }
2864
2865 if (expr->rank == 0)
2866 gfc_cleanup_loop (ploop);
2867
2868 if (norm2)
2869 {
2870 /* result = scale * sqrt(result). */
2871 tree sqrt;
2872 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
2873 resvar = build_call_expr_loc (input_location,
2874 sqrt, 1, resvar);
2875 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
2876 }
2877
2878 se->expr = resvar;
2879 }
2880
2881
2882 /* Inline implementation of the dot_product intrinsic. This function
2883 is based on gfc_conv_intrinsic_arith (the previous function). */
2884 static void
2885 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
2886 {
2887 tree resvar;
2888 tree type;
2889 stmtblock_t body;
2890 stmtblock_t block;
2891 tree tmp;
2892 gfc_loopinfo loop;
2893 gfc_actual_arglist *actual;
2894 gfc_ss *arrayss1, *arrayss2;
2895 gfc_se arrayse1, arrayse2;
2896 gfc_expr *arrayexpr1, *arrayexpr2;
2897
2898 type = gfc_typenode_for_spec (&expr->ts);
2899
2900 /* Initialize the result. */
2901 resvar = gfc_create_var (type, "val");
2902 if (expr->ts.type == BT_LOGICAL)
2903 tmp = build_int_cst (type, 0);
2904 else
2905 tmp = gfc_build_const (type, integer_zero_node);
2906
2907 gfc_add_modify (&se->pre, resvar, tmp);
2908
2909 /* Walk argument #1. */
2910 actual = expr->value.function.actual;
2911 arrayexpr1 = actual->expr;
2912 arrayss1 = gfc_walk_expr (arrayexpr1);
2913 gcc_assert (arrayss1 != gfc_ss_terminator);
2914
2915 /* Walk argument #2. */
2916 actual = actual->next;
2917 arrayexpr2 = actual->expr;
2918 arrayss2 = gfc_walk_expr (arrayexpr2);
2919 gcc_assert (arrayss2 != gfc_ss_terminator);
2920
2921 /* Initialize the scalarizer. */
2922 gfc_init_loopinfo (&loop);
2923 gfc_add_ss_to_loop (&loop, arrayss1);
2924 gfc_add_ss_to_loop (&loop, arrayss2);
2925
2926 /* Initialize the loop. */
2927 gfc_conv_ss_startstride (&loop);
2928 gfc_conv_loop_setup (&loop, &expr->where);
2929
2930 gfc_mark_ss_chain_used (arrayss1, 1);
2931 gfc_mark_ss_chain_used (arrayss2, 1);
2932
2933 /* Generate the loop body. */
2934 gfc_start_scalarized_body (&loop, &body);
2935 gfc_init_block (&block);
2936
2937 /* Make the tree expression for [conjg(]array1[)]. */
2938 gfc_init_se (&arrayse1, NULL);
2939 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
2940 arrayse1.ss = arrayss1;
2941 gfc_conv_expr_val (&arrayse1, arrayexpr1);
2942 if (expr->ts.type == BT_COMPLEX)
2943 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
2944 arrayse1.expr);
2945 gfc_add_block_to_block (&block, &arrayse1.pre);
2946
2947 /* Make the tree expression for array2. */
2948 gfc_init_se (&arrayse2, NULL);
2949 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
2950 arrayse2.ss = arrayss2;
2951 gfc_conv_expr_val (&arrayse2, arrayexpr2);
2952 gfc_add_block_to_block (&block, &arrayse2.pre);
2953
2954 /* Do the actual product and sum. */
2955 if (expr->ts.type == BT_LOGICAL)
2956 {
2957 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
2958 arrayse1.expr, arrayse2.expr);
2959 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
2960 }
2961 else
2962 {
2963 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
2964 arrayse2.expr);
2965 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
2966 }
2967 gfc_add_modify (&block, resvar, tmp);
2968
2969 /* Finish up the loop block and the loop. */
2970 tmp = gfc_finish_block (&block);
2971 gfc_add_expr_to_block (&body, tmp);
2972
2973 gfc_trans_scalarizing_loops (&loop, &body);
2974 gfc_add_block_to_block (&se->pre, &loop.pre);
2975 gfc_add_block_to_block (&se->pre, &loop.post);
2976 gfc_cleanup_loop (&loop);
2977
2978 se->expr = resvar;
2979 }
2980
2981
2982 /* Emit code for minloc or maxloc intrinsic. There are many different cases
2983 we need to handle. For performance reasons we sometimes create two
2984 loops instead of one, where the second one is much simpler.
2985 Examples for minloc intrinsic:
2986 1) Result is an array, a call is generated
2987 2) Array mask is used and NaNs need to be supported:
2988 limit = Infinity;
2989 pos = 0;
2990 S = from;
2991 while (S <= to) {
2992 if (mask[S]) {
2993 if (pos == 0) pos = S + (1 - from);
2994 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
2995 }
2996 S++;
2997 }
2998 goto lab2;
2999 lab1:;
3000 while (S <= to) {
3001 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3002 S++;
3003 }
3004 lab2:;
3005 3) NaNs need to be supported, but it is known at compile time or cheaply
3006 at runtime whether array is nonempty or not:
3007 limit = Infinity;
3008 pos = 0;
3009 S = from;
3010 while (S <= to) {
3011 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3012 S++;
3013 }
3014 if (from <= to) pos = 1;
3015 goto lab2;
3016 lab1:;
3017 while (S <= to) {
3018 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3019 S++;
3020 }
3021 lab2:;
3022 4) NaNs aren't supported, array mask is used:
3023 limit = infinities_supported ? Infinity : huge (limit);
3024 pos = 0;
3025 S = from;
3026 while (S <= to) {
3027 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3028 S++;
3029 }
3030 goto lab2;
3031 lab1:;
3032 while (S <= to) {
3033 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3034 S++;
3035 }
3036 lab2:;
3037 5) Same without array mask:
3038 limit = infinities_supported ? Infinity : huge (limit);
3039 pos = (from <= to) ? 1 : 0;
3040 S = from;
3041 while (S <= to) {
3042 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3043 S++;
3044 }
3045 For 3) and 5), if mask is scalar, this all goes into a conditional,
3046 setting pos = 0; in the else branch. */
3047
3048 static void
3049 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
3050 {
3051 stmtblock_t body;
3052 stmtblock_t block;
3053 stmtblock_t ifblock;
3054 stmtblock_t elseblock;
3055 tree limit;
3056 tree type;
3057 tree tmp;
3058 tree cond;
3059 tree elsetmp;
3060 tree ifbody;
3061 tree offset;
3062 tree nonempty;
3063 tree lab1, lab2;
3064 gfc_loopinfo loop;
3065 gfc_actual_arglist *actual;
3066 gfc_ss *arrayss;
3067 gfc_ss *maskss;
3068 gfc_se arrayse;
3069 gfc_se maskse;
3070 gfc_expr *arrayexpr;
3071 gfc_expr *maskexpr;
3072 tree pos;
3073 int n;
3074
3075 if (se->ss)
3076 {
3077 gfc_conv_intrinsic_funcall (se, expr);
3078 return;
3079 }
3080
3081 /* Initialize the result. */
3082 pos = gfc_create_var (gfc_array_index_type, "pos");
3083 offset = gfc_create_var (gfc_array_index_type, "offset");
3084 type = gfc_typenode_for_spec (&expr->ts);
3085
3086 /* Walk the arguments. */
3087 actual = expr->value.function.actual;
3088 arrayexpr = actual->expr;
3089 arrayss = gfc_walk_expr (arrayexpr);
3090 gcc_assert (arrayss != gfc_ss_terminator);
3091
3092 actual = actual->next->next;
3093 gcc_assert (actual);
3094 maskexpr = actual->expr;
3095 nonempty = NULL;
3096 if (maskexpr && maskexpr->rank != 0)
3097 {
3098 maskss = gfc_walk_expr (maskexpr);
3099 gcc_assert (maskss != gfc_ss_terminator);
3100 }
3101 else
3102 {
3103 mpz_t asize;
3104 if (gfc_array_size (arrayexpr, &asize))
3105 {
3106 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
3107 mpz_clear (asize);
3108 nonempty = fold_build2_loc (input_location, GT_EXPR,
3109 boolean_type_node, nonempty,
3110 gfc_index_zero_node);
3111 }
3112 maskss = NULL;
3113 }
3114
3115 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
3116 switch (arrayexpr->ts.type)
3117 {
3118 case BT_REAL:
3119 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
3120 break;
3121
3122 case BT_INTEGER:
3123 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
3124 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
3125 arrayexpr->ts.kind);
3126 break;
3127
3128 default:
3129 gcc_unreachable ();
3130 }
3131
3132 /* We start with the most negative possible value for MAXLOC, and the most
3133 positive possible value for MINLOC. The most negative possible value is
3134 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
3135 possible value is HUGE in both cases. */
3136 if (op == GT_EXPR)
3137 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
3138 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
3139 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
3140 build_int_cst (type, 1));
3141
3142 gfc_add_modify (&se->pre, limit, tmp);
3143
3144 /* Initialize the scalarizer. */
3145 gfc_init_loopinfo (&loop);
3146 gfc_add_ss_to_loop (&loop, arrayss);
3147 if (maskss)
3148 gfc_add_ss_to_loop (&loop, maskss);
3149
3150 /* Initialize the loop. */
3151 gfc_conv_ss_startstride (&loop);
3152
3153 /* The code generated can have more than one loop in sequence (see the
3154 comment at the function header). This doesn't work well with the
3155 scalarizer, which changes arrays' offset when the scalarization loops
3156 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
3157 are currently inlined in the scalar case only (for which loop is of rank
3158 one). As there is no dependency to care about in that case, there is no
3159 temporary, so that we can use the scalarizer temporary code to handle
3160 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
3161 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
3162 to restore offset.
3163 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
3164 should eventually go away. We could either create two loops properly,
3165 or find another way to save/restore the array offsets between the two
3166 loops (without conflicting with temporary management), or use a single
3167 loop minmaxloc implementation. See PR 31067. */
3168 loop.temp_dim = loop.dimen;
3169 gfc_conv_loop_setup (&loop, &expr->where);
3170
3171 gcc_assert (loop.dimen == 1);
3172 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
3173 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3174 loop.from[0], loop.to[0]);
3175
3176 lab1 = NULL;
3177 lab2 = NULL;
3178 /* Initialize the position to zero, following Fortran 2003. We are free
3179 to do this because Fortran 95 allows the result of an entirely false
3180 mask to be processor dependent. If we know at compile time the array
3181 is non-empty and no MASK is used, we can initialize to 1 to simplify
3182 the inner loop. */
3183 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
3184 gfc_add_modify (&loop.pre, pos,
3185 fold_build3_loc (input_location, COND_EXPR,
3186 gfc_array_index_type,
3187 nonempty, gfc_index_one_node,
3188 gfc_index_zero_node));
3189 else
3190 {
3191 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
3192 lab1 = gfc_build_label_decl (NULL_TREE);
3193 TREE_USED (lab1) = 1;
3194 lab2 = gfc_build_label_decl (NULL_TREE);
3195 TREE_USED (lab2) = 1;
3196 }
3197
3198 /* An offset must be added to the loop
3199 counter to obtain the required position. */
3200 gcc_assert (loop.from[0]);
3201
3202 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3203 gfc_index_one_node, loop.from[0]);
3204 gfc_add_modify (&loop.pre, offset, tmp);
3205
3206 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
3207 if (maskss)
3208 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
3209 /* Generate the loop body. */
3210 gfc_start_scalarized_body (&loop, &body);
3211
3212 /* If we have a mask, only check this element if the mask is set. */
3213 if (maskss)
3214 {
3215 gfc_init_se (&maskse, NULL);
3216 gfc_copy_loopinfo_to_se (&maskse, &loop);
3217 maskse.ss = maskss;
3218 gfc_conv_expr_val (&maskse, maskexpr);
3219 gfc_add_block_to_block (&body, &maskse.pre);
3220
3221 gfc_start_block (&block);
3222 }
3223 else
3224 gfc_init_block (&block);
3225
3226 /* Compare with the current limit. */
3227 gfc_init_se (&arrayse, NULL);
3228 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3229 arrayse.ss = arrayss;
3230 gfc_conv_expr_val (&arrayse, arrayexpr);
3231 gfc_add_block_to_block (&block, &arrayse.pre);
3232
3233 /* We do the following if this is a more extreme value. */
3234 gfc_start_block (&ifblock);
3235
3236 /* Assign the value to the limit... */
3237 gfc_add_modify (&ifblock, limit, arrayse.expr);
3238
3239 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
3240 {
3241 stmtblock_t ifblock2;
3242 tree ifbody2;
3243
3244 gfc_start_block (&ifblock2);
3245 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3246 loop.loopvar[0], offset);
3247 gfc_add_modify (&ifblock2, pos, tmp);
3248 ifbody2 = gfc_finish_block (&ifblock2);
3249 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, pos,
3250 gfc_index_zero_node);
3251 tmp = build3_v (COND_EXPR, cond, ifbody2,
3252 build_empty_stmt (input_location));
3253 gfc_add_expr_to_block (&block, tmp);
3254 }
3255
3256 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3257 loop.loopvar[0], offset);
3258 gfc_add_modify (&ifblock, pos, tmp);
3259
3260 if (lab1)
3261 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
3262
3263 ifbody = gfc_finish_block (&ifblock);
3264
3265 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
3266 {
3267 if (lab1)
3268 cond = fold_build2_loc (input_location,
3269 op == GT_EXPR ? GE_EXPR : LE_EXPR,
3270 boolean_type_node, arrayse.expr, limit);
3271 else
3272 cond = fold_build2_loc (input_location, op, boolean_type_node,
3273 arrayse.expr, limit);
3274
3275 ifbody = build3_v (COND_EXPR, cond, ifbody,
3276 build_empty_stmt (input_location));
3277 }
3278 gfc_add_expr_to_block (&block, ifbody);
3279
3280 if (maskss)
3281 {
3282 /* We enclose the above in if (mask) {...}. */
3283 tmp = gfc_finish_block (&block);
3284
3285 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3286 build_empty_stmt (input_location));
3287 }
3288 else
3289 tmp = gfc_finish_block (&block);
3290 gfc_add_expr_to_block (&body, tmp);
3291
3292 if (lab1)
3293 {
3294 gfc_trans_scalarized_loop_boundary (&loop, &body);
3295
3296 if (HONOR_NANS (DECL_MODE (limit)))
3297 {
3298 if (nonempty != NULL)
3299 {
3300 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
3301 tmp = build3_v (COND_EXPR, nonempty, ifbody,
3302 build_empty_stmt (input_location));
3303 gfc_add_expr_to_block (&loop.code[0], tmp);
3304 }
3305 }
3306
3307 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
3308 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
3309
3310 /* If we have a mask, only check this element if the mask is set. */
3311 if (maskss)
3312 {
3313 gfc_init_se (&maskse, NULL);
3314 gfc_copy_loopinfo_to_se (&maskse, &loop);
3315 maskse.ss = maskss;
3316 gfc_conv_expr_val (&maskse, maskexpr);
3317 gfc_add_block_to_block (&body, &maskse.pre);
3318
3319 gfc_start_block (&block);
3320 }
3321 else
3322 gfc_init_block (&block);
3323
3324 /* Compare with the current limit. */
3325 gfc_init_se (&arrayse, NULL);
3326 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3327 arrayse.ss = arrayss;
3328 gfc_conv_expr_val (&arrayse, arrayexpr);
3329 gfc_add_block_to_block (&block, &arrayse.pre);
3330
3331 /* We do the following if this is a more extreme value. */
3332 gfc_start_block (&ifblock);
3333
3334 /* Assign the value to the limit... */
3335 gfc_add_modify (&ifblock, limit, arrayse.expr);
3336
3337 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3338 loop.loopvar[0], offset);
3339 gfc_add_modify (&ifblock, pos, tmp);
3340
3341 ifbody = gfc_finish_block (&ifblock);
3342
3343 cond = fold_build2_loc (input_location, op, boolean_type_node,
3344 arrayse.expr, limit);
3345
3346 tmp = build3_v (COND_EXPR, cond, ifbody,
3347 build_empty_stmt (input_location));
3348 gfc_add_expr_to_block (&block, tmp);
3349
3350 if (maskss)
3351 {
3352 /* We enclose the above in if (mask) {...}. */
3353 tmp = gfc_finish_block (&block);
3354
3355 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3356 build_empty_stmt (input_location));
3357 }
3358 else
3359 tmp = gfc_finish_block (&block);
3360 gfc_add_expr_to_block (&body, tmp);
3361 /* Avoid initializing loopvar[0] again, it should be left where
3362 it finished by the first loop. */
3363 loop.from[0] = loop.loopvar[0];
3364 }
3365
3366 gfc_trans_scalarizing_loops (&loop, &body);
3367
3368 if (lab2)
3369 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
3370
3371 /* For a scalar mask, enclose the loop in an if statement. */
3372 if (maskexpr && maskss == NULL)
3373 {
3374 gfc_init_se (&maskse, NULL);
3375 gfc_conv_expr_val (&maskse, maskexpr);
3376 gfc_init_block (&block);
3377 gfc_add_block_to_block (&block, &loop.pre);
3378 gfc_add_block_to_block (&block, &loop.post);
3379 tmp = gfc_finish_block (&block);
3380
3381 /* For the else part of the scalar mask, just initialize
3382 the pos variable the same way as above. */
3383
3384 gfc_init_block (&elseblock);
3385 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
3386 elsetmp = gfc_finish_block (&elseblock);
3387
3388 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
3389 gfc_add_expr_to_block (&block, tmp);
3390 gfc_add_block_to_block (&se->pre, &block);
3391 }
3392 else
3393 {
3394 gfc_add_block_to_block (&se->pre, &loop.pre);
3395 gfc_add_block_to_block (&se->pre, &loop.post);
3396 }
3397 gfc_cleanup_loop (&loop);
3398
3399 se->expr = convert (type, pos);
3400 }
3401
3402 /* Emit code for minval or maxval intrinsic. There are many different cases
3403 we need to handle. For performance reasons we sometimes create two
3404 loops instead of one, where the second one is much simpler.
3405 Examples for minval intrinsic:
3406 1) Result is an array, a call is generated
3407 2) Array mask is used and NaNs need to be supported, rank 1:
3408 limit = Infinity;
3409 nonempty = false;
3410 S = from;
3411 while (S <= to) {
3412 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
3413 S++;
3414 }
3415 limit = nonempty ? NaN : huge (limit);
3416 lab:
3417 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
3418 3) NaNs need to be supported, but it is known at compile time or cheaply
3419 at runtime whether array is nonempty or not, rank 1:
3420 limit = Infinity;
3421 S = from;
3422 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
3423 limit = (from <= to) ? NaN : huge (limit);
3424 lab:
3425 while (S <= to) { limit = min (a[S], limit); S++; }
3426 4) Array mask is used and NaNs need to be supported, rank > 1:
3427 limit = Infinity;
3428 nonempty = false;
3429 fast = false;
3430 S1 = from1;
3431 while (S1 <= to1) {
3432 S2 = from2;
3433 while (S2 <= to2) {
3434 if (mask[S1][S2]) {
3435 if (fast) limit = min (a[S1][S2], limit);
3436 else {
3437 nonempty = true;
3438 if (a[S1][S2] <= limit) {
3439 limit = a[S1][S2];
3440 fast = true;
3441 }
3442 }
3443 }
3444 S2++;
3445 }
3446 S1++;
3447 }
3448 if (!fast)
3449 limit = nonempty ? NaN : huge (limit);
3450 5) NaNs need to be supported, but it is known at compile time or cheaply
3451 at runtime whether array is nonempty or not, rank > 1:
3452 limit = Infinity;
3453 fast = false;
3454 S1 = from1;
3455 while (S1 <= to1) {
3456 S2 = from2;
3457 while (S2 <= to2) {
3458 if (fast) limit = min (a[S1][S2], limit);
3459 else {
3460 if (a[S1][S2] <= limit) {
3461 limit = a[S1][S2];
3462 fast = true;
3463 }
3464 }
3465 S2++;
3466 }
3467 S1++;
3468 }
3469 if (!fast)
3470 limit = (nonempty_array) ? NaN : huge (limit);
3471 6) NaNs aren't supported, but infinities are. Array mask is used:
3472 limit = Infinity;
3473 nonempty = false;
3474 S = from;
3475 while (S <= to) {
3476 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
3477 S++;
3478 }
3479 limit = nonempty ? limit : huge (limit);
3480 7) Same without array mask:
3481 limit = Infinity;
3482 S = from;
3483 while (S <= to) { limit = min (a[S], limit); S++; }
3484 limit = (from <= to) ? limit : huge (limit);
3485 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
3486 limit = huge (limit);
3487 S = from;
3488 while (S <= to) { limit = min (a[S], limit); S++); }
3489 (or
3490 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
3491 with array mask instead).
3492 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
3493 setting limit = huge (limit); in the else branch. */
3494
3495 static void
3496 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
3497 {
3498 tree limit;
3499 tree type;
3500 tree tmp;
3501 tree ifbody;
3502 tree nonempty;
3503 tree nonempty_var;
3504 tree lab;
3505 tree fast;
3506 tree huge_cst = NULL, nan_cst = NULL;
3507 stmtblock_t body;
3508 stmtblock_t block, block2;
3509 gfc_loopinfo loop;
3510 gfc_actual_arglist *actual;
3511 gfc_ss *arrayss;
3512 gfc_ss *maskss;
3513 gfc_se arrayse;
3514 gfc_se maskse;
3515 gfc_expr *arrayexpr;
3516 gfc_expr *maskexpr;
3517 int n;
3518
3519 if (se->ss)
3520 {
3521 gfc_conv_intrinsic_funcall (se, expr);
3522 return;
3523 }
3524
3525 type = gfc_typenode_for_spec (&expr->ts);
3526 /* Initialize the result. */
3527 limit = gfc_create_var (type, "limit");
3528 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
3529 switch (expr->ts.type)
3530 {
3531 case BT_REAL:
3532 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
3533 expr->ts.kind, 0);
3534 if (HONOR_INFINITIES (DECL_MODE (limit)))
3535 {
3536 REAL_VALUE_TYPE real;
3537 real_inf (&real);
3538 tmp = build_real (type, real);
3539 }
3540 else
3541 tmp = huge_cst;
3542 if (HONOR_NANS (DECL_MODE (limit)))
3543 {
3544 REAL_VALUE_TYPE real;
3545 real_nan (&real, "", 1, DECL_MODE (limit));
3546 nan_cst = build_real (type, real);
3547 }
3548 break;
3549
3550 case BT_INTEGER:
3551 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
3552 break;
3553
3554 default:
3555 gcc_unreachable ();
3556 }
3557
3558 /* We start with the most negative possible value for MAXVAL, and the most
3559 positive possible value for MINVAL. The most negative possible value is
3560 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
3561 possible value is HUGE in both cases. */
3562 if (op == GT_EXPR)
3563 {
3564 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
3565 if (huge_cst)
3566 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
3567 TREE_TYPE (huge_cst), huge_cst);
3568 }
3569
3570 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
3571 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
3572 tmp, build_int_cst (type, 1));
3573
3574 gfc_add_modify (&se->pre, limit, tmp);
3575
3576 /* Walk the arguments. */
3577 actual = expr->value.function.actual;
3578 arrayexpr = actual->expr;
3579 arrayss = gfc_walk_expr (arrayexpr);
3580 gcc_assert (arrayss != gfc_ss_terminator);
3581
3582 actual = actual->next->next;
3583 gcc_assert (actual);
3584 maskexpr = actual->expr;
3585 nonempty = NULL;
3586 if (maskexpr && maskexpr->rank != 0)
3587 {
3588 maskss = gfc_walk_expr (maskexpr);
3589 gcc_assert (maskss != gfc_ss_terminator);
3590 }
3591 else
3592 {
3593 mpz_t asize;
3594 if (gfc_array_size (arrayexpr, &asize))
3595 {
3596 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
3597 mpz_clear (asize);
3598 nonempty = fold_build2_loc (input_location, GT_EXPR,
3599 boolean_type_node, nonempty,
3600 gfc_index_zero_node);
3601 }
3602 maskss = NULL;
3603 }
3604
3605 /* Initialize the scalarizer. */
3606 gfc_init_loopinfo (&loop);
3607 gfc_add_ss_to_loop (&loop, arrayss);
3608 if (maskss)
3609 gfc_add_ss_to_loop (&loop, maskss);
3610
3611 /* Initialize the loop. */
3612 gfc_conv_ss_startstride (&loop);
3613
3614 /* The code generated can have more than one loop in sequence (see the
3615 comment at the function header). This doesn't work well with the
3616 scalarizer, which changes arrays' offset when the scalarization loops
3617 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
3618 are currently inlined in the scalar case only. As there is no dependency
3619 to care about in that case, there is no temporary, so that we can use the
3620 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
3621 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
3622 gfc_trans_scalarized_loop_boundary even later to restore offset.
3623 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
3624 should eventually go away. We could either create two loops properly,
3625 or find another way to save/restore the array offsets between the two
3626 loops (without conflicting with temporary management), or use a single
3627 loop minmaxval implementation. See PR 31067. */
3628 loop.temp_dim = loop.dimen;
3629 gfc_conv_loop_setup (&loop, &expr->where);
3630
3631 if (nonempty == NULL && maskss == NULL
3632 && loop.dimen == 1 && loop.from[0] && loop.to[0])
3633 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3634 loop.from[0], loop.to[0]);
3635 nonempty_var = NULL;
3636 if (nonempty == NULL
3637 && (HONOR_INFINITIES (DECL_MODE (limit))
3638 || HONOR_NANS (DECL_MODE (limit))))
3639 {
3640 nonempty_var = gfc_create_var (boolean_type_node, "nonempty");
3641 gfc_add_modify (&se->pre, nonempty_var, boolean_false_node);
3642 nonempty = nonempty_var;
3643 }
3644 lab = NULL;
3645 fast = NULL;
3646 if (HONOR_NANS (DECL_MODE (limit)))
3647 {
3648 if (loop.dimen == 1)
3649 {
3650 lab = gfc_build_label_decl (NULL_TREE);
3651 TREE_USED (lab) = 1;
3652 }
3653 else
3654 {
3655 fast = gfc_create_var (boolean_type_node, "fast");
3656 gfc_add_modify (&se->pre, fast, boolean_false_node);
3657 }
3658 }
3659
3660 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
3661 if (maskss)
3662 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
3663 /* Generate the loop body. */
3664 gfc_start_scalarized_body (&loop, &body);
3665
3666 /* If we have a mask, only add this element if the mask is set. */
3667 if (maskss)
3668 {
3669 gfc_init_se (&maskse, NULL);
3670 gfc_copy_loopinfo_to_se (&maskse, &loop);
3671 maskse.ss = maskss;
3672 gfc_conv_expr_val (&maskse, maskexpr);
3673 gfc_add_block_to_block (&body, &maskse.pre);
3674
3675 gfc_start_block (&block);
3676 }
3677 else
3678 gfc_init_block (&block);
3679
3680 /* Compare with the current limit. */
3681 gfc_init_se (&arrayse, NULL);
3682 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3683 arrayse.ss = arrayss;
3684 gfc_conv_expr_val (&arrayse, arrayexpr);
3685 gfc_add_block_to_block (&block, &arrayse.pre);
3686
3687 gfc_init_block (&block2);
3688
3689 if (nonempty_var)
3690 gfc_add_modify (&block2, nonempty_var, boolean_true_node);
3691
3692 if (HONOR_NANS (DECL_MODE (limit)))
3693 {
3694 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
3695 boolean_type_node, arrayse.expr, limit);
3696 if (lab)
3697 ifbody = build1_v (GOTO_EXPR, lab);
3698 else
3699 {
3700 stmtblock_t ifblock;
3701
3702 gfc_init_block (&ifblock);
3703 gfc_add_modify (&ifblock, limit, arrayse.expr);
3704 gfc_add_modify (&ifblock, fast, boolean_true_node);
3705 ifbody = gfc_finish_block (&ifblock);
3706 }
3707 tmp = build3_v (COND_EXPR, tmp, ifbody,
3708 build_empty_stmt (input_location));
3709 gfc_add_expr_to_block (&block2, tmp);
3710 }
3711 else
3712 {
3713 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3714 signed zeros. */
3715 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3716 {
3717 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3718 arrayse.expr, limit);
3719 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3720 tmp = build3_v (COND_EXPR, tmp, ifbody,
3721 build_empty_stmt (input_location));
3722 gfc_add_expr_to_block (&block2, tmp);
3723 }
3724 else
3725 {
3726 tmp = fold_build2_loc (input_location,
3727 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3728 type, arrayse.expr, limit);
3729 gfc_add_modify (&block2, limit, tmp);
3730 }
3731 }
3732
3733 if (fast)
3734 {
3735 tree elsebody = gfc_finish_block (&block2);
3736
3737 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3738 signed zeros. */
3739 if (HONOR_NANS (DECL_MODE (limit))
3740 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3741 {
3742 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3743 arrayse.expr, limit);
3744 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3745 ifbody = build3_v (COND_EXPR, tmp, ifbody,
3746 build_empty_stmt (input_location));
3747 }
3748 else
3749 {
3750 tmp = fold_build2_loc (input_location,
3751 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3752 type, arrayse.expr, limit);
3753 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
3754 }
3755 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
3756 gfc_add_expr_to_block (&block, tmp);
3757 }
3758 else
3759 gfc_add_block_to_block (&block, &block2);
3760
3761 gfc_add_block_to_block (&block, &arrayse.post);
3762
3763 tmp = gfc_finish_block (&block);
3764 if (maskss)
3765 /* We enclose the above in if (mask) {...}. */
3766 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3767 build_empty_stmt (input_location));
3768 gfc_add_expr_to_block (&body, tmp);
3769
3770 if (lab)
3771 {
3772 gfc_trans_scalarized_loop_boundary (&loop, &body);
3773
3774 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
3775 nan_cst, huge_cst);
3776 gfc_add_modify (&loop.code[0], limit, tmp);
3777 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
3778
3779 /* If we have a mask, only add this element if the mask is set. */
3780 if (maskss)
3781 {
3782 gfc_init_se (&maskse, NULL);
3783 gfc_copy_loopinfo_to_se (&maskse, &loop);
3784 maskse.ss = maskss;
3785 gfc_conv_expr_val (&maskse, maskexpr);
3786 gfc_add_block_to_block (&body, &maskse.pre);
3787
3788 gfc_start_block (&block);
3789 }
3790 else
3791 gfc_init_block (&block);
3792
3793 /* Compare with the current limit. */
3794 gfc_init_se (&arrayse, NULL);
3795 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3796 arrayse.ss = arrayss;
3797 gfc_conv_expr_val (&arrayse, arrayexpr);
3798 gfc_add_block_to_block (&block, &arrayse.pre);
3799
3800 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3801 signed zeros. */
3802 if (HONOR_NANS (DECL_MODE (limit))
3803 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3804 {
3805 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3806 arrayse.expr, limit);
3807 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3808 tmp = build3_v (COND_EXPR, tmp, ifbody,
3809 build_empty_stmt (input_location));
3810 gfc_add_expr_to_block (&block, tmp);
3811 }
3812 else
3813 {
3814 tmp = fold_build2_loc (input_location,
3815 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3816 type, arrayse.expr, limit);
3817 gfc_add_modify (&block, limit, tmp);
3818 }
3819
3820 gfc_add_block_to_block (&block, &arrayse.post);
3821
3822 tmp = gfc_finish_block (&block);
3823 if (maskss)
3824 /* We enclose the above in if (mask) {...}. */
3825 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3826 build_empty_stmt (input_location));
3827 gfc_add_expr_to_block (&body, tmp);
3828 /* Avoid initializing loopvar[0] again, it should be left where
3829 it finished by the first loop. */
3830 loop.from[0] = loop.loopvar[0];
3831 }
3832 gfc_trans_scalarizing_loops (&loop, &body);
3833
3834 if (fast)
3835 {
3836 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
3837 nan_cst, huge_cst);
3838 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
3839 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
3840 ifbody);
3841 gfc_add_expr_to_block (&loop.pre, tmp);
3842 }
3843 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
3844 {
3845 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
3846 huge_cst);
3847 gfc_add_modify (&loop.pre, limit, tmp);
3848 }
3849
3850 /* For a scalar mask, enclose the loop in an if statement. */
3851 if (maskexpr && maskss == NULL)
3852 {
3853 tree else_stmt;
3854
3855 gfc_init_se (&maskse, NULL);
3856 gfc_conv_expr_val (&maskse, maskexpr);
3857 gfc_init_block (&block);
3858 gfc_add_block_to_block (&block, &loop.pre);
3859 gfc_add_block_to_block (&block, &loop.post);
3860 tmp = gfc_finish_block (&block);
3861
3862 if (HONOR_INFINITIES (DECL_MODE (limit)))
3863 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
3864 else
3865 else_stmt = build_empty_stmt (input_location);
3866 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
3867 gfc_add_expr_to_block (&block, tmp);
3868 gfc_add_block_to_block (&se->pre, &block);
3869 }
3870 else
3871 {
3872 gfc_add_block_to_block (&se->pre, &loop.pre);
3873 gfc_add_block_to_block (&se->pre, &loop.post);
3874 }
3875
3876 gfc_cleanup_loop (&loop);
3877
3878 se->expr = limit;
3879 }
3880
3881 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
3882 static void
3883 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
3884 {
3885 tree args[2];
3886 tree type;
3887 tree tmp;
3888
3889 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3890 type = TREE_TYPE (args[0]);
3891
3892 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3893 build_int_cst (type, 1), args[1]);
3894 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
3895 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
3896 build_int_cst (type, 0));
3897 type = gfc_typenode_for_spec (&expr->ts);
3898 se->expr = convert (type, tmp);
3899 }
3900
3901
3902 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
3903 static void
3904 gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
3905 {
3906 tree args[2];
3907
3908 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3909
3910 /* Convert both arguments to the unsigned type of the same size. */
3911 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
3912 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
3913
3914 /* If they have unequal type size, convert to the larger one. */
3915 if (TYPE_PRECISION (TREE_TYPE (args[0]))
3916 > TYPE_PRECISION (TREE_TYPE (args[1])))
3917 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
3918 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
3919 > TYPE_PRECISION (TREE_TYPE (args[0])))
3920 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
3921
3922 /* Now, we compare them. */
3923 se->expr = fold_build2_loc (input_location, op, boolean_type_node,
3924 args[0], args[1]);
3925 }
3926
3927
3928 /* Generate code to perform the specified operation. */
3929 static void
3930 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
3931 {
3932 tree args[2];
3933
3934 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3935 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
3936 args[0], args[1]);
3937 }
3938
3939 /* Bitwise not. */
3940 static void
3941 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
3942 {
3943 tree arg;
3944
3945 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3946 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
3947 TREE_TYPE (arg), arg);
3948 }
3949
3950 /* Set or clear a single bit. */
3951 static void
3952 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
3953 {
3954 tree args[2];
3955 tree type;
3956 tree tmp;
3957 enum tree_code op;
3958
3959 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3960 type = TREE_TYPE (args[0]);
3961
3962 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3963 build_int_cst (type, 1), args[1]);
3964 if (set)
3965 op = BIT_IOR_EXPR;
3966 else
3967 {
3968 op = BIT_AND_EXPR;
3969 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
3970 }
3971 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
3972 }
3973
3974 /* Extract a sequence of bits.
3975 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
3976 static void
3977 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
3978 {
3979 tree args[3];
3980 tree type;
3981 tree tmp;
3982 tree mask;
3983
3984 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3985 type = TREE_TYPE (args[0]);
3986
3987 mask = build_int_cst (type, -1);
3988 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
3989 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
3990
3991 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
3992
3993 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
3994 }
3995
3996 static void
3997 gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
3998 bool arithmetic)
3999 {
4000 tree args[2], type, num_bits, cond;
4001
4002 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4003
4004 args[0] = gfc_evaluate_now (args[0], &se->pre);
4005 args[1] = gfc_evaluate_now (args[1], &se->pre);
4006 type = TREE_TYPE (args[0]);
4007
4008 if (!arithmetic)
4009 args[0] = fold_convert (unsigned_type_for (type), args[0]);
4010 else
4011 gcc_assert (right_shift);
4012
4013 se->expr = fold_build2_loc (input_location,
4014 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
4015 TREE_TYPE (args[0]), args[0], args[1]);
4016
4017 if (!arithmetic)
4018 se->expr = fold_convert (type, se->expr);
4019
4020 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4021 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4022 special case. */
4023 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
4024 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
4025 args[1], num_bits);
4026
4027 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
4028 build_int_cst (type, 0), se->expr);
4029 }
4030
4031 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
4032 ? 0
4033 : ((shift >= 0) ? i << shift : i >> -shift)
4034 where all shifts are logical shifts. */
4035 static void
4036 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
4037 {
4038 tree args[2];
4039 tree type;
4040 tree utype;
4041 tree tmp;
4042 tree width;
4043 tree num_bits;
4044 tree cond;
4045 tree lshift;
4046 tree rshift;
4047
4048 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4049
4050 args[0] = gfc_evaluate_now (args[0], &se->pre);
4051 args[1] = gfc_evaluate_now (args[1], &se->pre);
4052
4053 type = TREE_TYPE (args[0]);
4054 utype = unsigned_type_for (type);
4055
4056 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
4057 args[1]);
4058
4059 /* Left shift if positive. */
4060 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
4061
4062 /* Right shift if negative.
4063 We convert to an unsigned type because we want a logical shift.
4064 The standard doesn't define the case of shifting negative
4065 numbers, and we try to be compatible with other compilers, most
4066 notably g77, here. */
4067 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
4068 utype, convert (utype, args[0]), width));
4069
4070 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, args[1],
4071 build_int_cst (TREE_TYPE (args[1]), 0));
4072 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
4073
4074 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4075 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4076 special case. */
4077 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
4078 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, width,
4079 num_bits);
4080 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
4081 build_int_cst (type, 0), tmp);
4082 }
4083
4084
4085 /* Circular shift. AKA rotate or barrel shift. */
4086
4087 static void
4088 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
4089 {
4090 tree *args;
4091 tree type;
4092 tree tmp;
4093 tree lrot;
4094 tree rrot;
4095 tree zero;
4096 unsigned int num_args;
4097
4098 num_args = gfc_intrinsic_argument_list_length (expr);
4099 args = XALLOCAVEC (tree, num_args);
4100
4101 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4102
4103 if (num_args == 3)
4104 {
4105 /* Use a library function for the 3 parameter version. */
4106 tree int4type = gfc_get_int_type (4);
4107
4108 type = TREE_TYPE (args[0]);
4109 /* We convert the first argument to at least 4 bytes, and
4110 convert back afterwards. This removes the need for library
4111 functions for all argument sizes, and function will be
4112 aligned to at least 32 bits, so there's no loss. */
4113 if (expr->ts.kind < 4)
4114 args[0] = convert (int4type, args[0]);
4115
4116 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
4117 need loads of library functions. They cannot have values >
4118 BIT_SIZE (I) so the conversion is safe. */
4119 args[1] = convert (int4type, args[1]);
4120 args[2] = convert (int4type, args[2]);
4121
4122 switch (expr->ts.kind)
4123 {
4124 case 1:
4125 case 2:
4126 case 4:
4127 tmp = gfor_fndecl_math_ishftc4;
4128 break;
4129 case 8:
4130 tmp = gfor_fndecl_math_ishftc8;
4131 break;
4132 case 16:
4133 tmp = gfor_fndecl_math_ishftc16;
4134 break;
4135 default:
4136 gcc_unreachable ();
4137 }
4138 se->expr = build_call_expr_loc (input_location,
4139 tmp, 3, args[0], args[1], args[2]);
4140 /* Convert the result back to the original type, if we extended
4141 the first argument's width above. */
4142 if (expr->ts.kind < 4)
4143 se->expr = convert (type, se->expr);
4144
4145 return;
4146 }
4147 type = TREE_TYPE (args[0]);
4148
4149 /* Evaluate arguments only once. */
4150 args[0] = gfc_evaluate_now (args[0], &se->pre);
4151 args[1] = gfc_evaluate_now (args[1], &se->pre);
4152
4153 /* Rotate left if positive. */
4154 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
4155
4156 /* Rotate right if negative. */
4157 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
4158 args[1]);
4159 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
4160
4161 zero = build_int_cst (TREE_TYPE (args[1]), 0);
4162 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, args[1],
4163 zero);
4164 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
4165
4166 /* Do nothing if shift == 0. */
4167 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, args[1],
4168 zero);
4169 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
4170 rrot);
4171 }
4172
4173
4174 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
4175 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
4176
4177 The conditional expression is necessary because the result of LEADZ(0)
4178 is defined, but the result of __builtin_clz(0) is undefined for most
4179 targets.
4180
4181 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
4182 difference in bit size between the argument of LEADZ and the C int. */
4183
4184 static void
4185 gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
4186 {
4187 tree arg;
4188 tree arg_type;
4189 tree cond;
4190 tree result_type;
4191 tree leadz;
4192 tree bit_size;
4193 tree tmp;
4194 tree func;
4195 int s, argsize;
4196
4197 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4198 argsize = TYPE_PRECISION (TREE_TYPE (arg));
4199
4200 /* Which variant of __builtin_clz* should we call? */
4201 if (argsize <= INT_TYPE_SIZE)
4202 {
4203 arg_type = unsigned_type_node;
4204 func = builtin_decl_explicit (BUILT_IN_CLZ);
4205 }
4206 else if (argsize <= LONG_TYPE_SIZE)
4207 {
4208 arg_type = long_unsigned_type_node;
4209 func = builtin_decl_explicit (BUILT_IN_CLZL);
4210 }
4211 else if (argsize <= LONG_LONG_TYPE_SIZE)
4212 {
4213 arg_type = long_long_unsigned_type_node;
4214 func = builtin_decl_explicit (BUILT_IN_CLZLL);
4215 }
4216 else
4217 {
4218 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4219 arg_type = gfc_build_uint_type (argsize);
4220 func = NULL_TREE;
4221 }
4222
4223 /* Convert the actual argument twice: first, to the unsigned type of the
4224 same size; then, to the proper argument type for the built-in
4225 function. But the return type is of the default INTEGER kind. */
4226 arg = fold_convert (gfc_build_uint_type (argsize), arg);
4227 arg = fold_convert (arg_type, arg);
4228 arg = gfc_evaluate_now (arg, &se->pre);
4229 result_type = gfc_get_int_type (gfc_default_integer_kind);
4230
4231 /* Compute LEADZ for the case i .ne. 0. */
4232 if (func)
4233 {
4234 s = TYPE_PRECISION (arg_type) - argsize;
4235 tmp = fold_convert (result_type,
4236 build_call_expr_loc (input_location, func,
4237 1, arg));
4238 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
4239 tmp, build_int_cst (result_type, s));
4240 }
4241 else
4242 {
4243 /* We end up here if the argument type is larger than 'long long'.
4244 We generate this code:
4245
4246 if (x & (ULL_MAX << ULL_SIZE) != 0)
4247 return clzll ((unsigned long long) (x >> ULLSIZE));
4248 else
4249 return ULL_SIZE + clzll ((unsigned long long) x);
4250 where ULL_MAX is the largest value that a ULL_MAX can hold
4251 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
4252 is the bit-size of the long long type (64 in this example). */
4253 tree ullsize, ullmax, tmp1, tmp2, btmp;
4254
4255 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
4256 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
4257 long_long_unsigned_type_node,
4258 build_int_cst (long_long_unsigned_type_node,
4259 0));
4260
4261 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
4262 fold_convert (arg_type, ullmax), ullsize);
4263 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
4264 arg, cond);
4265 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
4266 cond, build_int_cst (arg_type, 0));
4267
4268 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
4269 arg, ullsize);
4270 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
4271 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4272 tmp1 = fold_convert (result_type,
4273 build_call_expr_loc (input_location, btmp, 1, tmp1));
4274
4275 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
4276 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4277 tmp2 = fold_convert (result_type,
4278 build_call_expr_loc (input_location, btmp, 1, tmp2));
4279 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4280 tmp2, ullsize);
4281
4282 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
4283 cond, tmp1, tmp2);
4284 }
4285
4286 /* Build BIT_SIZE. */
4287 bit_size = build_int_cst (result_type, argsize);
4288
4289 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4290 arg, build_int_cst (arg_type, 0));
4291 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
4292 bit_size, leadz);
4293 }
4294
4295
4296 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
4297
4298 The conditional expression is necessary because the result of TRAILZ(0)
4299 is defined, but the result of __builtin_ctz(0) is undefined for most
4300 targets. */
4301
4302 static void
4303 gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
4304 {
4305 tree arg;
4306 tree arg_type;
4307 tree cond;
4308 tree result_type;
4309 tree trailz;
4310 tree bit_size;
4311 tree func;
4312 int argsize;
4313
4314 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4315 argsize = TYPE_PRECISION (TREE_TYPE (arg));
4316
4317 /* Which variant of __builtin_ctz* should we call? */
4318 if (argsize <= INT_TYPE_SIZE)
4319 {
4320 arg_type = unsigned_type_node;
4321 func = builtin_decl_explicit (BUILT_IN_CTZ);
4322 }
4323 else if (argsize <= LONG_TYPE_SIZE)
4324 {
4325 arg_type = long_unsigned_type_node;
4326 func = builtin_decl_explicit (BUILT_IN_CTZL);
4327 }
4328 else if (argsize <= LONG_LONG_TYPE_SIZE)
4329 {
4330 arg_type = long_long_unsigned_type_node;
4331 func = builtin_decl_explicit (BUILT_IN_CTZLL);
4332 }
4333 else
4334 {
4335 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4336 arg_type = gfc_build_uint_type (argsize);
4337 func = NULL_TREE;
4338 }
4339
4340 /* Convert the actual argument twice: first, to the unsigned type of the
4341 same size; then, to the proper argument type for the built-in
4342 function. But the return type is of the default INTEGER kind. */
4343 arg = fold_convert (gfc_build_uint_type (argsize), arg);
4344 arg = fold_convert (arg_type, arg);
4345 arg = gfc_evaluate_now (arg, &se->pre);
4346 result_type = gfc_get_int_type (gfc_default_integer_kind);
4347
4348 /* Compute TRAILZ for the case i .ne. 0. */
4349 if (func)
4350 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
4351 func, 1, arg));
4352 else
4353 {
4354 /* We end up here if the argument type is larger than 'long long'.
4355 We generate this code:
4356
4357 if ((x & ULL_MAX) == 0)
4358 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
4359 else
4360 return ctzll ((unsigned long long) x);
4361
4362 where ULL_MAX is the largest value that a ULL_MAX can hold
4363 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
4364 is the bit-size of the long long type (64 in this example). */
4365 tree ullsize, ullmax, tmp1, tmp2, btmp;
4366
4367 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
4368 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
4369 long_long_unsigned_type_node,
4370 build_int_cst (long_long_unsigned_type_node, 0));
4371
4372 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
4373 fold_convert (arg_type, ullmax));
4374 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, cond,
4375 build_int_cst (arg_type, 0));
4376
4377 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
4378 arg, ullsize);
4379 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
4380 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
4381 tmp1 = fold_convert (result_type,
4382 build_call_expr_loc (input_location, btmp, 1, tmp1));
4383 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4384 tmp1, ullsize);
4385
4386 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
4387 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
4388 tmp2 = fold_convert (result_type,
4389 build_call_expr_loc (input_location, btmp, 1, tmp2));
4390
4391 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
4392 cond, tmp1, tmp2);
4393 }
4394
4395 /* Build BIT_SIZE. */
4396 bit_size = build_int_cst (result_type, argsize);
4397
4398 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4399 arg, build_int_cst (arg_type, 0));
4400 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
4401 bit_size, trailz);
4402 }
4403
4404 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
4405 for types larger than "long long", we call the long long built-in for
4406 the lower and higher bits and combine the result. */
4407
4408 static void
4409 gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
4410 {
4411 tree arg;
4412 tree arg_type;
4413 tree result_type;
4414 tree func;
4415 int argsize;
4416
4417 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4418 argsize = TYPE_PRECISION (TREE_TYPE (arg));
4419 result_type = gfc_get_int_type (gfc_default_integer_kind);
4420
4421 /* Which variant of the builtin should we call? */
4422 if (argsize <= INT_TYPE_SIZE)
4423 {
4424 arg_type = unsigned_type_node;
4425 func = builtin_decl_explicit (parity
4426 ? BUILT_IN_PARITY
4427 : BUILT_IN_POPCOUNT);
4428 }
4429 else if (argsize <= LONG_TYPE_SIZE)
4430 {
4431 arg_type = long_unsigned_type_node;
4432 func = builtin_decl_explicit (parity
4433 ? BUILT_IN_PARITYL
4434 : BUILT_IN_POPCOUNTL);
4435 }
4436 else if (argsize <= LONG_LONG_TYPE_SIZE)
4437 {
4438 arg_type = long_long_unsigned_type_node;
4439 func = builtin_decl_explicit (parity
4440 ? BUILT_IN_PARITYLL
4441 : BUILT_IN_POPCOUNTLL);
4442 }
4443 else
4444 {
4445 /* Our argument type is larger than 'long long', which mean none
4446 of the POPCOUNT builtins covers it. We thus call the 'long long'
4447 variant multiple times, and add the results. */
4448 tree utype, arg2, call1, call2;
4449
4450 /* For now, we only cover the case where argsize is twice as large
4451 as 'long long'. */
4452 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4453
4454 func = builtin_decl_explicit (parity
4455 ? BUILT_IN_PARITYLL
4456 : BUILT_IN_POPCOUNTLL);
4457
4458 /* Convert it to an integer, and store into a variable. */
4459 utype = gfc_build_uint_type (argsize);
4460 arg = fold_convert (utype, arg);
4461 arg = gfc_evaluate_now (arg, &se->pre);
4462
4463 /* Call the builtin twice. */
4464 call1 = build_call_expr_loc (input_location, func, 1,
4465 fold_convert (long_long_unsigned_type_node,
4466 arg));
4467
4468 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
4469 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
4470 call2 = build_call_expr_loc (input_location, func, 1,
4471 fold_convert (long_long_unsigned_type_node,
4472 arg2));
4473
4474 /* Combine the results. */
4475 if (parity)
4476 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
4477 call1, call2);
4478 else
4479 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4480 call1, call2);
4481
4482 return;
4483 }
4484
4485 /* Convert the actual argument twice: first, to the unsigned type of the
4486 same size; then, to the proper argument type for the built-in
4487 function. */
4488 arg = fold_convert (gfc_build_uint_type (argsize), arg);
4489 arg = fold_convert (arg_type, arg);
4490
4491 se->expr = fold_convert (result_type,
4492 build_call_expr_loc (input_location, func, 1, arg));
4493 }
4494
4495
4496 /* Process an intrinsic with unspecified argument-types that has an optional
4497 argument (which could be of type character), e.g. EOSHIFT. For those, we
4498 need to append the string length of the optional argument if it is not
4499 present and the type is really character.
4500 primary specifies the position (starting at 1) of the non-optional argument
4501 specifying the type and optional gives the position of the optional
4502 argument in the arglist. */
4503
4504 static void
4505 conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
4506 unsigned primary, unsigned optional)
4507 {
4508 gfc_actual_arglist* prim_arg;
4509 gfc_actual_arglist* opt_arg;
4510 unsigned cur_pos;
4511 gfc_actual_arglist* arg;
4512 gfc_symbol* sym;
4513 vec<tree, va_gc> *append_args;
4514
4515 /* Find the two arguments given as position. */
4516 cur_pos = 0;
4517 prim_arg = NULL;
4518 opt_arg = NULL;
4519 for (arg = expr->value.function.actual; arg; arg = arg->next)
4520 {
4521 ++cur_pos;
4522
4523 if (cur_pos == primary)
4524 prim_arg = arg;
4525 if (cur_pos == optional)
4526 opt_arg = arg;
4527
4528 if (cur_pos >= primary && cur_pos >= optional)
4529 break;
4530 }
4531 gcc_assert (prim_arg);
4532 gcc_assert (prim_arg->expr);
4533 gcc_assert (opt_arg);
4534
4535 /* If we do have type CHARACTER and the optional argument is really absent,
4536 append a dummy 0 as string length. */
4537 append_args = NULL;
4538 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
4539 {
4540 tree dummy;
4541
4542 dummy = build_int_cst (gfc_charlen_type_node, 0);
4543 vec_alloc (append_args, 1);
4544 append_args->quick_push (dummy);
4545 }
4546
4547 /* Build the call itself. */
4548 sym = gfc_get_symbol_for_expr (expr);
4549 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4550 append_args);
4551 gfc_free_symbol (sym);
4552 }
4553
4554
4555 /* The length of a character string. */
4556 static void
4557 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
4558 {
4559 tree len;
4560 tree type;
4561 tree decl;
4562 gfc_symbol *sym;
4563 gfc_se argse;
4564 gfc_expr *arg;
4565
4566 gcc_assert (!se->ss);
4567
4568 arg = expr->value.function.actual->expr;
4569
4570 type = gfc_typenode_for_spec (&expr->ts);
4571 switch (arg->expr_type)
4572 {
4573 case EXPR_CONSTANT:
4574 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
4575 break;
4576
4577 case EXPR_ARRAY:
4578 /* Obtain the string length from the function used by
4579 trans-array.c(gfc_trans_array_constructor). */
4580 len = NULL_TREE;
4581 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
4582 break;
4583
4584 case EXPR_VARIABLE:
4585 if (arg->ref == NULL
4586 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
4587 {
4588 /* This doesn't catch all cases.
4589 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
4590 and the surrounding thread. */
4591 sym = arg->symtree->n.sym;
4592 decl = gfc_get_symbol_decl (sym);
4593 if (decl == current_function_decl && sym->attr.function
4594 && (sym->result == sym))
4595 decl = gfc_get_fake_result_decl (sym, 0);
4596
4597 len = sym->ts.u.cl->backend_decl;
4598 gcc_assert (len);
4599 break;
4600 }
4601
4602 /* Otherwise fall through. */
4603
4604 default:
4605 /* Anybody stupid enough to do this deserves inefficient code. */
4606 gfc_init_se (&argse, se);
4607 if (arg->rank == 0)
4608 gfc_conv_expr (&argse, arg);
4609 else
4610 gfc_conv_expr_descriptor (&argse, arg);
4611 gfc_add_block_to_block (&se->pre, &argse.pre);
4612 gfc_add_block_to_block (&se->post, &argse.post);
4613 len = argse.string_length;
4614 break;
4615 }
4616 se->expr = convert (type, len);
4617 }
4618
4619 /* The length of a character string not including trailing blanks. */
4620 static void
4621 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
4622 {
4623 int kind = expr->value.function.actual->expr->ts.kind;
4624 tree args[2], type, fndecl;
4625
4626 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4627 type = gfc_typenode_for_spec (&expr->ts);
4628
4629 if (kind == 1)
4630 fndecl = gfor_fndecl_string_len_trim;
4631 else if (kind == 4)
4632 fndecl = gfor_fndecl_string_len_trim_char4;
4633 else
4634 gcc_unreachable ();
4635
4636 se->expr = build_call_expr_loc (input_location,
4637 fndecl, 2, args[0], args[1]);
4638 se->expr = convert (type, se->expr);
4639 }
4640
4641
4642 /* Returns the starting position of a substring within a string. */
4643
4644 static void
4645 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
4646 tree function)
4647 {
4648 tree logical4_type_node = gfc_get_logical_type (4);
4649 tree type;
4650 tree fndecl;
4651 tree *args;
4652 unsigned int num_args;
4653
4654 args = XALLOCAVEC (tree, 5);
4655
4656 /* Get number of arguments; characters count double due to the
4657 string length argument. Kind= is not passed to the library
4658 and thus ignored. */
4659 if (expr->value.function.actual->next->next->expr == NULL)
4660 num_args = 4;
4661 else
4662 num_args = 5;
4663
4664 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4665 type = gfc_typenode_for_spec (&expr->ts);
4666
4667 if (num_args == 4)
4668 args[4] = build_int_cst (logical4_type_node, 0);
4669 else
4670 args[4] = convert (logical4_type_node, args[4]);
4671
4672 fndecl = build_addr (function, current_function_decl);
4673 se->expr = build_call_array_loc (input_location,
4674 TREE_TYPE (TREE_TYPE (function)), fndecl,
4675 5, args);
4676 se->expr = convert (type, se->expr);
4677
4678 }
4679
4680 /* The ascii value for a single character. */
4681 static void
4682 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
4683 {
4684 tree args[3], type, pchartype;
4685 int nargs;
4686
4687 nargs = gfc_intrinsic_argument_list_length (expr);
4688 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
4689 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
4690 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
4691 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
4692 type = gfc_typenode_for_spec (&expr->ts);
4693
4694 se->expr = build_fold_indirect_ref_loc (input_location,
4695 args[1]);
4696 se->expr = convert (type, se->expr);
4697 }
4698
4699
4700 /* Intrinsic ISNAN calls __builtin_isnan. */
4701
4702 static void
4703 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
4704 {
4705 tree arg;
4706
4707 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4708 se->expr = build_call_expr_loc (input_location,
4709 builtin_decl_explicit (BUILT_IN_ISNAN),
4710 1, arg);
4711 STRIP_TYPE_NOPS (se->expr);
4712 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
4713 }
4714
4715
4716 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
4717 their argument against a constant integer value. */
4718
4719 static void
4720 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
4721 {
4722 tree arg;
4723
4724 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4725 se->expr = fold_build2_loc (input_location, EQ_EXPR,
4726 gfc_typenode_for_spec (&expr->ts),
4727 arg, build_int_cst (TREE_TYPE (arg), value));
4728 }
4729
4730
4731
4732 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
4733
4734 static void
4735 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
4736 {
4737 tree tsource;
4738 tree fsource;
4739 tree mask;
4740 tree type;
4741 tree len, len2;
4742 tree *args;
4743 unsigned int num_args;
4744
4745 num_args = gfc_intrinsic_argument_list_length (expr);
4746 args = XALLOCAVEC (tree, num_args);
4747
4748 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4749 if (expr->ts.type != BT_CHARACTER)
4750 {
4751 tsource = args[0];
4752 fsource = args[1];
4753 mask = args[2];
4754 }
4755 else
4756 {
4757 /* We do the same as in the non-character case, but the argument
4758 list is different because of the string length arguments. We
4759 also have to set the string length for the result. */
4760 len = args[0];
4761 tsource = args[1];
4762 len2 = args[2];
4763 fsource = args[3];
4764 mask = args[4];
4765
4766 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
4767 &se->pre);
4768 se->string_length = len;
4769 }
4770 type = TREE_TYPE (tsource);
4771 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
4772 fold_convert (type, fsource));
4773 }
4774
4775
4776 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
4777
4778 static void
4779 gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
4780 {
4781 tree args[3], mask, type;
4782
4783 gfc_conv_intrinsic_function_args (se, expr, args, 3);
4784 mask = gfc_evaluate_now (args[2], &se->pre);
4785
4786 type = TREE_TYPE (args[0]);
4787 gcc_assert (TREE_TYPE (args[1]) == type);
4788 gcc_assert (TREE_TYPE (mask) == type);
4789
4790 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
4791 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
4792 fold_build1_loc (input_location, BIT_NOT_EXPR,
4793 type, mask));
4794 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
4795 args[0], args[1]);
4796 }
4797
4798
4799 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
4800 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
4801
4802 static void
4803 gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
4804 {
4805 tree arg, allones, type, utype, res, cond, bitsize;
4806 int i;
4807
4808 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4809 arg = gfc_evaluate_now (arg, &se->pre);
4810
4811 type = gfc_get_int_type (expr->ts.kind);
4812 utype = unsigned_type_for (type);
4813
4814 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
4815 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
4816
4817 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
4818 build_int_cst (utype, 0));
4819
4820 if (left)
4821 {
4822 /* Left-justified mask. */
4823 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
4824 bitsize, arg);
4825 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
4826 fold_convert (utype, res));
4827
4828 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
4829 smaller than type width. */
4830 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
4831 build_int_cst (TREE_TYPE (arg), 0));
4832 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
4833 build_int_cst (utype, 0), res);
4834 }
4835 else
4836 {
4837 /* Right-justified mask. */
4838 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
4839 fold_convert (utype, arg));
4840 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
4841
4842 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
4843 strictly smaller than type width. */
4844 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4845 arg, bitsize);
4846 res = fold_build3_loc (input_location, COND_EXPR, utype,
4847 cond, allones, res);
4848 }
4849
4850 se->expr = fold_convert (type, res);
4851 }
4852
4853
4854 /* FRACTION (s) is translated into frexp (s, &dummy_int). */
4855 static void
4856 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
4857 {
4858 tree arg, type, tmp, frexp;
4859
4860 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4861
4862 type = gfc_typenode_for_spec (&expr->ts);
4863 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4864 tmp = gfc_create_var (integer_type_node, NULL);
4865 se->expr = build_call_expr_loc (input_location, frexp, 2,
4866 fold_convert (type, arg),
4867 gfc_build_addr_expr (NULL_TREE, tmp));
4868 se->expr = fold_convert (type, se->expr);
4869 }
4870
4871
4872 /* NEAREST (s, dir) is translated into
4873 tmp = copysign (HUGE_VAL, dir);
4874 return nextafter (s, tmp);
4875 */
4876 static void
4877 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
4878 {
4879 tree args[2], type, tmp, nextafter, copysign, huge_val;
4880
4881 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
4882 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
4883
4884 type = gfc_typenode_for_spec (&expr->ts);
4885 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4886
4887 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
4888 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
4889 fold_convert (type, args[1]));
4890 se->expr = build_call_expr_loc (input_location, nextafter, 2,
4891 fold_convert (type, args[0]), tmp);
4892 se->expr = fold_convert (type, se->expr);
4893 }
4894
4895
4896 /* SPACING (s) is translated into
4897 int e;
4898 if (s == 0)
4899 res = tiny;
4900 else
4901 {
4902 frexp (s, &e);
4903 e = e - prec;
4904 e = MAX_EXPR (e, emin);
4905 res = scalbn (1., e);
4906 }
4907 return res;
4908
4909 where prec is the precision of s, gfc_real_kinds[k].digits,
4910 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
4911 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
4912
4913 static void
4914 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
4915 {
4916 tree arg, type, prec, emin, tiny, res, e;
4917 tree cond, tmp, frexp, scalbn;
4918 int k;
4919 stmtblock_t block;
4920
4921 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
4922 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
4923 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
4924 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
4925
4926 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4927 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
4928
4929 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4930 arg = gfc_evaluate_now (arg, &se->pre);
4931
4932 type = gfc_typenode_for_spec (&expr->ts);
4933 e = gfc_create_var (integer_type_node, NULL);
4934 res = gfc_create_var (type, NULL);
4935
4936
4937 /* Build the block for s /= 0. */
4938 gfc_start_block (&block);
4939 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
4940 gfc_build_addr_expr (NULL_TREE, e));
4941 gfc_add_expr_to_block (&block, tmp);
4942
4943 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
4944 prec);
4945 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
4946 integer_type_node, tmp, emin));
4947
4948 tmp = build_call_expr_loc (input_location, scalbn, 2,
4949 build_real_from_int_cst (type, integer_one_node), e);
4950 gfc_add_modify (&block, res, tmp);
4951
4952 /* Finish by building the IF statement. */
4953 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
4954 build_real_from_int_cst (type, integer_zero_node));
4955 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
4956 gfc_finish_block (&block));
4957
4958 gfc_add_expr_to_block (&se->pre, tmp);
4959 se->expr = res;
4960 }
4961
4962
4963 /* RRSPACING (s) is translated into
4964 int e;
4965 real x;
4966 x = fabs (s);
4967 if (x != 0)
4968 {
4969 frexp (s, &e);
4970 x = scalbn (x, precision - e);
4971 }
4972 return x;
4973
4974 where precision is gfc_real_kinds[k].digits. */
4975
4976 static void
4977 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
4978 {
4979 tree arg, type, e, x, cond, stmt, tmp, frexp, scalbn, fabs;
4980 int prec, k;
4981 stmtblock_t block;
4982
4983 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
4984 prec = gfc_real_kinds[k].digits;
4985
4986 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4987 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
4988 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
4989
4990 type = gfc_typenode_for_spec (&expr->ts);
4991 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4992 arg = gfc_evaluate_now (arg, &se->pre);
4993
4994 e = gfc_create_var (integer_type_node, NULL);
4995 x = gfc_create_var (type, NULL);
4996 gfc_add_modify (&se->pre, x,
4997 build_call_expr_loc (input_location, fabs, 1, arg));
4998
4999
5000 gfc_start_block (&block);
5001 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
5002 gfc_build_addr_expr (NULL_TREE, e));
5003 gfc_add_expr_to_block (&block, tmp);
5004
5005 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
5006 build_int_cst (integer_type_node, prec), e);
5007 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
5008 gfc_add_modify (&block, x, tmp);
5009 stmt = gfc_finish_block (&block);
5010
5011 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, x,
5012 build_real_from_int_cst (type, integer_zero_node));
5013 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
5014 gfc_add_expr_to_block (&se->pre, tmp);
5015
5016 se->expr = fold_convert (type, x);
5017 }
5018
5019
5020 /* SCALE (s, i) is translated into scalbn (s, i). */
5021 static void
5022 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
5023 {
5024 tree args[2], type, scalbn;
5025
5026 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5027
5028 type = gfc_typenode_for_spec (&expr->ts);
5029 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5030 se->expr = build_call_expr_loc (input_location, scalbn, 2,
5031 fold_convert (type, args[0]),
5032 fold_convert (integer_type_node, args[1]));
5033 se->expr = fold_convert (type, se->expr);
5034 }
5035
5036
5037 /* SET_EXPONENT (s, i) is translated into
5038 scalbn (frexp (s, &dummy_int), i). */
5039 static void
5040 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
5041 {
5042 tree args[2], type, tmp, frexp, scalbn;
5043
5044 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
5045 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
5046
5047 type = gfc_typenode_for_spec (&expr->ts);
5048 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5049
5050 tmp = gfc_create_var (integer_type_node, NULL);
5051 tmp = build_call_expr_loc (input_location, frexp, 2,
5052 fold_convert (type, args[0]),
5053 gfc_build_addr_expr (NULL_TREE, tmp));
5054 se->expr = build_call_expr_loc (input_location, scalbn, 2, tmp,
5055 fold_convert (integer_type_node, args[1]));
5056 se->expr = fold_convert (type, se->expr);
5057 }
5058
5059
5060 static void
5061 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
5062 {
5063 gfc_actual_arglist *actual;
5064 tree arg1;
5065 tree type;
5066 tree fncall0;
5067 tree fncall1;
5068 gfc_se argse;
5069
5070 gfc_init_se (&argse, NULL);
5071 actual = expr->value.function.actual;
5072
5073 if (actual->expr->ts.type == BT_CLASS)
5074 gfc_add_class_array_ref (actual->expr);
5075
5076 argse.want_pointer = 1;
5077 argse.data_not_needed = 1;
5078 gfc_conv_expr_descriptor (&argse, actual->expr);
5079 gfc_add_block_to_block (&se->pre, &argse.pre);
5080 gfc_add_block_to_block (&se->post, &argse.post);
5081 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
5082
5083 /* Build the call to size0. */
5084 fncall0 = build_call_expr_loc (input_location,
5085 gfor_fndecl_size0, 1, arg1);
5086
5087 actual = actual->next;
5088
5089 if (actual->expr)
5090 {
5091 gfc_init_se (&argse, NULL);
5092 gfc_conv_expr_type (&argse, actual->expr,
5093 gfc_array_index_type);
5094 gfc_add_block_to_block (&se->pre, &argse.pre);
5095
5096 /* Unusually, for an intrinsic, size does not exclude
5097 an optional arg2, so we must test for it. */
5098 if (actual->expr->expr_type == EXPR_VARIABLE
5099 && actual->expr->symtree->n.sym->attr.dummy
5100 && actual->expr->symtree->n.sym->attr.optional)
5101 {
5102 tree tmp;
5103 /* Build the call to size1. */
5104 fncall1 = build_call_expr_loc (input_location,
5105 gfor_fndecl_size1, 2,
5106 arg1, argse.expr);
5107
5108 gfc_init_se (&argse, NULL);
5109 argse.want_pointer = 1;
5110 argse.data_not_needed = 1;
5111 gfc_conv_expr (&argse, actual->expr);
5112 gfc_add_block_to_block (&se->pre, &argse.pre);
5113 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5114 argse.expr, null_pointer_node);
5115 tmp = gfc_evaluate_now (tmp, &se->pre);
5116 se->expr = fold_build3_loc (input_location, COND_EXPR,
5117 pvoid_type_node, tmp, fncall1, fncall0);
5118 }
5119 else
5120 {
5121 se->expr = NULL_TREE;
5122 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
5123 gfc_array_index_type,
5124 argse.expr, gfc_index_one_node);
5125 }
5126 }
5127 else if (expr->value.function.actual->expr->rank == 1)
5128 {
5129 argse.expr = gfc_index_zero_node;
5130 se->expr = NULL_TREE;
5131 }
5132 else
5133 se->expr = fncall0;
5134
5135 if (se->expr == NULL_TREE)
5136 {
5137 tree ubound, lbound;
5138
5139 arg1 = build_fold_indirect_ref_loc (input_location,
5140 arg1);
5141 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
5142 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
5143 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
5144 gfc_array_index_type, ubound, lbound);
5145 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
5146 gfc_array_index_type,
5147 se->expr, gfc_index_one_node);
5148 se->expr = fold_build2_loc (input_location, MAX_EXPR,
5149 gfc_array_index_type, se->expr,
5150 gfc_index_zero_node);
5151 }
5152
5153 type = gfc_typenode_for_spec (&expr->ts);
5154 se->expr = convert (type, se->expr);
5155 }
5156
5157
5158 /* Helper function to compute the size of a character variable,
5159 excluding the terminating null characters. The result has
5160 gfc_array_index_type type. */
5161
5162 tree
5163 size_of_string_in_bytes (int kind, tree string_length)
5164 {
5165 tree bytesize;
5166 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
5167
5168 bytesize = build_int_cst (gfc_array_index_type,
5169 gfc_character_kinds[i].bit_size / 8);
5170
5171 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5172 bytesize,
5173 fold_convert (gfc_array_index_type, string_length));
5174 }
5175
5176
5177 static void
5178 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
5179 {
5180 gfc_expr *arg;
5181 gfc_se argse;
5182 tree source_bytes;
5183 tree type;
5184 tree tmp;
5185 tree lower;
5186 tree upper;
5187 int n;
5188
5189 arg = expr->value.function.actual->expr;
5190
5191 gfc_init_se (&argse, NULL);
5192
5193 if (arg->rank == 0)
5194 {
5195 if (arg->ts.type == BT_CLASS)
5196 gfc_add_data_component (arg);
5197
5198 gfc_conv_expr_reference (&argse, arg);
5199
5200 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5201 argse.expr));
5202
5203 /* Obtain the source word length. */
5204 if (arg->ts.type == BT_CHARACTER)
5205 se->expr = size_of_string_in_bytes (arg->ts.kind,
5206 argse.string_length);
5207 else
5208 se->expr = fold_convert (gfc_array_index_type, size_in_bytes (type));
5209 }
5210 else
5211 {
5212 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
5213 argse.want_pointer = 0;
5214 gfc_conv_expr_descriptor (&argse, arg);
5215 type = gfc_get_element_type (TREE_TYPE (argse.expr));
5216
5217 /* Obtain the argument's word length. */
5218 if (arg->ts.type == BT_CHARACTER)
5219 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
5220 else
5221 tmp = fold_convert (gfc_array_index_type,
5222 size_in_bytes (type));
5223 gfc_add_modify (&argse.pre, source_bytes, tmp);
5224
5225 /* Obtain the size of the array in bytes. */
5226 for (n = 0; n < arg->rank; n++)
5227 {
5228 tree idx;
5229 idx = gfc_rank_cst[n];
5230 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
5231 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
5232 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5233 gfc_array_index_type, upper, lower);
5234 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5235 gfc_array_index_type, tmp, gfc_index_one_node);
5236 tmp = fold_build2_loc (input_location, MULT_EXPR,
5237 gfc_array_index_type, tmp, source_bytes);
5238 gfc_add_modify (&argse.pre, source_bytes, tmp);
5239 }
5240 se->expr = source_bytes;
5241 }
5242
5243 gfc_add_block_to_block (&se->pre, &argse.pre);
5244 }
5245
5246
5247 static void
5248 gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
5249 {
5250 gfc_expr *arg;
5251 gfc_se argse;
5252 tree type, result_type, tmp;
5253
5254 arg = expr->value.function.actual->expr;
5255
5256 gfc_init_se (&argse, NULL);
5257 result_type = gfc_get_int_type (expr->ts.kind);
5258
5259 if (arg->rank == 0)
5260 {
5261 if (arg->ts.type == BT_CLASS)
5262 {
5263 gfc_add_vptr_component (arg);
5264 gfc_add_size_component (arg);
5265 gfc_conv_expr (&argse, arg);
5266 tmp = fold_convert (result_type, argse.expr);
5267 goto done;
5268 }
5269
5270 gfc_conv_expr_reference (&argse, arg);
5271 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5272 argse.expr));
5273 }
5274 else
5275 {
5276 argse.want_pointer = 0;
5277 gfc_conv_expr_descriptor (&argse, arg);
5278 type = gfc_get_element_type (TREE_TYPE (argse.expr));
5279 }
5280
5281 /* Obtain the argument's word length. */
5282 if (arg->ts.type == BT_CHARACTER)
5283 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
5284 else
5285 tmp = size_in_bytes (type);
5286 tmp = fold_convert (result_type, tmp);
5287
5288 done:
5289 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
5290 build_int_cst (result_type, BITS_PER_UNIT));
5291 gfc_add_block_to_block (&se->pre, &argse.pre);
5292 }
5293
5294
5295 /* Intrinsic string comparison functions. */
5296
5297 static void
5298 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
5299 {
5300 tree args[4];
5301
5302 gfc_conv_intrinsic_function_args (se, expr, args, 4);
5303
5304 se->expr
5305 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
5306 expr->value.function.actual->expr->ts.kind,
5307 op);
5308 se->expr = fold_build2_loc (input_location, op,
5309 gfc_typenode_for_spec (&expr->ts), se->expr,
5310 build_int_cst (TREE_TYPE (se->expr), 0));
5311 }
5312
5313 /* Generate a call to the adjustl/adjustr library function. */
5314 static void
5315 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
5316 {
5317 tree args[3];
5318 tree len;
5319 tree type;
5320 tree var;
5321 tree tmp;
5322
5323 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
5324 len = args[1];
5325
5326 type = TREE_TYPE (args[2]);
5327 var = gfc_conv_string_tmp (se, type, len);
5328 args[0] = var;
5329
5330 tmp = build_call_expr_loc (input_location,
5331 fndecl, 3, args[0], args[1], args[2]);
5332 gfc_add_expr_to_block (&se->pre, tmp);
5333 se->expr = var;
5334 se->string_length = len;
5335 }
5336
5337
5338 /* Generate code for the TRANSFER intrinsic:
5339 For scalar results:
5340 DEST = TRANSFER (SOURCE, MOLD)
5341 where:
5342 typeof<DEST> = typeof<MOLD>
5343 and:
5344 MOLD is scalar.
5345
5346 For array results:
5347 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
5348 where:
5349 typeof<DEST> = typeof<MOLD>
5350 and:
5351 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
5352 sizeof (DEST(0) * SIZE). */
5353 static void
5354 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
5355 {
5356 tree tmp;
5357 tree tmpdecl;
5358 tree ptr;
5359 tree extent;
5360 tree source;
5361 tree source_type;
5362 tree source_bytes;
5363 tree mold_type;
5364 tree dest_word_len;
5365 tree size_words;
5366 tree size_bytes;
5367 tree upper;
5368 tree lower;
5369 tree stmt;
5370 gfc_actual_arglist *arg;
5371 gfc_se argse;
5372 gfc_array_info *info;
5373 stmtblock_t block;
5374 int n;
5375 bool scalar_mold;
5376 gfc_expr *source_expr, *mold_expr;
5377
5378 info = NULL;
5379 if (se->loop)
5380 info = &se->ss->info->data.array;
5381
5382 /* Convert SOURCE. The output from this stage is:-
5383 source_bytes = length of the source in bytes
5384 source = pointer to the source data. */
5385 arg = expr->value.function.actual;
5386 source_expr = arg->expr;
5387
5388 /* Ensure double transfer through LOGICAL preserves all
5389 the needed bits. */
5390 if (arg->expr->expr_type == EXPR_FUNCTION
5391 && arg->expr->value.function.esym == NULL
5392 && arg->expr->value.function.isym != NULL
5393 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
5394 && arg->expr->ts.type == BT_LOGICAL
5395 && expr->ts.type != arg->expr->ts.type)
5396 arg->expr->value.function.name = "__transfer_in_transfer";
5397
5398 gfc_init_se (&argse, NULL);
5399
5400 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
5401
5402 /* Obtain the pointer to source and the length of source in bytes. */
5403 if (arg->expr->rank == 0)
5404 {
5405 gfc_conv_expr_reference (&argse, arg->expr);
5406 if (arg->expr->ts.type == BT_CLASS)
5407 source = gfc_class_data_get (argse.expr);
5408 else
5409 source = argse.expr;
5410
5411 /* Obtain the source word length. */
5412 switch (arg->expr->ts.type)
5413 {
5414 case BT_CHARACTER:
5415 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
5416 argse.string_length);
5417 break;
5418 case BT_CLASS:
5419 tmp = gfc_vtable_size_get (argse.expr);
5420 break;
5421 default:
5422 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5423 source));
5424 tmp = fold_convert (gfc_array_index_type,
5425 size_in_bytes (source_type));
5426 break;
5427 }
5428 }
5429 else
5430 {
5431 argse.want_pointer = 0;
5432 gfc_conv_expr_descriptor (&argse, arg->expr);
5433 source = gfc_conv_descriptor_data_get (argse.expr);
5434 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
5435
5436 /* Repack the source if not simply contiguous. */
5437 if (!gfc_is_simply_contiguous (arg->expr, false))
5438 {
5439 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
5440
5441 if (gfc_option.warn_array_temp)
5442 gfc_warning ("Creating array temporary at %L", &expr->where);
5443
5444 source = build_call_expr_loc (input_location,
5445 gfor_fndecl_in_pack, 1, tmp);
5446 source = gfc_evaluate_now (source, &argse.pre);
5447
5448 /* Free the temporary. */
5449 gfc_start_block (&block);
5450 tmp = gfc_call_free (convert (pvoid_type_node, source));
5451 gfc_add_expr_to_block (&block, tmp);
5452 stmt = gfc_finish_block (&block);
5453
5454 /* Clean up if it was repacked. */
5455 gfc_init_block (&block);
5456 tmp = gfc_conv_array_data (argse.expr);
5457 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5458 source, tmp);
5459 tmp = build3_v (COND_EXPR, tmp, stmt,
5460 build_empty_stmt (input_location));
5461 gfc_add_expr_to_block (&block, tmp);
5462 gfc_add_block_to_block (&block, &se->post);
5463 gfc_init_block (&se->post);
5464 gfc_add_block_to_block (&se->post, &block);
5465 }
5466
5467 /* Obtain the source word length. */
5468 if (arg->expr->ts.type == BT_CHARACTER)
5469 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
5470 argse.string_length);
5471 else
5472 tmp = fold_convert (gfc_array_index_type,
5473 size_in_bytes (source_type));
5474
5475 /* Obtain the size of the array in bytes. */
5476 extent = gfc_create_var (gfc_array_index_type, NULL);
5477 for (n = 0; n < arg->expr->rank; n++)
5478 {
5479 tree idx;
5480 idx = gfc_rank_cst[n];
5481 gfc_add_modify (&argse.pre, source_bytes, tmp);
5482 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
5483 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
5484 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5485 gfc_array_index_type, upper, lower);
5486 gfc_add_modify (&argse.pre, extent, tmp);
5487 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5488 gfc_array_index_type, extent,
5489 gfc_index_one_node);
5490 tmp = fold_build2_loc (input_location, MULT_EXPR,
5491 gfc_array_index_type, tmp, source_bytes);
5492 }
5493 }
5494
5495 gfc_add_modify (&argse.pre, source_bytes, tmp);
5496 gfc_add_block_to_block (&se->pre, &argse.pre);
5497 gfc_add_block_to_block (&se->post, &argse.post);
5498
5499 /* Now convert MOLD. The outputs are:
5500 mold_type = the TREE type of MOLD
5501 dest_word_len = destination word length in bytes. */
5502 arg = arg->next;
5503 mold_expr = arg->expr;
5504
5505 gfc_init_se (&argse, NULL);
5506
5507 scalar_mold = arg->expr->rank == 0;
5508
5509 if (arg->expr->rank == 0)
5510 {
5511 gfc_conv_expr_reference (&argse, arg->expr);
5512 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5513 argse.expr));
5514 }
5515 else
5516 {
5517 gfc_init_se (&argse, NULL);
5518 argse.want_pointer = 0;
5519 gfc_conv_expr_descriptor (&argse, arg->expr);
5520 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
5521 }
5522
5523 gfc_add_block_to_block (&se->pre, &argse.pre);
5524 gfc_add_block_to_block (&se->post, &argse.post);
5525
5526 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
5527 {
5528 /* If this TRANSFER is nested in another TRANSFER, use a type
5529 that preserves all bits. */
5530 if (arg->expr->ts.type == BT_LOGICAL)
5531 mold_type = gfc_get_int_type (arg->expr->ts.kind);
5532 }
5533
5534 /* Obtain the destination word length. */
5535 switch (arg->expr->ts.type)
5536 {
5537 case BT_CHARACTER:
5538 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
5539 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
5540 break;
5541 case BT_CLASS:
5542 tmp = gfc_vtable_size_get (argse.expr);
5543 break;
5544 default:
5545 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
5546 break;
5547 }
5548 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
5549 gfc_add_modify (&se->pre, dest_word_len, tmp);
5550
5551 /* Finally convert SIZE, if it is present. */
5552 arg = arg->next;
5553 size_words = gfc_create_var (gfc_array_index_type, NULL);
5554
5555 if (arg->expr)
5556 {
5557 gfc_init_se (&argse, NULL);
5558 gfc_conv_expr_reference (&argse, arg->expr);
5559 tmp = convert (gfc_array_index_type,
5560 build_fold_indirect_ref_loc (input_location,
5561 argse.expr));
5562 gfc_add_block_to_block (&se->pre, &argse.pre);
5563 gfc_add_block_to_block (&se->post, &argse.post);
5564 }
5565 else
5566 tmp = NULL_TREE;
5567
5568 /* Separate array and scalar results. */
5569 if (scalar_mold && tmp == NULL_TREE)
5570 goto scalar_transfer;
5571
5572 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
5573 if (tmp != NULL_TREE)
5574 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5575 tmp, dest_word_len);
5576 else
5577 tmp = source_bytes;
5578
5579 gfc_add_modify (&se->pre, size_bytes, tmp);
5580 gfc_add_modify (&se->pre, size_words,
5581 fold_build2_loc (input_location, CEIL_DIV_EXPR,
5582 gfc_array_index_type,
5583 size_bytes, dest_word_len));
5584
5585 /* Evaluate the bounds of the result. If the loop range exists, we have
5586 to check if it is too large. If so, we modify loop->to be consistent
5587 with min(size, size(source)). Otherwise, size is made consistent with
5588 the loop range, so that the right number of bytes is transferred.*/
5589 n = se->loop->order[0];
5590 if (se->loop->to[n] != NULL_TREE)
5591 {
5592 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5593 se->loop->to[n], se->loop->from[n]);
5594 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5595 tmp, gfc_index_one_node);
5596 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
5597 tmp, size_words);
5598 gfc_add_modify (&se->pre, size_words, tmp);
5599 gfc_add_modify (&se->pre, size_bytes,
5600 fold_build2_loc (input_location, MULT_EXPR,
5601 gfc_array_index_type,
5602 size_words, dest_word_len));
5603 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5604 size_words, se->loop->from[n]);
5605 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5606 upper, gfc_index_one_node);
5607 }
5608 else
5609 {
5610 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5611 size_words, gfc_index_one_node);
5612 se->loop->from[n] = gfc_index_zero_node;
5613 }
5614
5615 se->loop->to[n] = upper;
5616
5617 /* Build a destination descriptor, using the pointer, source, as the
5618 data field. */
5619 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
5620 NULL_TREE, false, true, false, &expr->where);
5621
5622 /* Cast the pointer to the result. */
5623 tmp = gfc_conv_descriptor_data_get (info->descriptor);
5624 tmp = fold_convert (pvoid_type_node, tmp);
5625
5626 /* Use memcpy to do the transfer. */
5627 tmp
5628 = build_call_expr_loc (input_location,
5629 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
5630 fold_convert (pvoid_type_node, source),
5631 fold_convert (size_type_node,
5632 fold_build2_loc (input_location,
5633 MIN_EXPR,
5634 gfc_array_index_type,
5635 size_bytes,
5636 source_bytes)));
5637 gfc_add_expr_to_block (&se->pre, tmp);
5638
5639 se->expr = info->descriptor;
5640 if (expr->ts.type == BT_CHARACTER)
5641 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
5642
5643 return;
5644
5645 /* Deal with scalar results. */
5646 scalar_transfer:
5647 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
5648 dest_word_len, source_bytes);
5649 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
5650 extent, gfc_index_zero_node);
5651
5652 if (expr->ts.type == BT_CHARACTER)
5653 {
5654 tree direct, indirect, free;
5655
5656 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
5657 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
5658 "transfer");
5659
5660 /* If source is longer than the destination, use a pointer to
5661 the source directly. */
5662 gfc_init_block (&block);
5663 gfc_add_modify (&block, tmpdecl, ptr);
5664 direct = gfc_finish_block (&block);
5665
5666 /* Otherwise, allocate a string with the length of the destination
5667 and copy the source into it. */
5668 gfc_init_block (&block);
5669 tmp = gfc_get_pchar_type (expr->ts.kind);
5670 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
5671 gfc_add_modify (&block, tmpdecl,
5672 fold_convert (TREE_TYPE (ptr), tmp));
5673 tmp = build_call_expr_loc (input_location,
5674 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
5675 fold_convert (pvoid_type_node, tmpdecl),
5676 fold_convert (pvoid_type_node, ptr),
5677 fold_convert (size_type_node, extent));
5678 gfc_add_expr_to_block (&block, tmp);
5679 indirect = gfc_finish_block (&block);
5680
5681 /* Wrap it up with the condition. */
5682 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
5683 dest_word_len, source_bytes);
5684 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
5685 gfc_add_expr_to_block (&se->pre, tmp);
5686
5687 /* Free the temporary string, if necessary. */
5688 free = gfc_call_free (tmpdecl);
5689 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
5690 dest_word_len, source_bytes);
5691 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
5692 gfc_add_expr_to_block (&se->post, tmp);
5693
5694 se->expr = tmpdecl;
5695 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
5696 }
5697 else
5698 {
5699 tmpdecl = gfc_create_var (mold_type, "transfer");
5700
5701 ptr = convert (build_pointer_type (mold_type), source);
5702
5703 /* For CLASS results, allocate the needed memory first. */
5704 if (mold_expr->ts.type == BT_CLASS)
5705 {
5706 tree cdata;
5707 cdata = gfc_class_data_get (tmpdecl);
5708 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
5709 gfc_add_modify (&se->pre, cdata, tmp);
5710 }
5711
5712 /* Use memcpy to do the transfer. */
5713 if (mold_expr->ts.type == BT_CLASS)
5714 tmp = gfc_class_data_get (tmpdecl);
5715 else
5716 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
5717
5718 tmp = build_call_expr_loc (input_location,
5719 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
5720 fold_convert (pvoid_type_node, tmp),
5721 fold_convert (pvoid_type_node, ptr),
5722 fold_convert (size_type_node, extent));
5723 gfc_add_expr_to_block (&se->pre, tmp);
5724
5725 /* For CLASS results, set the _vptr. */
5726 if (mold_expr->ts.type == BT_CLASS)
5727 {
5728 tree vptr;
5729 gfc_symbol *vtab;
5730 vptr = gfc_class_vptr_get (tmpdecl);
5731 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
5732 gcc_assert (vtab);
5733 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
5734 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
5735 }
5736
5737 se->expr = tmpdecl;
5738 }
5739 }
5740
5741
5742 /* Generate code for the ALLOCATED intrinsic.
5743 Generate inline code that directly check the address of the argument. */
5744
5745 static void
5746 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
5747 {
5748 gfc_actual_arglist *arg1;
5749 gfc_se arg1se;
5750 tree tmp;
5751
5752 gfc_init_se (&arg1se, NULL);
5753 arg1 = expr->value.function.actual;
5754
5755 if (arg1->expr->ts.type == BT_CLASS)
5756 {
5757 /* Make sure that class array expressions have both a _data
5758 component reference and an array reference.... */
5759 if (CLASS_DATA (arg1->expr)->attr.dimension)
5760 gfc_add_class_array_ref (arg1->expr);
5761 /* .... whilst scalars only need the _data component. */
5762 else
5763 gfc_add_data_component (arg1->expr);
5764 }
5765
5766 if (arg1->expr->rank == 0)
5767 {
5768 /* Allocatable scalar. */
5769 arg1se.want_pointer = 1;
5770 gfc_conv_expr (&arg1se, arg1->expr);
5771 tmp = arg1se.expr;
5772 }
5773 else
5774 {
5775 /* Allocatable array. */
5776 arg1se.descriptor_only = 1;
5777 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
5778 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
5779 }
5780
5781 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
5782 fold_convert (TREE_TYPE (tmp), null_pointer_node));
5783 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
5784 }
5785
5786
5787 /* Generate code for the ASSOCIATED intrinsic.
5788 If both POINTER and TARGET are arrays, generate a call to library function
5789 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
5790 In other cases, generate inline code that directly compare the address of
5791 POINTER with the address of TARGET. */
5792
5793 static void
5794 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
5795 {
5796 gfc_actual_arglist *arg1;
5797 gfc_actual_arglist *arg2;
5798 gfc_se arg1se;
5799 gfc_se arg2se;
5800 tree tmp2;
5801 tree tmp;
5802 tree nonzero_charlen;
5803 tree nonzero_arraylen;
5804 gfc_ss *ss;
5805 bool scalar;
5806
5807 gfc_init_se (&arg1se, NULL);
5808 gfc_init_se (&arg2se, NULL);
5809 arg1 = expr->value.function.actual;
5810 arg2 = arg1->next;
5811
5812 /* Check whether the expression is a scalar or not; we cannot use
5813 arg1->expr->rank as it can be nonzero for proc pointers. */
5814 ss = gfc_walk_expr (arg1->expr);
5815 scalar = ss == gfc_ss_terminator;
5816 if (!scalar)
5817 gfc_free_ss_chain (ss);
5818
5819 if (!arg2->expr)
5820 {
5821 /* No optional target. */
5822 if (scalar)
5823 {
5824 /* A pointer to a scalar. */
5825 arg1se.want_pointer = 1;
5826 gfc_conv_expr (&arg1se, arg1->expr);
5827 if (arg1->expr->symtree->n.sym->attr.proc_pointer
5828 && arg1->expr->symtree->n.sym->attr.dummy)
5829 arg1se.expr = build_fold_indirect_ref_loc (input_location,
5830 arg1se.expr);
5831 if (arg1->expr->ts.type == BT_CLASS)
5832 tmp2 = gfc_class_data_get (arg1se.expr);
5833 else
5834 tmp2 = arg1se.expr;
5835 }
5836 else
5837 {
5838 /* A pointer to an array. */
5839 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
5840 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
5841 }
5842 gfc_add_block_to_block (&se->pre, &arg1se.pre);
5843 gfc_add_block_to_block (&se->post, &arg1se.post);
5844 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp2,
5845 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
5846 se->expr = tmp;
5847 }
5848 else
5849 {
5850 /* An optional target. */
5851 if (arg2->expr->ts.type == BT_CLASS)
5852 gfc_add_data_component (arg2->expr);
5853
5854 nonzero_charlen = NULL_TREE;
5855 if (arg1->expr->ts.type == BT_CHARACTER)
5856 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
5857 boolean_type_node,
5858 arg1->expr->ts.u.cl->backend_decl,
5859 integer_zero_node);
5860 if (scalar)
5861 {
5862 /* A pointer to a scalar. */
5863 arg1se.want_pointer = 1;
5864 gfc_conv_expr (&arg1se, arg1->expr);
5865 if (arg1->expr->symtree->n.sym->attr.proc_pointer
5866 && arg1->expr->symtree->n.sym->attr.dummy)
5867 arg1se.expr = build_fold_indirect_ref_loc (input_location,
5868 arg1se.expr);
5869 if (arg1->expr->ts.type == BT_CLASS)
5870 arg1se.expr = gfc_class_data_get (arg1se.expr);
5871
5872 arg2se.want_pointer = 1;
5873 gfc_conv_expr (&arg2se, arg2->expr);
5874 if (arg2->expr->symtree->n.sym->attr.proc_pointer
5875 && arg2->expr->symtree->n.sym->attr.dummy)
5876 arg2se.expr = build_fold_indirect_ref_loc (input_location,
5877 arg2se.expr);
5878 gfc_add_block_to_block (&se->pre, &arg1se.pre);
5879 gfc_add_block_to_block (&se->post, &arg1se.post);
5880 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5881 arg1se.expr, arg2se.expr);
5882 tmp2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5883 arg1se.expr, null_pointer_node);
5884 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5885 boolean_type_node, tmp, tmp2);
5886 }
5887 else
5888 {
5889 /* An array pointer of zero length is not associated if target is
5890 present. */
5891 arg1se.descriptor_only = 1;
5892 gfc_conv_expr_lhs (&arg1se, arg1->expr);
5893 if (arg1->expr->rank == -1)
5894 {
5895 tmp = gfc_conv_descriptor_rank (arg1se.expr);
5896 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5897 TREE_TYPE (tmp), tmp, gfc_index_one_node);
5898 }
5899 else
5900 tmp = gfc_rank_cst[arg1->expr->rank - 1];
5901 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
5902 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
5903 boolean_type_node, tmp,
5904 build_int_cst (TREE_TYPE (tmp), 0));
5905
5906 /* A pointer to an array, call library function _gfor_associated. */
5907 arg1se.want_pointer = 1;
5908 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
5909
5910 arg2se.want_pointer = 1;
5911 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
5912 gfc_add_block_to_block (&se->pre, &arg2se.pre);
5913 gfc_add_block_to_block (&se->post, &arg2se.post);
5914 se->expr = build_call_expr_loc (input_location,
5915 gfor_fndecl_associated, 2,
5916 arg1se.expr, arg2se.expr);
5917 se->expr = convert (boolean_type_node, se->expr);
5918 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5919 boolean_type_node, se->expr,
5920 nonzero_arraylen);
5921 }
5922
5923 /* If target is present zero character length pointers cannot
5924 be associated. */
5925 if (nonzero_charlen != NULL_TREE)
5926 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5927 boolean_type_node,
5928 se->expr, nonzero_charlen);
5929 }
5930
5931 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
5932 }
5933
5934
5935 /* Generate code for the SAME_TYPE_AS intrinsic.
5936 Generate inline code that directly checks the vindices. */
5937
5938 static void
5939 gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
5940 {
5941 gfc_expr *a, *b;
5942 gfc_se se1, se2;
5943 tree tmp;
5944 tree conda = NULL_TREE, condb = NULL_TREE;
5945
5946 gfc_init_se (&se1, NULL);
5947 gfc_init_se (&se2, NULL);
5948
5949 a = expr->value.function.actual->expr;
5950 b = expr->value.function.actual->next->expr;
5951
5952 if (UNLIMITED_POLY (a))
5953 {
5954 tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
5955 conda = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5956 tmp, build_int_cst (TREE_TYPE (tmp), 0));
5957 }
5958
5959 if (UNLIMITED_POLY (b))
5960 {
5961 tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
5962 condb = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5963 tmp, build_int_cst (TREE_TYPE (tmp), 0));
5964 }
5965
5966 if (a->ts.type == BT_CLASS)
5967 {
5968 gfc_add_vptr_component (a);
5969 gfc_add_hash_component (a);
5970 }
5971 else if (a->ts.type == BT_DERIVED)
5972 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
5973 a->ts.u.derived->hash_value);
5974
5975 if (b->ts.type == BT_CLASS)
5976 {
5977 gfc_add_vptr_component (b);
5978 gfc_add_hash_component (b);
5979 }
5980 else if (b->ts.type == BT_DERIVED)
5981 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
5982 b->ts.u.derived->hash_value);
5983
5984 gfc_conv_expr (&se1, a);
5985 gfc_conv_expr (&se2, b);
5986
5987 tmp = fold_build2_loc (input_location, EQ_EXPR,
5988 boolean_type_node, se1.expr,
5989 fold_convert (TREE_TYPE (se1.expr), se2.expr));
5990
5991 if (conda)
5992 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
5993 boolean_type_node, conda, tmp);
5994
5995 if (condb)
5996 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
5997 boolean_type_node, condb, tmp);
5998
5999 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
6000 }
6001
6002
6003 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
6004
6005 static void
6006 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
6007 {
6008 tree args[2];
6009
6010 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6011 se->expr = build_call_expr_loc (input_location,
6012 gfor_fndecl_sc_kind, 2, args[0], args[1]);
6013 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6014 }
6015
6016
6017 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
6018
6019 static void
6020 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
6021 {
6022 tree arg, type;
6023
6024 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6025
6026 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
6027 type = gfc_get_int_type (4);
6028 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
6029
6030 /* Convert it to the required type. */
6031 type = gfc_typenode_for_spec (&expr->ts);
6032 se->expr = build_call_expr_loc (input_location,
6033 gfor_fndecl_si_kind, 1, arg);
6034 se->expr = fold_convert (type, se->expr);
6035 }
6036
6037
6038 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
6039
6040 static void
6041 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
6042 {
6043 gfc_actual_arglist *actual;
6044 tree type;
6045 gfc_se argse;
6046 vec<tree, va_gc> *args = NULL;
6047
6048 for (actual = expr->value.function.actual; actual; actual = actual->next)
6049 {
6050 gfc_init_se (&argse, se);
6051
6052 /* Pass a NULL pointer for an absent arg. */
6053 if (actual->expr == NULL)
6054 argse.expr = null_pointer_node;
6055 else
6056 {
6057 gfc_typespec ts;
6058 gfc_clear_ts (&ts);
6059
6060 if (actual->expr->ts.kind != gfc_c_int_kind)
6061 {
6062 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
6063 ts.type = BT_INTEGER;
6064 ts.kind = gfc_c_int_kind;
6065 gfc_convert_type (actual->expr, &ts, 2);
6066 }
6067 gfc_conv_expr_reference (&argse, actual->expr);
6068 }
6069
6070 gfc_add_block_to_block (&se->pre, &argse.pre);
6071 gfc_add_block_to_block (&se->post, &argse.post);
6072 vec_safe_push (args, argse.expr);
6073 }
6074
6075 /* Convert it to the required type. */
6076 type = gfc_typenode_for_spec (&expr->ts);
6077 se->expr = build_call_expr_loc_vec (input_location,
6078 gfor_fndecl_sr_kind, args);
6079 se->expr = fold_convert (type, se->expr);
6080 }
6081
6082
6083 /* Generate code for TRIM (A) intrinsic function. */
6084
6085 static void
6086 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
6087 {
6088 tree var;
6089 tree len;
6090 tree addr;
6091 tree tmp;
6092 tree cond;
6093 tree fndecl;
6094 tree function;
6095 tree *args;
6096 unsigned int num_args;
6097
6098 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
6099 args = XALLOCAVEC (tree, num_args);
6100
6101 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
6102 addr = gfc_build_addr_expr (ppvoid_type_node, var);
6103 len = gfc_create_var (gfc_charlen_type_node, "len");
6104
6105 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
6106 args[0] = gfc_build_addr_expr (NULL_TREE, len);
6107 args[1] = addr;
6108
6109 if (expr->ts.kind == 1)
6110 function = gfor_fndecl_string_trim;
6111 else if (expr->ts.kind == 4)
6112 function = gfor_fndecl_string_trim_char4;
6113 else
6114 gcc_unreachable ();
6115
6116 fndecl = build_addr (function, current_function_decl);
6117 tmp = build_call_array_loc (input_location,
6118 TREE_TYPE (TREE_TYPE (function)), fndecl,
6119 num_args, args);
6120 gfc_add_expr_to_block (&se->pre, tmp);
6121
6122 /* Free the temporary afterwards, if necessary. */
6123 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6124 len, build_int_cst (TREE_TYPE (len), 0));
6125 tmp = gfc_call_free (var);
6126 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
6127 gfc_add_expr_to_block (&se->post, tmp);
6128
6129 se->expr = var;
6130 se->string_length = len;
6131 }
6132
6133
6134 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
6135
6136 static void
6137 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
6138 {
6139 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
6140 tree type, cond, tmp, count, exit_label, n, max, largest;
6141 tree size;
6142 stmtblock_t block, body;
6143 int i;
6144
6145 /* We store in charsize the size of a character. */
6146 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
6147 size = build_int_cst (size_type_node, gfc_character_kinds[i].bit_size / 8);
6148
6149 /* Get the arguments. */
6150 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6151 slen = fold_convert (size_type_node, gfc_evaluate_now (args[0], &se->pre));
6152 src = args[1];
6153 ncopies = gfc_evaluate_now (args[2], &se->pre);
6154 ncopies_type = TREE_TYPE (ncopies);
6155
6156 /* Check that NCOPIES is not negative. */
6157 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, ncopies,
6158 build_int_cst (ncopies_type, 0));
6159 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
6160 "Argument NCOPIES of REPEAT intrinsic is negative "
6161 "(its value is %ld)",
6162 fold_convert (long_integer_type_node, ncopies));
6163
6164 /* If the source length is zero, any non negative value of NCOPIES
6165 is valid, and nothing happens. */
6166 n = gfc_create_var (ncopies_type, "ncopies");
6167 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
6168 build_int_cst (size_type_node, 0));
6169 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
6170 build_int_cst (ncopies_type, 0), ncopies);
6171 gfc_add_modify (&se->pre, n, tmp);
6172 ncopies = n;
6173
6174 /* Check that ncopies is not too large: ncopies should be less than
6175 (or equal to) MAX / slen, where MAX is the maximal integer of
6176 the gfc_charlen_type_node type. If slen == 0, we need a special
6177 case to avoid the division by zero. */
6178 i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
6179 max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_charlen_int_kind);
6180 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node,
6181 fold_convert (size_type_node, max), slen);
6182 largest = TYPE_PRECISION (size_type_node) > TYPE_PRECISION (ncopies_type)
6183 ? size_type_node : ncopies_type;
6184 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6185 fold_convert (largest, ncopies),
6186 fold_convert (largest, max));
6187 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
6188 build_int_cst (size_type_node, 0));
6189 cond = fold_build3_loc (input_location, COND_EXPR, boolean_type_node, tmp,
6190 boolean_false_node, cond);
6191 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
6192 "Argument NCOPIES of REPEAT intrinsic is too large");
6193
6194 /* Compute the destination length. */
6195 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6196 fold_convert (gfc_charlen_type_node, slen),
6197 fold_convert (gfc_charlen_type_node, ncopies));
6198 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
6199 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
6200
6201 /* Generate the code to do the repeat operation:
6202 for (i = 0; i < ncopies; i++)
6203 memmove (dest + (i * slen * size), src, slen*size); */
6204 gfc_start_block (&block);
6205 count = gfc_create_var (ncopies_type, "count");
6206 gfc_add_modify (&block, count, build_int_cst (ncopies_type, 0));
6207 exit_label = gfc_build_label_decl (NULL_TREE);
6208
6209 /* Start the loop body. */
6210 gfc_start_block (&body);
6211
6212 /* Exit the loop if count >= ncopies. */
6213 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, count,
6214 ncopies);
6215 tmp = build1_v (GOTO_EXPR, exit_label);
6216 TREE_USED (exit_label) = 1;
6217 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
6218 build_empty_stmt (input_location));
6219 gfc_add_expr_to_block (&body, tmp);
6220
6221 /* Call memmove (dest + (i*slen*size), src, slen*size). */
6222 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6223 fold_convert (gfc_charlen_type_node, slen),
6224 fold_convert (gfc_charlen_type_node, count));
6225 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6226 tmp, fold_convert (gfc_charlen_type_node, size));
6227 tmp = fold_build_pointer_plus_loc (input_location,
6228 fold_convert (pvoid_type_node, dest), tmp);
6229 tmp = build_call_expr_loc (input_location,
6230 builtin_decl_explicit (BUILT_IN_MEMMOVE),
6231 3, tmp, src,
6232 fold_build2_loc (input_location, MULT_EXPR,
6233 size_type_node, slen,
6234 fold_convert (size_type_node,
6235 size)));
6236 gfc_add_expr_to_block (&body, tmp);
6237
6238 /* Increment count. */
6239 tmp = fold_build2_loc (input_location, PLUS_EXPR, ncopies_type,
6240 count, build_int_cst (TREE_TYPE (count), 1));
6241 gfc_add_modify (&body, count, tmp);
6242
6243 /* Build the loop. */
6244 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
6245 gfc_add_expr_to_block (&block, tmp);
6246
6247 /* Add the exit label. */
6248 tmp = build1_v (LABEL_EXPR, exit_label);
6249 gfc_add_expr_to_block (&block, tmp);
6250
6251 /* Finish the block. */
6252 tmp = gfc_finish_block (&block);
6253 gfc_add_expr_to_block (&se->pre, tmp);
6254
6255 /* Set the result value. */
6256 se->expr = dest;
6257 se->string_length = dlen;
6258 }
6259
6260
6261 /* Generate code for the IARGC intrinsic. */
6262
6263 static void
6264 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
6265 {
6266 tree tmp;
6267 tree fndecl;
6268 tree type;
6269
6270 /* Call the library function. This always returns an INTEGER(4). */
6271 fndecl = gfor_fndecl_iargc;
6272 tmp = build_call_expr_loc (input_location,
6273 fndecl, 0);
6274
6275 /* Convert it to the required type. */
6276 type = gfc_typenode_for_spec (&expr->ts);
6277 tmp = fold_convert (type, tmp);
6278
6279 se->expr = tmp;
6280 }
6281
6282
6283 /* The loc intrinsic returns the address of its argument as
6284 gfc_index_integer_kind integer. */
6285
6286 static void
6287 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
6288 {
6289 tree temp_var;
6290 gfc_expr *arg_expr;
6291
6292 gcc_assert (!se->ss);
6293
6294 arg_expr = expr->value.function.actual->expr;
6295 if (arg_expr->rank == 0)
6296 gfc_conv_expr_reference (se, arg_expr);
6297 else
6298 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
6299 se->expr= convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
6300
6301 /* Create a temporary variable for loc return value. Without this,
6302 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
6303 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
6304 gfc_add_modify (&se->pre, temp_var, se->expr);
6305 se->expr = temp_var;
6306 }
6307
6308
6309 /* The following routine generates code for the intrinsic
6310 functions from the ISO_C_BINDING module:
6311 * C_LOC
6312 * C_FUNLOC
6313 * C_ASSOCIATED */
6314
6315 static void
6316 conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
6317 {
6318 gfc_actual_arglist *arg = expr->value.function.actual;
6319
6320 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
6321 {
6322 if (arg->expr->rank == 0)
6323 gfc_conv_expr_reference (se, arg->expr);
6324 else if (gfc_is_simply_contiguous (arg->expr, false))
6325 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
6326 else
6327 {
6328 gfc_conv_expr_descriptor (se, arg->expr);
6329 se->expr = gfc_conv_descriptor_data_get (se->expr);
6330 }
6331
6332 /* TODO -- the following two lines shouldn't be necessary, but if
6333 they're removed, a bug is exposed later in the code path.
6334 This workaround was thus introduced, but will have to be
6335 removed; please see PR 35150 for details about the issue. */
6336 se->expr = convert (pvoid_type_node, se->expr);
6337 se->expr = gfc_evaluate_now (se->expr, &se->pre);
6338 }
6339 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
6340 gfc_conv_expr_reference (se, arg->expr);
6341 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
6342 {
6343 gfc_se arg1se;
6344 gfc_se arg2se;
6345
6346 /* Build the addr_expr for the first argument. The argument is
6347 already an *address* so we don't need to set want_pointer in
6348 the gfc_se. */
6349 gfc_init_se (&arg1se, NULL);
6350 gfc_conv_expr (&arg1se, arg->expr);
6351 gfc_add_block_to_block (&se->pre, &arg1se.pre);
6352 gfc_add_block_to_block (&se->post, &arg1se.post);
6353
6354 /* See if we were given two arguments. */
6355 if (arg->next->expr == NULL)
6356 /* Only given one arg so generate a null and do a
6357 not-equal comparison against the first arg. */
6358 se->expr = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6359 arg1se.expr,
6360 fold_convert (TREE_TYPE (arg1se.expr),
6361 null_pointer_node));
6362 else
6363 {
6364 tree eq_expr;
6365 tree not_null_expr;
6366
6367 /* Given two arguments so build the arg2se from second arg. */
6368 gfc_init_se (&arg2se, NULL);
6369 gfc_conv_expr (&arg2se, arg->next->expr);
6370 gfc_add_block_to_block (&se->pre, &arg2se.pre);
6371 gfc_add_block_to_block (&se->post, &arg2se.post);
6372
6373 /* Generate test to compare that the two args are equal. */
6374 eq_expr = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
6375 arg1se.expr, arg2se.expr);
6376 /* Generate test to ensure that the first arg is not null. */
6377 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
6378 boolean_type_node,
6379 arg1se.expr, null_pointer_node);
6380
6381 /* Finally, the generated test must check that both arg1 is not
6382 NULL and that it is equal to the second arg. */
6383 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6384 boolean_type_node,
6385 not_null_expr, eq_expr);
6386 }
6387 }
6388 else
6389 gcc_unreachable ();
6390 }
6391
6392
6393 /* The following routine generates code for the intrinsic
6394 subroutines from the ISO_C_BINDING module:
6395 * C_F_POINTER
6396 * C_F_PROCPOINTER. */
6397
6398 static tree
6399 conv_isocbinding_subroutine (gfc_code *code)
6400 {
6401 gfc_se se;
6402 gfc_se cptrse;
6403 gfc_se fptrse;
6404 gfc_se shapese;
6405 gfc_ss *shape_ss;
6406 tree desc, dim, tmp, stride, offset;
6407 stmtblock_t body, block;
6408 gfc_loopinfo loop;
6409 gfc_actual_arglist *arg = code->ext.actual;
6410
6411 gfc_init_se (&se, NULL);
6412 gfc_init_se (&cptrse, NULL);
6413 gfc_conv_expr (&cptrse, arg->expr);
6414 gfc_add_block_to_block (&se.pre, &cptrse.pre);
6415 gfc_add_block_to_block (&se.post, &cptrse.post);
6416
6417 gfc_init_se (&fptrse, NULL);
6418 if (arg->next->expr->rank == 0)
6419 {
6420 fptrse.want_pointer = 1;
6421 gfc_conv_expr (&fptrse, arg->next->expr);
6422 gfc_add_block_to_block (&se.pre, &fptrse.pre);
6423 gfc_add_block_to_block (&se.post, &fptrse.post);
6424 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
6425 && arg->next->expr->symtree->n.sym->attr.dummy)
6426 fptrse.expr = build_fold_indirect_ref_loc (input_location,
6427 fptrse.expr);
6428 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
6429 TREE_TYPE (fptrse.expr),
6430 fptrse.expr,
6431 fold_convert (TREE_TYPE (fptrse.expr),
6432 cptrse.expr));
6433 gfc_add_expr_to_block (&se.pre, se.expr);
6434 gfc_add_block_to_block (&se.pre, &se.post);
6435 return gfc_finish_block (&se.pre);
6436 }
6437
6438 gfc_start_block (&block);
6439
6440 /* Get the descriptor of the Fortran pointer. */
6441 fptrse.descriptor_only = 1;
6442 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
6443 gfc_add_block_to_block (&block, &fptrse.pre);
6444 desc = fptrse.expr;
6445
6446 /* Set data value, dtype, and offset. */
6447 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
6448 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
6449 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
6450 gfc_get_dtype (TREE_TYPE (desc)));
6451
6452 /* Start scalarization of the bounds, using the shape argument. */
6453
6454 shape_ss = gfc_walk_expr (arg->next->next->expr);
6455 gcc_assert (shape_ss != gfc_ss_terminator);
6456 gfc_init_se (&shapese, NULL);
6457
6458 gfc_init_loopinfo (&loop);
6459 gfc_add_ss_to_loop (&loop, shape_ss);
6460 gfc_conv_ss_startstride (&loop);
6461 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
6462 gfc_mark_ss_chain_used (shape_ss, 1);
6463
6464 gfc_copy_loopinfo_to_se (&shapese, &loop);
6465 shapese.ss = shape_ss;
6466
6467 stride = gfc_create_var (gfc_array_index_type, "stride");
6468 offset = gfc_create_var (gfc_array_index_type, "offset");
6469 gfc_add_modify (&block, stride, gfc_index_one_node);
6470 gfc_add_modify (&block, offset, gfc_index_zero_node);
6471
6472 /* Loop body. */
6473 gfc_start_scalarized_body (&loop, &body);
6474
6475 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6476 loop.loopvar[0], loop.from[0]);
6477
6478 /* Set bounds and stride. */
6479 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
6480 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
6481
6482 gfc_conv_expr (&shapese, arg->next->next->expr);
6483 gfc_add_block_to_block (&body, &shapese.pre);
6484 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
6485 gfc_add_block_to_block (&body, &shapese.post);
6486
6487 /* Calculate offset. */
6488 gfc_add_modify (&body, offset,
6489 fold_build2_loc (input_location, PLUS_EXPR,
6490 gfc_array_index_type, offset, stride));
6491 /* Update stride. */
6492 gfc_add_modify (&body, stride,
6493 fold_build2_loc (input_location, MULT_EXPR,
6494 gfc_array_index_type, stride,
6495 fold_convert (gfc_array_index_type,
6496 shapese.expr)));
6497 /* Finish scalarization loop. */
6498 gfc_trans_scalarizing_loops (&loop, &body);
6499 gfc_add_block_to_block (&block, &loop.pre);
6500 gfc_add_block_to_block (&block, &loop.post);
6501 gfc_add_block_to_block (&block, &fptrse.post);
6502 gfc_cleanup_loop (&loop);
6503
6504 gfc_add_modify (&block, offset,
6505 fold_build1_loc (input_location, NEGATE_EXPR,
6506 gfc_array_index_type, offset));
6507 gfc_conv_descriptor_offset_set (&block, desc, offset);
6508
6509 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
6510 gfc_add_block_to_block (&se.pre, &se.post);
6511 return gfc_finish_block (&se.pre);
6512 }
6513
6514
6515 /* Generate code for an intrinsic function. Some map directly to library
6516 calls, others get special handling. In some cases the name of the function
6517 used depends on the type specifiers. */
6518
6519 void
6520 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
6521 {
6522 const char *name;
6523 int lib, kind;
6524 tree fndecl;
6525
6526 name = &expr->value.function.name[2];
6527
6528 if (expr->rank > 0)
6529 {
6530 lib = gfc_is_intrinsic_libcall (expr);
6531 if (lib != 0)
6532 {
6533 if (lib == 1)
6534 se->ignore_optional = 1;
6535
6536 switch (expr->value.function.isym->id)
6537 {
6538 case GFC_ISYM_EOSHIFT:
6539 case GFC_ISYM_PACK:
6540 case GFC_ISYM_RESHAPE:
6541 /* For all of those the first argument specifies the type and the
6542 third is optional. */
6543 conv_generic_with_optional_char_arg (se, expr, 1, 3);
6544 break;
6545
6546 default:
6547 gfc_conv_intrinsic_funcall (se, expr);
6548 break;
6549 }
6550
6551 return;
6552 }
6553 }
6554
6555 switch (expr->value.function.isym->id)
6556 {
6557 case GFC_ISYM_NONE:
6558 gcc_unreachable ();
6559
6560 case GFC_ISYM_REPEAT:
6561 gfc_conv_intrinsic_repeat (se, expr);
6562 break;
6563
6564 case GFC_ISYM_TRIM:
6565 gfc_conv_intrinsic_trim (se, expr);
6566 break;
6567
6568 case GFC_ISYM_SC_KIND:
6569 gfc_conv_intrinsic_sc_kind (se, expr);
6570 break;
6571
6572 case GFC_ISYM_SI_KIND:
6573 gfc_conv_intrinsic_si_kind (se, expr);
6574 break;
6575
6576 case GFC_ISYM_SR_KIND:
6577 gfc_conv_intrinsic_sr_kind (se, expr);
6578 break;
6579
6580 case GFC_ISYM_EXPONENT:
6581 gfc_conv_intrinsic_exponent (se, expr);
6582 break;
6583
6584 case GFC_ISYM_SCAN:
6585 kind = expr->value.function.actual->expr->ts.kind;
6586 if (kind == 1)
6587 fndecl = gfor_fndecl_string_scan;
6588 else if (kind == 4)
6589 fndecl = gfor_fndecl_string_scan_char4;
6590 else
6591 gcc_unreachable ();
6592
6593 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6594 break;
6595
6596 case GFC_ISYM_VERIFY:
6597 kind = expr->value.function.actual->expr->ts.kind;
6598 if (kind == 1)
6599 fndecl = gfor_fndecl_string_verify;
6600 else if (kind == 4)
6601 fndecl = gfor_fndecl_string_verify_char4;
6602 else
6603 gcc_unreachable ();
6604
6605 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6606 break;
6607
6608 case GFC_ISYM_ALLOCATED:
6609 gfc_conv_allocated (se, expr);
6610 break;
6611
6612 case GFC_ISYM_ASSOCIATED:
6613 gfc_conv_associated(se, expr);
6614 break;
6615
6616 case GFC_ISYM_SAME_TYPE_AS:
6617 gfc_conv_same_type_as (se, expr);
6618 break;
6619
6620 case GFC_ISYM_ABS:
6621 gfc_conv_intrinsic_abs (se, expr);
6622 break;
6623
6624 case GFC_ISYM_ADJUSTL:
6625 if (expr->ts.kind == 1)
6626 fndecl = gfor_fndecl_adjustl;
6627 else if (expr->ts.kind == 4)
6628 fndecl = gfor_fndecl_adjustl_char4;
6629 else
6630 gcc_unreachable ();
6631
6632 gfc_conv_intrinsic_adjust (se, expr, fndecl);
6633 break;
6634
6635 case GFC_ISYM_ADJUSTR:
6636 if (expr->ts.kind == 1)
6637 fndecl = gfor_fndecl_adjustr;
6638 else if (expr->ts.kind == 4)
6639 fndecl = gfor_fndecl_adjustr_char4;
6640 else
6641 gcc_unreachable ();
6642
6643 gfc_conv_intrinsic_adjust (se, expr, fndecl);
6644 break;
6645
6646 case GFC_ISYM_AIMAG:
6647 gfc_conv_intrinsic_imagpart (se, expr);
6648 break;
6649
6650 case GFC_ISYM_AINT:
6651 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
6652 break;
6653
6654 case GFC_ISYM_ALL:
6655 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
6656 break;
6657
6658 case GFC_ISYM_ANINT:
6659 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
6660 break;
6661
6662 case GFC_ISYM_AND:
6663 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
6664 break;
6665
6666 case GFC_ISYM_ANY:
6667 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
6668 break;
6669
6670 case GFC_ISYM_BTEST:
6671 gfc_conv_intrinsic_btest (se, expr);
6672 break;
6673
6674 case GFC_ISYM_BGE:
6675 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
6676 break;
6677
6678 case GFC_ISYM_BGT:
6679 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
6680 break;
6681
6682 case GFC_ISYM_BLE:
6683 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
6684 break;
6685
6686 case GFC_ISYM_BLT:
6687 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
6688 break;
6689
6690 case GFC_ISYM_C_ASSOCIATED:
6691 case GFC_ISYM_C_FUNLOC:
6692 case GFC_ISYM_C_LOC:
6693 conv_isocbinding_function (se, expr);
6694 break;
6695
6696 case GFC_ISYM_ACHAR:
6697 case GFC_ISYM_CHAR:
6698 gfc_conv_intrinsic_char (se, expr);
6699 break;
6700
6701 case GFC_ISYM_CONVERSION:
6702 case GFC_ISYM_REAL:
6703 case GFC_ISYM_LOGICAL:
6704 case GFC_ISYM_DBLE:
6705 gfc_conv_intrinsic_conversion (se, expr);
6706 break;
6707
6708 /* Integer conversions are handled separately to make sure we get the
6709 correct rounding mode. */
6710 case GFC_ISYM_INT:
6711 case GFC_ISYM_INT2:
6712 case GFC_ISYM_INT8:
6713 case GFC_ISYM_LONG:
6714 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
6715 break;
6716
6717 case GFC_ISYM_NINT:
6718 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
6719 break;
6720
6721 case GFC_ISYM_CEILING:
6722 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
6723 break;
6724
6725 case GFC_ISYM_FLOOR:
6726 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
6727 break;
6728
6729 case GFC_ISYM_MOD:
6730 gfc_conv_intrinsic_mod (se, expr, 0);
6731 break;
6732
6733 case GFC_ISYM_MODULO:
6734 gfc_conv_intrinsic_mod (se, expr, 1);
6735 break;
6736
6737 case GFC_ISYM_CMPLX:
6738 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
6739 break;
6740
6741 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
6742 gfc_conv_intrinsic_iargc (se, expr);
6743 break;
6744
6745 case GFC_ISYM_COMPLEX:
6746 gfc_conv_intrinsic_cmplx (se, expr, 1);
6747 break;
6748
6749 case GFC_ISYM_CONJG:
6750 gfc_conv_intrinsic_conjg (se, expr);
6751 break;
6752
6753 case GFC_ISYM_COUNT:
6754 gfc_conv_intrinsic_count (se, expr);
6755 break;
6756
6757 case GFC_ISYM_CTIME:
6758 gfc_conv_intrinsic_ctime (se, expr);
6759 break;
6760
6761 case GFC_ISYM_DIM:
6762 gfc_conv_intrinsic_dim (se, expr);
6763 break;
6764
6765 case GFC_ISYM_DOT_PRODUCT:
6766 gfc_conv_intrinsic_dot_product (se, expr);
6767 break;
6768
6769 case GFC_ISYM_DPROD:
6770 gfc_conv_intrinsic_dprod (se, expr);
6771 break;
6772
6773 case GFC_ISYM_DSHIFTL:
6774 gfc_conv_intrinsic_dshift (se, expr, true);
6775 break;
6776
6777 case GFC_ISYM_DSHIFTR:
6778 gfc_conv_intrinsic_dshift (se, expr, false);
6779 break;
6780
6781 case GFC_ISYM_FDATE:
6782 gfc_conv_intrinsic_fdate (se, expr);
6783 break;
6784
6785 case GFC_ISYM_FRACTION:
6786 gfc_conv_intrinsic_fraction (se, expr);
6787 break;
6788
6789 case GFC_ISYM_IALL:
6790 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
6791 break;
6792
6793 case GFC_ISYM_IAND:
6794 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
6795 break;
6796
6797 case GFC_ISYM_IANY:
6798 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
6799 break;
6800
6801 case GFC_ISYM_IBCLR:
6802 gfc_conv_intrinsic_singlebitop (se, expr, 0);
6803 break;
6804
6805 case GFC_ISYM_IBITS:
6806 gfc_conv_intrinsic_ibits (se, expr);
6807 break;
6808
6809 case GFC_ISYM_IBSET:
6810 gfc_conv_intrinsic_singlebitop (se, expr, 1);
6811 break;
6812
6813 case GFC_ISYM_IACHAR:
6814 case GFC_ISYM_ICHAR:
6815 /* We assume ASCII character sequence. */
6816 gfc_conv_intrinsic_ichar (se, expr);
6817 break;
6818
6819 case GFC_ISYM_IARGC:
6820 gfc_conv_intrinsic_iargc (se, expr);
6821 break;
6822
6823 case GFC_ISYM_IEOR:
6824 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
6825 break;
6826
6827 case GFC_ISYM_INDEX:
6828 kind = expr->value.function.actual->expr->ts.kind;
6829 if (kind == 1)
6830 fndecl = gfor_fndecl_string_index;
6831 else if (kind == 4)
6832 fndecl = gfor_fndecl_string_index_char4;
6833 else
6834 gcc_unreachable ();
6835
6836 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6837 break;
6838
6839 case GFC_ISYM_IOR:
6840 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
6841 break;
6842
6843 case GFC_ISYM_IPARITY:
6844 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
6845 break;
6846
6847 case GFC_ISYM_IS_IOSTAT_END:
6848 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
6849 break;
6850
6851 case GFC_ISYM_IS_IOSTAT_EOR:
6852 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
6853 break;
6854
6855 case GFC_ISYM_ISNAN:
6856 gfc_conv_intrinsic_isnan (se, expr);
6857 break;
6858
6859 case GFC_ISYM_LSHIFT:
6860 gfc_conv_intrinsic_shift (se, expr, false, false);
6861 break;
6862
6863 case GFC_ISYM_RSHIFT:
6864 gfc_conv_intrinsic_shift (se, expr, true, true);
6865 break;
6866
6867 case GFC_ISYM_SHIFTA:
6868 gfc_conv_intrinsic_shift (se, expr, true, true);
6869 break;
6870
6871 case GFC_ISYM_SHIFTL:
6872 gfc_conv_intrinsic_shift (se, expr, false, false);
6873 break;
6874
6875 case GFC_ISYM_SHIFTR:
6876 gfc_conv_intrinsic_shift (se, expr, true, false);
6877 break;
6878
6879 case GFC_ISYM_ISHFT:
6880 gfc_conv_intrinsic_ishft (se, expr);
6881 break;
6882
6883 case GFC_ISYM_ISHFTC:
6884 gfc_conv_intrinsic_ishftc (se, expr);
6885 break;
6886
6887 case GFC_ISYM_LEADZ:
6888 gfc_conv_intrinsic_leadz (se, expr);
6889 break;
6890
6891 case GFC_ISYM_TRAILZ:
6892 gfc_conv_intrinsic_trailz (se, expr);
6893 break;
6894
6895 case GFC_ISYM_POPCNT:
6896 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
6897 break;
6898
6899 case GFC_ISYM_POPPAR:
6900 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
6901 break;
6902
6903 case GFC_ISYM_LBOUND:
6904 gfc_conv_intrinsic_bound (se, expr, 0);
6905 break;
6906
6907 case GFC_ISYM_LCOBOUND:
6908 conv_intrinsic_cobound (se, expr);
6909 break;
6910
6911 case GFC_ISYM_TRANSPOSE:
6912 /* The scalarizer has already been set up for reversed dimension access
6913 order ; now we just get the argument value normally. */
6914 gfc_conv_expr (se, expr->value.function.actual->expr);
6915 break;
6916
6917 case GFC_ISYM_LEN:
6918 gfc_conv_intrinsic_len (se, expr);
6919 break;
6920
6921 case GFC_ISYM_LEN_TRIM:
6922 gfc_conv_intrinsic_len_trim (se, expr);
6923 break;
6924
6925 case GFC_ISYM_LGE:
6926 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
6927 break;
6928
6929 case GFC_ISYM_LGT:
6930 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
6931 break;
6932
6933 case GFC_ISYM_LLE:
6934 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
6935 break;
6936
6937 case GFC_ISYM_LLT:
6938 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
6939 break;
6940
6941 case GFC_ISYM_MASKL:
6942 gfc_conv_intrinsic_mask (se, expr, 1);
6943 break;
6944
6945 case GFC_ISYM_MASKR:
6946 gfc_conv_intrinsic_mask (se, expr, 0);
6947 break;
6948
6949 case GFC_ISYM_MAX:
6950 if (expr->ts.type == BT_CHARACTER)
6951 gfc_conv_intrinsic_minmax_char (se, expr, 1);
6952 else
6953 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
6954 break;
6955
6956 case GFC_ISYM_MAXLOC:
6957 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
6958 break;
6959
6960 case GFC_ISYM_MAXVAL:
6961 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
6962 break;
6963
6964 case GFC_ISYM_MERGE:
6965 gfc_conv_intrinsic_merge (se, expr);
6966 break;
6967
6968 case GFC_ISYM_MERGE_BITS:
6969 gfc_conv_intrinsic_merge_bits (se, expr);
6970 break;
6971
6972 case GFC_ISYM_MIN:
6973 if (expr->ts.type == BT_CHARACTER)
6974 gfc_conv_intrinsic_minmax_char (se, expr, -1);
6975 else
6976 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
6977 break;
6978
6979 case GFC_ISYM_MINLOC:
6980 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
6981 break;
6982
6983 case GFC_ISYM_MINVAL:
6984 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
6985 break;
6986
6987 case GFC_ISYM_NEAREST:
6988 gfc_conv_intrinsic_nearest (se, expr);
6989 break;
6990
6991 case GFC_ISYM_NORM2:
6992 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
6993 break;
6994
6995 case GFC_ISYM_NOT:
6996 gfc_conv_intrinsic_not (se, expr);
6997 break;
6998
6999 case GFC_ISYM_OR:
7000 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
7001 break;
7002
7003 case GFC_ISYM_PARITY:
7004 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
7005 break;
7006
7007 case GFC_ISYM_PRESENT:
7008 gfc_conv_intrinsic_present (se, expr);
7009 break;
7010
7011 case GFC_ISYM_PRODUCT:
7012 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
7013 break;
7014
7015 case GFC_ISYM_RANK:
7016 gfc_conv_intrinsic_rank (se, expr);
7017 break;
7018
7019 case GFC_ISYM_RRSPACING:
7020 gfc_conv_intrinsic_rrspacing (se, expr);
7021 break;
7022
7023 case GFC_ISYM_SET_EXPONENT:
7024 gfc_conv_intrinsic_set_exponent (se, expr);
7025 break;
7026
7027 case GFC_ISYM_SCALE:
7028 gfc_conv_intrinsic_scale (se, expr);
7029 break;
7030
7031 case GFC_ISYM_SIGN:
7032 gfc_conv_intrinsic_sign (se, expr);
7033 break;
7034
7035 case GFC_ISYM_SIZE:
7036 gfc_conv_intrinsic_size (se, expr);
7037 break;
7038
7039 case GFC_ISYM_SIZEOF:
7040 case GFC_ISYM_C_SIZEOF:
7041 gfc_conv_intrinsic_sizeof (se, expr);
7042 break;
7043
7044 case GFC_ISYM_STORAGE_SIZE:
7045 gfc_conv_intrinsic_storage_size (se, expr);
7046 break;
7047
7048 case GFC_ISYM_SPACING:
7049 gfc_conv_intrinsic_spacing (se, expr);
7050 break;
7051
7052 case GFC_ISYM_STRIDE:
7053 conv_intrinsic_stride (se, expr);
7054 break;
7055
7056 case GFC_ISYM_SUM:
7057 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
7058 break;
7059
7060 case GFC_ISYM_TRANSFER:
7061 if (se->ss && se->ss->info->useflags)
7062 /* Access the previously obtained result. */
7063 gfc_conv_tmp_array_ref (se);
7064 else
7065 gfc_conv_intrinsic_transfer (se, expr);
7066 break;
7067
7068 case GFC_ISYM_TTYNAM:
7069 gfc_conv_intrinsic_ttynam (se, expr);
7070 break;
7071
7072 case GFC_ISYM_UBOUND:
7073 gfc_conv_intrinsic_bound (se, expr, 1);
7074 break;
7075
7076 case GFC_ISYM_UCOBOUND:
7077 conv_intrinsic_cobound (se, expr);
7078 break;
7079
7080 case GFC_ISYM_XOR:
7081 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
7082 break;
7083
7084 case GFC_ISYM_LOC:
7085 gfc_conv_intrinsic_loc (se, expr);
7086 break;
7087
7088 case GFC_ISYM_THIS_IMAGE:
7089 /* For num_images() == 1, handle as LCOBOUND. */
7090 if (expr->value.function.actual->expr
7091 && gfc_option.coarray == GFC_FCOARRAY_SINGLE)
7092 conv_intrinsic_cobound (se, expr);
7093 else
7094 trans_this_image (se, expr);
7095 break;
7096
7097 case GFC_ISYM_IMAGE_INDEX:
7098 trans_image_index (se, expr);
7099 break;
7100
7101 case GFC_ISYM_NUM_IMAGES:
7102 trans_num_images (se);
7103 break;
7104
7105 case GFC_ISYM_ACCESS:
7106 case GFC_ISYM_CHDIR:
7107 case GFC_ISYM_CHMOD:
7108 case GFC_ISYM_DTIME:
7109 case GFC_ISYM_ETIME:
7110 case GFC_ISYM_EXTENDS_TYPE_OF:
7111 case GFC_ISYM_FGET:
7112 case GFC_ISYM_FGETC:
7113 case GFC_ISYM_FNUM:
7114 case GFC_ISYM_FPUT:
7115 case GFC_ISYM_FPUTC:
7116 case GFC_ISYM_FSTAT:
7117 case GFC_ISYM_FTELL:
7118 case GFC_ISYM_GETCWD:
7119 case GFC_ISYM_GETGID:
7120 case GFC_ISYM_GETPID:
7121 case GFC_ISYM_GETUID:
7122 case GFC_ISYM_HOSTNM:
7123 case GFC_ISYM_KILL:
7124 case GFC_ISYM_IERRNO:
7125 case GFC_ISYM_IRAND:
7126 case GFC_ISYM_ISATTY:
7127 case GFC_ISYM_JN2:
7128 case GFC_ISYM_LINK:
7129 case GFC_ISYM_LSTAT:
7130 case GFC_ISYM_MALLOC:
7131 case GFC_ISYM_MATMUL:
7132 case GFC_ISYM_MCLOCK:
7133 case GFC_ISYM_MCLOCK8:
7134 case GFC_ISYM_RAND:
7135 case GFC_ISYM_RENAME:
7136 case GFC_ISYM_SECOND:
7137 case GFC_ISYM_SECNDS:
7138 case GFC_ISYM_SIGNAL:
7139 case GFC_ISYM_STAT:
7140 case GFC_ISYM_SYMLNK:
7141 case GFC_ISYM_SYSTEM:
7142 case GFC_ISYM_TIME:
7143 case GFC_ISYM_TIME8:
7144 case GFC_ISYM_UMASK:
7145 case GFC_ISYM_UNLINK:
7146 case GFC_ISYM_YN2:
7147 gfc_conv_intrinsic_funcall (se, expr);
7148 break;
7149
7150 case GFC_ISYM_EOSHIFT:
7151 case GFC_ISYM_PACK:
7152 case GFC_ISYM_RESHAPE:
7153 /* For those, expr->rank should always be >0 and thus the if above the
7154 switch should have matched. */
7155 gcc_unreachable ();
7156 break;
7157
7158 default:
7159 gfc_conv_intrinsic_lib_function (se, expr);
7160 break;
7161 }
7162 }
7163
7164
7165 static gfc_ss *
7166 walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
7167 {
7168 gfc_ss *arg_ss, *tmp_ss;
7169 gfc_actual_arglist *arg;
7170
7171 arg = expr->value.function.actual;
7172
7173 gcc_assert (arg->expr);
7174
7175 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
7176 gcc_assert (arg_ss != gfc_ss_terminator);
7177
7178 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
7179 {
7180 if (tmp_ss->info->type != GFC_SS_SCALAR
7181 && tmp_ss->info->type != GFC_SS_REFERENCE)
7182 {
7183 int tmp_dim;
7184
7185 gcc_assert (tmp_ss->dimen == 2);
7186
7187 /* We just invert dimensions. */
7188 tmp_dim = tmp_ss->dim[0];
7189 tmp_ss->dim[0] = tmp_ss->dim[1];
7190 tmp_ss->dim[1] = tmp_dim;
7191 }
7192
7193 /* Stop when tmp_ss points to the last valid element of the chain... */
7194 if (tmp_ss->next == gfc_ss_terminator)
7195 break;
7196 }
7197
7198 /* ... so that we can attach the rest of the chain to it. */
7199 tmp_ss->next = ss;
7200
7201 return arg_ss;
7202 }
7203
7204
7205 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
7206 This has the side effect of reversing the nested list, so there is no
7207 need to call gfc_reverse_ss on it (the given list is assumed not to be
7208 reversed yet). */
7209
7210 static gfc_ss *
7211 nest_loop_dimension (gfc_ss *ss, int dim)
7212 {
7213 int ss_dim, i;
7214 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
7215 gfc_loopinfo *new_loop;
7216
7217 gcc_assert (ss != gfc_ss_terminator);
7218
7219 for (; ss != gfc_ss_terminator; ss = ss->next)
7220 {
7221 new_ss = gfc_get_ss ();
7222 new_ss->next = prev_ss;
7223 new_ss->parent = ss;
7224 new_ss->info = ss->info;
7225 new_ss->info->refcount++;
7226 if (ss->dimen != 0)
7227 {
7228 gcc_assert (ss->info->type != GFC_SS_SCALAR
7229 && ss->info->type != GFC_SS_REFERENCE);
7230
7231 new_ss->dimen = 1;
7232 new_ss->dim[0] = ss->dim[dim];
7233
7234 gcc_assert (dim < ss->dimen);
7235
7236 ss_dim = --ss->dimen;
7237 for (i = dim; i < ss_dim; i++)
7238 ss->dim[i] = ss->dim[i + 1];
7239
7240 ss->dim[ss_dim] = 0;
7241 }
7242 prev_ss = new_ss;
7243
7244 if (ss->nested_ss)
7245 {
7246 ss->nested_ss->parent = new_ss;
7247 new_ss->nested_ss = ss->nested_ss;
7248 }
7249 ss->nested_ss = new_ss;
7250 }
7251
7252 new_loop = gfc_get_loopinfo ();
7253 gfc_init_loopinfo (new_loop);
7254
7255 gcc_assert (prev_ss != NULL);
7256 gcc_assert (prev_ss != gfc_ss_terminator);
7257 gfc_add_ss_to_loop (new_loop, prev_ss);
7258 return new_ss->parent;
7259 }
7260
7261
7262 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
7263 is to be inlined. */
7264
7265 static gfc_ss *
7266 walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
7267 {
7268 gfc_ss *tmp_ss, *tail, *array_ss;
7269 gfc_actual_arglist *arg1, *arg2, *arg3;
7270 int sum_dim;
7271 bool scalar_mask = false;
7272
7273 /* The rank of the result will be determined later. */
7274 arg1 = expr->value.function.actual;
7275 arg2 = arg1->next;
7276 arg3 = arg2->next;
7277 gcc_assert (arg3 != NULL);
7278
7279 if (expr->rank == 0)
7280 return ss;
7281
7282 tmp_ss = gfc_ss_terminator;
7283
7284 if (arg3->expr)
7285 {
7286 gfc_ss *mask_ss;
7287
7288 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
7289 if (mask_ss == tmp_ss)
7290 scalar_mask = 1;
7291
7292 tmp_ss = mask_ss;
7293 }
7294
7295 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
7296 gcc_assert (array_ss != tmp_ss);
7297
7298 /* Odd thing: If the mask is scalar, it is used by the frontend after
7299 the array (to make an if around the nested loop). Thus it shall
7300 be after array_ss once the gfc_ss list is reversed. */
7301 if (scalar_mask)
7302 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
7303 else
7304 tmp_ss = array_ss;
7305
7306 /* "Hide" the dimension on which we will sum in the first arg's scalarization
7307 chain. */
7308 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
7309 tail = nest_loop_dimension (tmp_ss, sum_dim);
7310 tail->next = ss;
7311
7312 return tmp_ss;
7313 }
7314
7315
7316 static gfc_ss *
7317 walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
7318 {
7319
7320 switch (expr->value.function.isym->id)
7321 {
7322 case GFC_ISYM_PRODUCT:
7323 case GFC_ISYM_SUM:
7324 return walk_inline_intrinsic_arith (ss, expr);
7325
7326 case GFC_ISYM_TRANSPOSE:
7327 return walk_inline_intrinsic_transpose (ss, expr);
7328
7329 default:
7330 gcc_unreachable ();
7331 }
7332 gcc_unreachable ();
7333 }
7334
7335
7336 /* This generates code to execute before entering the scalarization loop.
7337 Currently does nothing. */
7338
7339 void
7340 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
7341 {
7342 switch (ss->info->expr->value.function.isym->id)
7343 {
7344 case GFC_ISYM_UBOUND:
7345 case GFC_ISYM_LBOUND:
7346 case GFC_ISYM_UCOBOUND:
7347 case GFC_ISYM_LCOBOUND:
7348 case GFC_ISYM_THIS_IMAGE:
7349 break;
7350
7351 default:
7352 gcc_unreachable ();
7353 }
7354 }
7355
7356
7357 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
7358 are expanded into code inside the scalarization loop. */
7359
7360 static gfc_ss *
7361 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
7362 {
7363 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
7364 gfc_add_class_array_ref (expr->value.function.actual->expr);
7365
7366 /* The two argument version returns a scalar. */
7367 if (expr->value.function.actual->next->expr)
7368 return ss;
7369
7370 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
7371 }
7372
7373
7374 /* Walk an intrinsic array libcall. */
7375
7376 static gfc_ss *
7377 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
7378 {
7379 gcc_assert (expr->rank > 0);
7380 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
7381 }
7382
7383
7384 /* Return whether the function call expression EXPR will be expanded
7385 inline by gfc_conv_intrinsic_function. */
7386
7387 bool
7388 gfc_inline_intrinsic_function_p (gfc_expr *expr)
7389 {
7390 gfc_actual_arglist *args;
7391
7392 if (!expr->value.function.isym)
7393 return false;
7394
7395 switch (expr->value.function.isym->id)
7396 {
7397 case GFC_ISYM_PRODUCT:
7398 case GFC_ISYM_SUM:
7399 /* Disable inline expansion if code size matters. */
7400 if (optimize_size)
7401 return false;
7402
7403 args = expr->value.function.actual;
7404 /* We need to be able to subset the SUM argument at compile-time. */
7405 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
7406 return false;
7407
7408 return true;
7409
7410 case GFC_ISYM_TRANSPOSE:
7411 return true;
7412
7413 default:
7414 return false;
7415 }
7416 }
7417
7418
7419 /* Returns nonzero if the specified intrinsic function call maps directly to
7420 an external library call. Should only be used for functions that return
7421 arrays. */
7422
7423 int
7424 gfc_is_intrinsic_libcall (gfc_expr * expr)
7425 {
7426 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
7427 gcc_assert (expr->rank > 0);
7428
7429 if (gfc_inline_intrinsic_function_p (expr))
7430 return 0;
7431
7432 switch (expr->value.function.isym->id)
7433 {
7434 case GFC_ISYM_ALL:
7435 case GFC_ISYM_ANY:
7436 case GFC_ISYM_COUNT:
7437 case GFC_ISYM_JN2:
7438 case GFC_ISYM_IANY:
7439 case GFC_ISYM_IALL:
7440 case GFC_ISYM_IPARITY:
7441 case GFC_ISYM_MATMUL:
7442 case GFC_ISYM_MAXLOC:
7443 case GFC_ISYM_MAXVAL:
7444 case GFC_ISYM_MINLOC:
7445 case GFC_ISYM_MINVAL:
7446 case GFC_ISYM_NORM2:
7447 case GFC_ISYM_PARITY:
7448 case GFC_ISYM_PRODUCT:
7449 case GFC_ISYM_SUM:
7450 case GFC_ISYM_SHAPE:
7451 case GFC_ISYM_SPREAD:
7452 case GFC_ISYM_YN2:
7453 /* Ignore absent optional parameters. */
7454 return 1;
7455
7456 case GFC_ISYM_RESHAPE:
7457 case GFC_ISYM_CSHIFT:
7458 case GFC_ISYM_EOSHIFT:
7459 case GFC_ISYM_PACK:
7460 case GFC_ISYM_UNPACK:
7461 /* Pass absent optional parameters. */
7462 return 2;
7463
7464 default:
7465 return 0;
7466 }
7467 }
7468
7469 /* Walk an intrinsic function. */
7470 gfc_ss *
7471 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
7472 gfc_intrinsic_sym * isym)
7473 {
7474 gcc_assert (isym);
7475
7476 if (isym->elemental)
7477 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
7478 NULL, GFC_SS_SCALAR);
7479
7480 if (expr->rank == 0)
7481 return ss;
7482
7483 if (gfc_inline_intrinsic_function_p (expr))
7484 return walk_inline_intrinsic_function (ss, expr);
7485
7486 if (gfc_is_intrinsic_libcall (expr))
7487 return gfc_walk_intrinsic_libfunc (ss, expr);
7488
7489 /* Special cases. */
7490 switch (isym->id)
7491 {
7492 case GFC_ISYM_LBOUND:
7493 case GFC_ISYM_LCOBOUND:
7494 case GFC_ISYM_UBOUND:
7495 case GFC_ISYM_UCOBOUND:
7496 case GFC_ISYM_THIS_IMAGE:
7497 return gfc_walk_intrinsic_bound (ss, expr);
7498
7499 case GFC_ISYM_TRANSFER:
7500 return gfc_walk_intrinsic_libfunc (ss, expr);
7501
7502 default:
7503 /* This probably meant someone forgot to add an intrinsic to the above
7504 list(s) when they implemented it, or something's gone horribly
7505 wrong. */
7506 gcc_unreachable ();
7507 }
7508 }
7509
7510
7511 static tree
7512 conv_intrinsic_atomic_def (gfc_code *code)
7513 {
7514 gfc_se atom, value;
7515 stmtblock_t block;
7516
7517 gfc_init_se (&atom, NULL);
7518 gfc_init_se (&value, NULL);
7519 gfc_conv_expr (&atom, code->ext.actual->expr);
7520 gfc_conv_expr (&value, code->ext.actual->next->expr);
7521
7522 gfc_init_block (&block);
7523 gfc_add_modify (&block, atom.expr,
7524 fold_convert (TREE_TYPE (atom.expr), value.expr));
7525 return gfc_finish_block (&block);
7526 }
7527
7528
7529 static tree
7530 conv_intrinsic_atomic_ref (gfc_code *code)
7531 {
7532 gfc_se atom, value;
7533 stmtblock_t block;
7534
7535 gfc_init_se (&atom, NULL);
7536 gfc_init_se (&value, NULL);
7537 gfc_conv_expr (&value, code->ext.actual->expr);
7538 gfc_conv_expr (&atom, code->ext.actual->next->expr);
7539
7540 gfc_init_block (&block);
7541 gfc_add_modify (&block, value.expr,
7542 fold_convert (TREE_TYPE (value.expr), atom.expr));
7543 return gfc_finish_block (&block);
7544 }
7545
7546
7547 static tree
7548 conv_intrinsic_move_alloc (gfc_code *code)
7549 {
7550 stmtblock_t block;
7551 gfc_expr *from_expr, *to_expr;
7552 gfc_expr *to_expr2, *from_expr2 = NULL;
7553 gfc_se from_se, to_se;
7554 tree tmp;
7555 bool coarray;
7556
7557 gfc_start_block (&block);
7558
7559 from_expr = code->ext.actual->expr;
7560 to_expr = code->ext.actual->next->expr;
7561
7562 gfc_init_se (&from_se, NULL);
7563 gfc_init_se (&to_se, NULL);
7564
7565 gcc_assert (from_expr->ts.type != BT_CLASS
7566 || to_expr->ts.type == BT_CLASS);
7567 coarray = gfc_get_corank (from_expr) != 0;
7568
7569 if (from_expr->rank == 0 && !coarray)
7570 {
7571 if (from_expr->ts.type != BT_CLASS)
7572 from_expr2 = from_expr;
7573 else
7574 {
7575 from_expr2 = gfc_copy_expr (from_expr);
7576 gfc_add_data_component (from_expr2);
7577 }
7578
7579 if (to_expr->ts.type != BT_CLASS)
7580 to_expr2 = to_expr;
7581 else
7582 {
7583 to_expr2 = gfc_copy_expr (to_expr);
7584 gfc_add_data_component (to_expr2);
7585 }
7586
7587 from_se.want_pointer = 1;
7588 to_se.want_pointer = 1;
7589 gfc_conv_expr (&from_se, from_expr2);
7590 gfc_conv_expr (&to_se, to_expr2);
7591 gfc_add_block_to_block (&block, &from_se.pre);
7592 gfc_add_block_to_block (&block, &to_se.pre);
7593
7594 /* Deallocate "to". */
7595 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, true,
7596 to_expr, to_expr->ts);
7597 gfc_add_expr_to_block (&block, tmp);
7598
7599 /* Assign (_data) pointers. */
7600 gfc_add_modify_loc (input_location, &block, to_se.expr,
7601 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
7602
7603 /* Set "from" to NULL. */
7604 gfc_add_modify_loc (input_location, &block, from_se.expr,
7605 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
7606
7607 gfc_add_block_to_block (&block, &from_se.post);
7608 gfc_add_block_to_block (&block, &to_se.post);
7609
7610 /* Set _vptr. */
7611 if (to_expr->ts.type == BT_CLASS)
7612 {
7613 gfc_symbol *vtab;
7614
7615 gfc_free_expr (to_expr2);
7616 gfc_init_se (&to_se, NULL);
7617 to_se.want_pointer = 1;
7618 gfc_add_vptr_component (to_expr);
7619 gfc_conv_expr (&to_se, to_expr);
7620
7621 if (from_expr->ts.type == BT_CLASS)
7622 {
7623 if (UNLIMITED_POLY (from_expr))
7624 vtab = NULL;
7625 else
7626 {
7627 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
7628 gcc_assert (vtab);
7629 }
7630
7631 gfc_free_expr (from_expr2);
7632 gfc_init_se (&from_se, NULL);
7633 from_se.want_pointer = 1;
7634 gfc_add_vptr_component (from_expr);
7635 gfc_conv_expr (&from_se, from_expr);
7636 gfc_add_modify_loc (input_location, &block, to_se.expr,
7637 fold_convert (TREE_TYPE (to_se.expr),
7638 from_se.expr));
7639
7640 /* Reset _vptr component to declared type. */
7641 if (vtab == NULL)
7642 /* Unlimited polymorphic. */
7643 gfc_add_modify_loc (input_location, &block, from_se.expr,
7644 fold_convert (TREE_TYPE (from_se.expr),
7645 null_pointer_node));
7646 else
7647 {
7648 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7649 gfc_add_modify_loc (input_location, &block, from_se.expr,
7650 fold_convert (TREE_TYPE (from_se.expr), tmp));
7651 }
7652 }
7653 else
7654 {
7655 vtab = gfc_find_vtab (&from_expr->ts);
7656 gcc_assert (vtab);
7657 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7658 gfc_add_modify_loc (input_location, &block, to_se.expr,
7659 fold_convert (TREE_TYPE (to_se.expr), tmp));
7660 }
7661 }
7662
7663 return gfc_finish_block (&block);
7664 }
7665
7666 /* Update _vptr component. */
7667 if (to_expr->ts.type == BT_CLASS)
7668 {
7669 gfc_symbol *vtab;
7670
7671 to_se.want_pointer = 1;
7672 to_expr2 = gfc_copy_expr (to_expr);
7673 gfc_add_vptr_component (to_expr2);
7674 gfc_conv_expr (&to_se, to_expr2);
7675
7676 if (from_expr->ts.type == BT_CLASS)
7677 {
7678 if (UNLIMITED_POLY (from_expr))
7679 vtab = NULL;
7680 else
7681 {
7682 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
7683 gcc_assert (vtab);
7684 }
7685
7686 from_se.want_pointer = 1;
7687 from_expr2 = gfc_copy_expr (from_expr);
7688 gfc_add_vptr_component (from_expr2);
7689 gfc_conv_expr (&from_se, from_expr2);
7690 gfc_add_modify_loc (input_location, &block, to_se.expr,
7691 fold_convert (TREE_TYPE (to_se.expr),
7692 from_se.expr));
7693
7694 /* Reset _vptr component to declared type. */
7695 if (vtab == NULL)
7696 /* Unlimited polymorphic. */
7697 gfc_add_modify_loc (input_location, &block, from_se.expr,
7698 fold_convert (TREE_TYPE (from_se.expr),
7699 null_pointer_node));
7700 else
7701 {
7702 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7703 gfc_add_modify_loc (input_location, &block, from_se.expr,
7704 fold_convert (TREE_TYPE (from_se.expr), tmp));
7705 }
7706 }
7707 else
7708 {
7709 vtab = gfc_find_vtab (&from_expr->ts);
7710 gcc_assert (vtab);
7711 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7712 gfc_add_modify_loc (input_location, &block, to_se.expr,
7713 fold_convert (TREE_TYPE (to_se.expr), tmp));
7714 }
7715
7716 gfc_free_expr (to_expr2);
7717 gfc_init_se (&to_se, NULL);
7718
7719 if (from_expr->ts.type == BT_CLASS)
7720 {
7721 gfc_free_expr (from_expr2);
7722 gfc_init_se (&from_se, NULL);
7723 }
7724 }
7725
7726
7727 /* Deallocate "to". */
7728 if (from_expr->rank == 0)
7729 {
7730 to_se.want_coarray = 1;
7731 from_se.want_coarray = 1;
7732 }
7733 gfc_conv_expr_descriptor (&to_se, to_expr);
7734 gfc_conv_expr_descriptor (&from_se, from_expr);
7735
7736 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
7737 is an image control "statement", cf. IR F08/0040 in 12-006A. */
7738 if (coarray && gfc_option.coarray == GFC_FCOARRAY_LIB)
7739 {
7740 tree cond;
7741
7742 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
7743 NULL_TREE, NULL_TREE, true, to_expr,
7744 true);
7745 gfc_add_expr_to_block (&block, tmp);
7746
7747 tmp = gfc_conv_descriptor_data_get (to_se.expr);
7748 cond = fold_build2_loc (input_location, EQ_EXPR,
7749 boolean_type_node, tmp,
7750 fold_convert (TREE_TYPE (tmp),
7751 null_pointer_node));
7752 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
7753 3, null_pointer_node, null_pointer_node,
7754 build_int_cst (integer_type_node, 0));
7755
7756 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
7757 tmp, build_empty_stmt (input_location));
7758 gfc_add_expr_to_block (&block, tmp);
7759 }
7760 else
7761 {
7762 tmp = gfc_conv_descriptor_data_get (to_se.expr);
7763 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
7764 NULL_TREE, true, to_expr, false);
7765 gfc_add_expr_to_block (&block, tmp);
7766 }
7767
7768 /* Move the pointer and update the array descriptor data. */
7769 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
7770
7771 /* Set "from" to NULL. */
7772 tmp = gfc_conv_descriptor_data_get (from_se.expr);
7773 gfc_add_modify_loc (input_location, &block, tmp,
7774 fold_convert (TREE_TYPE (tmp), null_pointer_node));
7775
7776 return gfc_finish_block (&block);
7777 }
7778
7779
7780 tree
7781 gfc_conv_intrinsic_subroutine (gfc_code *code)
7782 {
7783 tree res;
7784
7785 gcc_assert (code->resolved_isym);
7786
7787 switch (code->resolved_isym->id)
7788 {
7789 case GFC_ISYM_MOVE_ALLOC:
7790 res = conv_intrinsic_move_alloc (code);
7791 break;
7792
7793 case GFC_ISYM_ATOMIC_DEF:
7794 res = conv_intrinsic_atomic_def (code);
7795 break;
7796
7797 case GFC_ISYM_ATOMIC_REF:
7798 res = conv_intrinsic_atomic_ref (code);
7799 break;
7800
7801 case GFC_ISYM_C_F_POINTER:
7802 case GFC_ISYM_C_F_PROCPOINTER:
7803 res = conv_isocbinding_subroutine (code);
7804 break;
7805
7806
7807 default:
7808 res = NULL_TREE;
7809 break;
7810 }
7811
7812 return res;
7813 }
7814
7815 #include "gt-fortran-trans-intrinsic.h"