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