comparison gcc/fortran/trans-intrinsic.c @ 111:04ced10e8804

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