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