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