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