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