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