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