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