]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-intrinsic.c
Update copyright years.
[thirdparty/gcc.git] / gcc / fortran / trans-intrinsic.c
CommitLineData
4ee9c684 1/* Intrinsic translation
f1717362 2 Copyright (C) 2002-2016 Free Software Foundation, Inc.
4ee9c684 3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
5
c84b470d 6This file is part of GCC.
4ee9c684 7
c84b470d 8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
bdabe786 10Software Foundation; either version 3, or (at your option) any later
c84b470d 11version.
4ee9c684 12
c84b470d 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
4ee9c684 17
18You should have received a copy of the GNU General Public License
bdabe786 19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
4ee9c684 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"
989adef3 27#include "tm.h" /* For UNITS_PER_WORD. */
4ee9c684 28#include "tree.h"
4cba6f60 29#include "gfortran.h"
30#include "trans.h"
9ed99284 31#include "stringpool.h"
4cba6f60 32#include "fold-const.h"
9ed99284 33#include "tree-nested.h"
34#include "stor-layout.h"
7cbc820e 35#include "toplev.h" /* For rest_of_decl_compilation. */
4b1085db 36#include "arith.h"
4ee9c684 37#include "trans-const.h"
38#include "trans-types.h"
39#include "trans-array.h"
9f1c76f9 40#include "dependency.h" /* For CAF array alias analysis. */
4ee9c684 41/* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
4ee9c684 42
df084314 43/* This maps Fortran intrinsic math functions to external library or GCC
4ee9c684 44 builtin functions. */
fb1e4f4a 45typedef struct GTY(()) gfc_intrinsic_map_t {
4ee9c684 46 /* The explicit enum is required to work around inadequacies in the
47 garbage collection/gengtype parsing mechanism. */
55cb4417 48 enum gfc_isym_id id;
4ee9c684 49
50 /* Enum value from the "language-independent", aka C-centric, part
51 of gcc, or END_BUILTINS of no such value set. */
a80ae91c 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;
4ee9c684 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
920e54ef 61 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
4ee9c684 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;
920e54ef 76 tree real10_decl;
77 tree real16_decl;
4ee9c684 78 tree complex4_decl;
79 tree complex8_decl;
920e54ef 80 tree complex10_decl;
81 tree complex16_decl;
4ee9c684 82}
83gfc_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. */
920e54ef 88#define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
89 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
a80ae91c 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},
920e54ef 93
94#define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
95 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
a80ae91c 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},
4ee9c684 99
ff4425cf 100#define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
a80ae91c 101 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
102 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
ff4425cf 103 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
104 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
105
c6599767 106#define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
a80ae91c 107 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
108 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
c6599767 109 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
a80ae91c 110 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
111
4ee9c684 112static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
113{
a80ae91c 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. */
4ee9c684 117#include "mathbuiltins.def"
118
ff4425cf 119 /* Functions in libgfortran. */
120 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
121
4ee9c684 122 /* End the list. */
ff4425cf 123 LIB_FUNCTION (NONE, NULL, false)
124
4ee9c684 125};
a80ae91c 126#undef OTHER_BUILTIN
ff4425cf 127#undef LIB_FUNCTION
4ee9c684 128#undef DEFINE_MATH_BUILTIN
158e0e64 129#undef DEFINE_MATH_BUILTIN_C
4ee9c684 130
4ee9c684 131
8a1417cb 132enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
4ee9c684 133
a80ae91c 134
135/* Find the correct variant of a given builtin from its argument. */
136static tree
137builtin_decl_for_precision (enum built_in_function base_built_in,
138 int precision)
139{
b9a16870 140 enum built_in_function i = END_BUILTINS;
a80ae91c 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;
c6599767 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 }
a80ae91c 158
b9a16870 159 return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
a80ae91c 160}
161
162
808656b4 163tree
164gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
165 int kind)
a80ae91c 166{
167 int i = gfc_validate_kind (BT_REAL, kind, false);
c6599767 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. */
411ee1e5 173 gfc_intrinsic_map_t *m;
c6599767 174 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
175 ;
176
177 return m->real16_decl;
178 }
179
a80ae91c 180 return builtin_decl_for_precision (double_built_in,
181 gfc_real_kinds[i].mode_precision);
182}
183
184
5ddb0172 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. */
4ee9c684 189
5ddb0172 190static void
191gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
192 tree *argarray, int nargs)
4ee9c684 193{
194 gfc_actual_arglist *actual;
bd24f178 195 gfc_expr *e;
196 gfc_intrinsic_arg *formal;
4ee9c684 197 gfc_se argse;
5ddb0172 198 int curr_arg;
4ee9c684 199
bd24f178 200 formal = expr->value.function.isym->formal;
5ddb0172 201 actual = expr->value.function.actual;
bd24f178 202
5ddb0172 203 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
204 actual = actual->next,
205 formal = formal ? formal->next : NULL)
4ee9c684 206 {
5ddb0172 207 gcc_assert (actual);
bd24f178 208 e = actual->expr;
9ca15c9b 209 /* Skip omitted optional arguments. */
bd24f178 210 if (!e)
5ddb0172 211 {
212 --curr_arg;
213 continue;
214 }
4ee9c684 215
216 /* Evaluate the parameter. This will substitute scalarized
b14e2757 217 references automatically. */
4ee9c684 218 gfc_init_se (&argse, se);
219
bd24f178 220 if (e->ts.type == BT_CHARACTER)
4ee9c684 221 {
bd24f178 222 gfc_conv_expr (&argse, e);
4ee9c684 223 gfc_conv_string_parameter (&argse);
5ddb0172 224 argarray[curr_arg++] = argse.string_length;
225 gcc_assert (curr_arg < nargs);
4ee9c684 226 }
227 else
bd24f178 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. */
24146844 232 if (e->expr_type == EXPR_VARIABLE
bd24f178 233 && e->symtree->n.sym->attr.optional
234 && formal
235 && formal->optional)
2abe085f 236 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
4ee9c684 237
238 gfc_add_block_to_block (&se->pre, &argse.pre);
239 gfc_add_block_to_block (&se->post, &argse.post);
5ddb0172 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
247static unsigned int
248gfc_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++;
8889e071 262 }
5ddb0172 263
264 return n;
4ee9c684 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
271static void
272gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
273{
274 tree type;
5ddb0172 275 tree *args;
276 int nargs;
4ee9c684 277
5ddb0172 278 nargs = gfc_intrinsic_argument_list_length (expr);
86b32f71 279 args = XALLOCAVEC (tree, nargs);
5ddb0172 280
411ee1e5 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
5ddb0172 283 and will trigger an ICE if it's not the case. */
4ee9c684 284 type = gfc_typenode_for_spec (&expr->ts);
22d678e8 285 gcc_assert (expr->value.function.actual->expr);
5ddb0172 286 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
4ee9c684 287
b44437b9 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);
389dd41b 310 tmp = build_call_expr_loc (input_location,
311 fndecl, 3, addr, args[0], args[1]);
b44437b9 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
4ee9c684 324 /* Conversion from complex to non-complex involves taking the real
325 component of the value. */
5ddb0172 326 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
4ee9c684 327 && expr->ts.type != BT_COMPLEX)
328 {
329 tree artype;
330
5ddb0172 331 artype = TREE_TYPE (TREE_TYPE (args[0]));
6f5c9335 332 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
333 args[0]);
4ee9c684 334 }
335
5ddb0172 336 se->expr = convert (type, args[0]);
4ee9c684 337}
338
e41f2c1a 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
4ee9c684 342 Similarly for CEILING. */
343
344static tree
345build_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);
6f5c9335 359 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
360 boolean_type_node, tmp, arg);
4ee9c684 361
6f5c9335 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);
4ee9c684 365 return tmp;
366}
367
368
ef080b63 369/* Round to nearest integer, away from zero. */
4ee9c684 370
371static tree
ef080b63 372build_round_expr (tree arg, tree restype)
4ee9c684 373{
4ee9c684 374 tree argtype;
ef080b63 375 tree fn;
ef080b63 376 int argprec, resprec;
4ee9c684 377
378 argtype = TREE_TYPE (arg);
ef080b63 379 argprec = TYPE_PRECISION (argtype);
380 resprec = TYPE_PRECISION (restype);
4ee9c684 381
f5fdea80 382 /* Depending on the type of the result, choose the int intrinsic
fb1fb9d3 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)
f5fdea80 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);
ef080b63 391 else if (resprec <= LONG_LONG_TYPE_SIZE)
a80ae91c 392 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
ef080b63 393 else
f5fdea80 394 gcc_unreachable ();
ef080b63 395
389dd41b 396 return fold_convert (restype, build_call_expr_loc (input_location,
397 fn, 1, arg));
4ee9c684 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
405static tree
4bbc8816 406build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
8a1417cb 407 enum rounding_mode op)
4ee9c684 408{
409 switch (op)
410 {
8a1417cb 411 case RND_FLOOR:
4ee9c684 412 return build_fixbound_expr (pblock, arg, type, 0);
413 break;
414
8a1417cb 415 case RND_CEIL:
4ee9c684 416 return build_fixbound_expr (pblock, arg, type, 1);
417 break;
418
8a1417cb 419 case RND_ROUND:
ef080b63 420 return build_round_expr (arg, type);
421 break;
4ee9c684 422
ef080b63 423 case RND_TRUNC:
6f5c9335 424 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
ef080b63 425 break;
426
427 default:
428 gcc_unreachable ();
4ee9c684 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.
4bbc8816 435 Values larger than those that can be represented by this kind are
8e2caf1e 436 unchanged, as they will not be accurate enough to represent the
4bbc8816 437 rounding.
4ee9c684 438 huge = HUGE (KIND (a))
439 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
440 */
441
442static void
8a1417cb 443gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
4ee9c684 444{
445 tree type;
446 tree itype;
ea8ac4ce 447 tree arg[2];
4ee9c684 448 tree tmp;
449 tree cond;
a80ae91c 450 tree decl;
4b1085db 451 mpfr_t huge;
ea8ac4ce 452 int n, nargs;
4ee9c684 453 int kind;
454
455 kind = expr->ts.kind;
15da0ca7 456 nargs = gfc_intrinsic_argument_list_length (expr);
4ee9c684 457
a80ae91c 458 decl = NULL_TREE;
4ee9c684 459 /* We have builtin functions for some cases. */
460 switch (op)
461 {
8a1417cb 462 case RND_ROUND:
808656b4 463 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
4ee9c684 464 break;
465
8a1417cb 466 case RND_TRUNC:
808656b4 467 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
4bbc8816 468 break;
469
470 default:
471 gcc_unreachable ();
4ee9c684 472 }
473
474 /* Evaluate the argument. */
22d678e8 475 gcc_assert (expr->value.function.actual->expr);
ea8ac4ce 476 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
4ee9c684 477
478 /* Use a builtin function if one exists. */
a80ae91c 479 if (decl != NULL_TREE)
4ee9c684 480 {
a80ae91c 481 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
4ee9c684 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);
ea8ac4ce 488 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
4ee9c684 489
490 /* Test if the value is too large to handle sensibly. */
4b1085db 491 gfc_set_model_kind (kind);
492 mpfr_init (huge);
f2d4ef3b 493 n = gfc_validate_kind (BT_INTEGER, kind, false);
4b1085db 494 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
2b6bc4f2 495 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
6f5c9335 496 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, arg[0],
497 tmp);
4ee9c684 498
4b1085db 499 mpfr_neg (huge, huge, GFC_RND_MODE);
2b6bc4f2 500 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
6f5c9335 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);
4ee9c684 505 itype = gfc_get_int_type (kind);
506
ea8ac4ce 507 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
4ee9c684 508 tmp = convert (type, tmp);
6f5c9335 509 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
510 arg[0]);
4b1085db 511 mpfr_clear (huge);
4ee9c684 512}
513
514
515/* Convert to an integer using the specified rounding mode. */
516
517static void
8a1417cb 518gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
4ee9c684 519{
520 tree type;
99614c0d 521 tree *args;
522 int nargs;
4ee9c684 523
99614c0d 524 nargs = gfc_intrinsic_argument_list_length (expr);
86b32f71 525 args = XALLOCAVEC (tree, nargs);
99614c0d 526
411ee1e5 527 /* Evaluate the argument, we process all arguments even though we only
99614c0d 528 use the first one for code generation purposes. */
4ee9c684 529 type = gfc_typenode_for_spec (&expr->ts);
22d678e8 530 gcc_assert (expr->value.function.actual->expr);
99614c0d 531 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
4ee9c684 532
99614c0d 533 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
4ee9c684 534 {
535 /* Conversion to a different integer kind. */
99614c0d 536 se->expr = convert (type, args[0]);
4ee9c684 537 }
538 else
539 {
540 /* Conversion from complex to non-complex involves taking the real
541 component of the value. */
99614c0d 542 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
4ee9c684 543 && expr->ts.type != BT_COMPLEX)
544 {
545 tree artype;
546
99614c0d 547 artype = TREE_TYPE (TREE_TYPE (args[0]));
6f5c9335 548 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
549 args[0]);
4ee9c684 550 }
551
99614c0d 552 se->expr = build_fix_expr (&se->pre, args[0], type, op);
4ee9c684 553 }
554}
555
556
557/* Get the imaginary component of a value. */
558
559static void
560gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
561{
562 tree arg;
563
5ddb0172 564 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6f5c9335 565 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
566 TREE_TYPE (TREE_TYPE (arg)), arg);
4ee9c684 567}
568
569
570/* Get the complex conjugate of a value. */
571
572static void
573gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
574{
575 tree arg;
576
5ddb0172 577 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6f5c9335 578 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
4ee9c684 579}
580
581
c6599767 582
583static tree
584define_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
4ee9c684 604/* Initialize function decls for library functions. The external functions
605 are created as required. Builtin functions are added here. */
606
607void
608gfc_build_intrinsic_lib_fndecls (void)
609{
610 gfc_intrinsic_map_t *m;
e8428f9c 611 tree quad_decls[END_BUILTINS + 1];
c6599767 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
cfcdd3f1 619 tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
f5fdea80 620 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
c6599767 621
e8428f9c 622 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
c6599767 623
cfcdd3f1 624 type = float128_type_node;
625 complex_type = complex_float128_type_node;
c6599767 626 /* type (*) (type) */
cfcdd3f1 627 func_1 = build_function_type_list (type, type, NULL_TREE);
f5fdea80 628 /* int (*) (type) */
629 func_iround = build_function_type_list (integer_type_node,
630 type, NULL_TREE);
c6599767 631 /* long (*) (type) */
cfcdd3f1 632 func_lround = build_function_type_list (long_integer_type_node,
633 type, NULL_TREE);
c6599767 634 /* long long (*) (type) */
cfcdd3f1 635 func_llround = build_function_type_list (long_long_integer_type_node,
636 type, NULL_TREE);
c6599767 637 /* type (*) (type, type) */
cfcdd3f1 638 func_2 = build_function_type_list (type, type, type, NULL_TREE);
c6599767 639 /* type (*) (type, &int) */
cfcdd3f1 640 func_frexp
641 = build_function_type_list (type,
642 type,
643 build_pointer_type (integer_type_node),
644 NULL_TREE);
c6599767 645 /* type (*) (type, int) */
cfcdd3f1 646 func_scalbn = build_function_type_list (type,
647 type, integer_type_node, NULL_TREE);
c6599767 648 /* type (*) (complex type) */
cfcdd3f1 649 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
808656b4 650 /* complex type (*) (complex type, complex type) */
cfcdd3f1 651 func_cpow
652 = build_function_type_list (complex_type,
653 complex_type, complex_type, NULL_TREE);
c6599767 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
6de19d80 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
c6599767 678 }
4ee9c684 679
680 /* Add GCC builtin functions. */
a80ae91c 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)
b9a16870 685 m->real4_decl = builtin_decl_explicit (m->float_built_in);
a80ae91c 686 if (m->complex_float_built_in != END_BUILTINS)
b9a16870 687 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
a80ae91c 688 if (m->double_built_in != END_BUILTINS)
b9a16870 689 m->real8_decl = builtin_decl_explicit (m->double_built_in);
a80ae91c 690 if (m->complex_double_built_in != END_BUILTINS)
b9a16870 691 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
a80ae91c 692
693 /* If real(kind=10) exists, it is always long double. */
694 if (m->long_double_built_in != END_BUILTINS)
b9a16870 695 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
a80ae91c 696 if (m->complex_long_double_built_in != END_BUILTINS)
b9a16870 697 m->complex10_decl
698 = builtin_decl_explicit (m->complex_long_double_built_in);
a80ae91c 699
c6599767 700 if (!gfc_real16_is_float128)
701 {
702 if (m->long_double_built_in != END_BUILTINS)
b9a16870 703 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
c6599767 704 if (m->complex_long_double_built_in != END_BUILTINS)
b9a16870 705 m->complex16_decl
706 = builtin_decl_explicit (m->complex_long_double_built_in);
c6599767 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];
c6599767 719 }
4ee9c684 720 }
721}
722
723
724/* Create a fndecl for a simple intrinsic library function. */
725
726static tree
727gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
728{
729 tree type;
f1f41a6c 730 vec<tree, va_gc> *argtypes;
4ee9c684 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;
920e54ef 748 case 10:
749 pdecl = &m->real10_decl;
750 break;
751 case 16:
752 pdecl = &m->real16_decl;
753 break;
4ee9c684 754 default:
22d678e8 755 gcc_unreachable ();
4ee9c684 756 }
757 }
758 else if (ts->type == BT_COMPLEX)
759 {
22d678e8 760 gcc_assert (m->complex_available);
4ee9c684 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;
920e54ef 770 case 10:
771 pdecl = &m->complex10_decl;
772 break;
773 case 16:
774 pdecl = &m->complex16_decl;
775 break;
4ee9c684 776 default:
22d678e8 777 gcc_unreachable ();
4ee9c684 778 }
779 }
780 else
22d678e8 781 gcc_unreachable ();
4ee9c684 782
783 if (*pdecl)
784 return *pdecl;
785
786 if (m->libm_name)
787 {
a80ae91c 788 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
789 if (gfc_real_kinds[n].c_float)
112f3d57 790 snprintf (name, sizeof (name), "%s%s%s",
a80ae91c 791 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
792 else if (gfc_real_kinds[n].c_double)
112f3d57 793 snprintf (name, sizeof (name), "%s%s",
a80ae91c 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");
c6599767 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");
112f3d57 801 else
a80ae91c 802 gcc_unreachable ();
4ee9c684 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
5edc3af9 811 argtypes = NULL;
4ee9c684 812 for (actual = expr->value.function.actual; actual; actual = actual->next)
813 {
814 type = gfc_typenode_for_spec (&actual->expr->ts);
f1f41a6c 815 vec_safe_push (argtypes, type);
4ee9c684 816 }
5edc3af9 817 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
e60a6f7b 818 fndecl = build_decl (input_location,
819 FUNCTION_DECL, get_identifier (name), type);
4ee9c684 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
b2c4af5e 828 rest_of_decl_compilation (fndecl, 1, 0);
4ee9c684 829
830 (*pdecl) = fndecl;
831 return fndecl;
832}
833
834
835/* Convert an intrinsic function into an external or builtin call. */
836
837static void
838gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
839{
840 gfc_intrinsic_map_t *m;
4ee9c684 841 tree fndecl;
5ddb0172 842 tree rettype;
843 tree *args;
844 unsigned int num_args;
55cb4417 845 gfc_isym_id id;
4ee9c684 846
55cb4417 847 id = expr->value.function.isym->id;
4ee9c684 848 /* Find the entry for this function. */
a80ae91c 849 for (m = gfc_intrinsic_map;
850 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
4ee9c684 851 {
852 if (id == m->id)
853 break;
854 }
855
856 if (m->id == GFC_ISYM_NONE)
857 {
382ad5c3 858 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
859 expr->value.function.name, id);
4ee9c684 860 }
861
862 /* Get the decl and generate the call. */
5ddb0172 863 num_args = gfc_intrinsic_argument_list_length (expr);
86b32f71 864 args = XALLOCAVEC (tree, num_args);
5ddb0172 865
866 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4ee9c684 867 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
5ddb0172 868 rettype = TREE_TYPE (TREE_TYPE (fndecl));
869
0e49e441 870 fndecl = build_addr (fndecl);
389dd41b 871 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
4ee9c684 872}
873
f24d382c 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
9c5786bd 879void
880gfc_trans_same_strlen_check (const char* intr_name, locus* where,
881 tree a, tree b, stmtblock_t* target)
f24d382c 882{
883 tree cond;
884 tree name;
885
886 /* If bounds-checking is disabled, do nothing. */
ad8ed98e 887 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
f24d382c 888 return;
889
890 /* Compare the two string lengths. */
6f5c9335 891 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, a, b);
f24d382c 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,
9c5786bd 897 "Unequal character lengths (%ld/%ld) in %s",
f24d382c 898 fold_convert (long_integer_type_node, a),
899 fold_convert (long_integer_type_node, b), name);
900}
901
902
1d8a0522 903/* The EXPONENT(X) intrinsic function is translated into
34e106da 904 int ret;
1d8a0522 905 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
906 so that if X is a NaN or infinity, the result is HUGE(0).
34e106da 907 */
4ee9c684 908
909static void
9dd6c589 910gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
4ee9c684 911{
1d8a0522 912 tree arg, type, res, tmp, frexp, cond, huge;
913 int i;
4ee9c684 914
808656b4 915 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
a80ae91c 916 expr->value.function.actual->expr->ts.kind);
4ee9c684 917
34e106da 918 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
1d8a0522 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);
34e106da 926
927 res = gfc_create_var (integer_type_node, NULL);
a80ae91c 928 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
929 gfc_build_addr_expr (NULL_TREE, res));
1d8a0522 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);
34e106da 934
9dd6c589 935 type = gfc_typenode_for_spec (&expr->ts);
1d8a0522 936 se->expr = fold_convert (type, se->expr);
4ee9c684 937}
938
09800dba 939
5f4a118e 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
956static void
957conv_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
1016static tree
1017conv_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
5f4a118e 1097/* Get data from a remote coarray. */
1098
1099static void
9f1c76f9 1100gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
1101 tree may_require_tmp)
5f4a118e 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
4fe73152 1108 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
5f4a118e 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
3b336bb1 1124 vec = null_pointer_node;
1125
5f4a118e 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)
00bc0309 1138 res_var = gfc_conv_string_tmp (se, build_pointer_type (type),
1139 argse.string_length);
5f4a118e 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);
102abea2 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),
3b336bb1 1168 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1169 : array_expr->rank,
1170 type));
5f4a118e 1171 if (has_vector)
1172 {
3b336bb1 1173 vec = conv_caf_vector_subscript (&argse.pre, argse.expr, &ar2);
5f4a118e 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
5f4a118e 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);
384d1ed7 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);
5f4a118e 1209
9f1c76f9 1210 /* No overlap possible as we have generated a temporary. */
1211 if (lhs == NULL_TREE)
1212 may_require_tmp = boolean_false_node;
1213
5118f067 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
9f1c76f9 1222 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 9,
5f4a118e 1223 token, offset, image_index, argse.expr, vec,
9f1c76f9 1224 dst_var, kind, lhs_kind, may_require_tmp);
5f4a118e 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. */
411ee1e5 1237
5f4a118e 1238static tree
1239conv_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;
9f1c76f9 1244 tree may_require_tmp;
a10fb10a 1245 tree lhs_type = NULL_TREE;
5f4a118e 1246 tree vec = null_pointer_node, rhs_vec = null_pointer_node;
1247
4fe73152 1248 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
5f4a118e 1249
1250 lhs_expr = code->ext.actual->expr;
1251 rhs_expr = code->ext.actual->next->expr;
9f1c76f9 1252 may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, false) == 0
1253 ? boolean_false_node : boolean_true_node;
5f4a118e 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);
a10fb10a 1263 lhs_type = TREE_TYPE (lhs_se.expr);
5f4a118e 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);
102abea2 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),
3b336bb1 1290 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1291 : lhs_expr->rank,
1292 lhs_type));
5f4a118e 1293 if (has_vector)
1294 {
3b336bb1 1295 vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
5f4a118e 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);
9f1c76f9 1309 gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
1310 may_require_tmp);
5f4a118e 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);
384d1ed7 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);
5f4a118e 1324
1325 /* RHS. */
1326 gfc_init_se (&rhs_se, NULL);
a10fb10a 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;
5f4a118e 1330 if (rhs_expr->rank == 0)
1331 {
1332 symbol_attribute attr;
1333 gfc_clear_attr (&attr);
1334 gfc_conv_expr (&rhs_se, rhs_expr);
a10fb10a 1335 if (!gfc_is_coindexed (rhs_expr) && rhs_expr->ts.type != BT_CHARACTER)
1336 rhs_se.expr = fold_convert (lhs_type , rhs_se.expr);
5f4a118e 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;
102abea2 1346 tree tmp2;
5f4a118e 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);
102abea2 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),
3b336bb1 1364 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
1365 : rhs_expr->rank,
1366 tmp2));
5f4a118e 1367 if (has_vector)
1368 {
3b336bb1 1369 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
5f4a118e 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))
9f1c76f9 1379 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 9, token,
5f4a118e 1380 offset, image_index, lhs_se.expr, vec,
9f1c76f9 1381 rhs_se.expr, lhs_kind, rhs_kind, may_require_tmp);
5f4a118e 1382 else
1383 {
1384 tree rhs_token, rhs_offset, rhs_image_index;
1385
5118f067 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
5f4a118e 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);
384d1ed7 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);
9f1c76f9 1400 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget, 13,
5f4a118e 1401 token, offset, image_index, lhs_se.expr, vec,
1402 rhs_token, rhs_offset, rhs_image_index,
9f1c76f9 1403 rhs_se.expr, rhs_vec, lhs_kind, rhs_kind,
1404 may_require_tmp);
5f4a118e 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);
5118f067 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
5f4a118e 1418 return gfc_finish_block (&block);
1419}
1420
1421
70b5944a 1422static void
2e34dcd8 1423trans_this_image (gfc_se * se, gfc_expr *expr)
70b5944a 1424{
2e34dcd8 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;
2e34dcd8 1429 int rank, corank;
3427a543 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;
2e34dcd8 1435
1436 /* The case -fcoarray=single is handled elsewhere. */
4fe73152 1437 gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
2e34dcd8 1438
2e34dcd8 1439 /* Argument-free version: THIS_IMAGE(). */
3427a543 1440 if (distance || expr->value.function.actual->expr == NULL)
2e34dcd8 1441 {
3427a543 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;
d44f2f7c 1452 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
3427a543 1453 tmp);
9a457ae7 1454 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
d44f2f7c 1455 tmp);
2e34dcd8 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);
636321de 1467 argse.want_coarray = 1;
5d34a30f 1468 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2e34dcd8 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);
bfa43780 1479 gcc_assert (se->ss->info->expr == expr);
2e34dcd8 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,
69777e5d 1484 build_int_cst (TREE_TYPE (dim_arg), 1));
2e34dcd8 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 {
ab2c1de8 1499 if (wi::ltu_p (dim_arg, 1)
3a54beaf 1500 || wi::gtu_p (dim_arg, GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
0d2b3c9c 1501 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2e34dcd8 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
9a457ae7 1524 m = this_image() - 1
bfc5d51b 1525 if (corank == 1)
1526 {
1527 sub(1) = m + lcobound(corank)
1528 return;
1529 }
2e34dcd8 1530 i = rank
69777e5d 1531 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2e34dcd8 1532 for (;;)
1533 {
1534 extent = gfc_extent(i)
1535 ml = m
1536 m = m/extent
411ee1e5 1537 if (i >= min_var)
2e34dcd8 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
bfc5d51b 1546 /* this_image () - 1. */
d44f2f7c 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));
bfc5d51b 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
411ee1e5 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);
2e34dcd8 1568
1569 /* m = this_image () - 1. */
2e34dcd8 1570 gfc_add_modify (&se->pre, m, tmp);
1571
69777e5d 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));
2e34dcd8 1576 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
1577 build_int_cst (integer_type_node, rank + corank - 2),
69777e5d 1578 tmp);
2e34dcd8 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. */
411ee1e5 1601 gfc_add_modify (&loop, m,
2e34dcd8 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,
69777e5d 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)));
2e34dcd8 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));
70b5944a 1648}
1649
09800dba 1650
1651static void
1652trans_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;
09800dba 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);
636321de 1665 argse.want_coarray = 1;
5d34a30f 1666 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
09800dba 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);
5d34a30f 1673 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
09800dba 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
c83059be 1705 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
09800dba 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
4fe73152 1749 if (flag_coarray == GFC_FCOARRAY_SINGLE)
09800dba 1750 num_images = build_int_cst (type, 1);
1751 else
1752 {
d44f2f7c 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);
09800dba 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
70b5944a 1772static void
3427a543 1773trans_num_images (gfc_se * se, gfc_expr *expr)
70b5944a 1774{
3427a543 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);
d44f2f7c 1802 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
70b5944a 1803}
1804
076094b7 1805
90342c73 1806static void
1807gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
1808{
1809 gfc_se argse;
90342c73 1810
90342c73 1811 gfc_init_se (&argse, NULL);
1812 argse.data_not_needed = 1;
f00f6dd6 1813 argse.descriptor_only = 1;
90342c73 1814
5d34a30f 1815 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
90342c73 1816 gfc_add_block_to_block (&se->pre, &argse.pre);
1817 gfc_add_block_to_block (&se->post, &argse.post);
f00f6dd6 1818
edc4866f 1819 se->expr = gfc_conv_descriptor_rank (argse.expr);
90342c73 1820}
1821
1822
4ee9c684 1823/* Evaluate a single upper or lower bound. */
231e961a 1824/* TODO: bound intrinsic generates way too much unnecessary code. */
4ee9c684 1825
1826static void
1827gfc_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;
66a56860 1835 tree cond, cond1, cond3, cond4, size;
c6a41748 1836 tree ubound;
1837 tree lbound;
4ee9c684 1838 gfc_se argse;
c6a41748 1839 gfc_array_spec * as;
9b58b4c7 1840 bool assumed_rank_lb_one;
4ee9c684 1841
4ee9c684 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. */
22d678e8 1848 gcc_assert (!arg2->expr);
1849 gcc_assert (se->loop->dimen == 1);
bfa43780 1850 gcc_assert (se->ss->info->expr == expr);
4ee9c684 1851 gfc_advance_se_ss_chain (se);
1852 bound = se->loop->loopvar[0];
6f5c9335 1853 bound = fold_build2_loc (input_location, MINUS_EXPR,
1854 gfc_array_index_type, bound,
1855 se->loop->from[0]);
4ee9c684 1856 }
1857 else
1858 {
1859 /* use the passed argument. */
076094b7 1860 gcc_assert (arg2->expr);
4ee9c684 1861 gfc_init_se (&argse, NULL);
076094b7 1862 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
4ee9c684 1863 gfc_add_block_to_block (&se->pre, &argse.pre);
1864 bound = argse.expr;
1865 /* Convert from one based to zero based. */
6f5c9335 1866 bound = fold_build2_loc (input_location, MINUS_EXPR,
1867 gfc_array_index_type, bound,
1868 gfc_index_one_node);
4ee9c684 1869 }
1870
1871 /* TODO: don't re-evaluate the descriptor on each iteration. */
1872 /* Get a descriptor for the first parameter. */
ec9200dc 1873 gfc_init_se (&argse, NULL);
5d34a30f 1874 gfc_conv_expr_descriptor (&argse, arg->expr);
4ee9c684 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
9b58b4c7 1880 as = gfc_get_full_arrayspec_from_expr (arg->expr);
1881
4ee9c684 1882 if (INTEGER_CST_P (bound))
1883 {
e913b5cd 1884 if (((!as || as->type != AS_ASSUMED_RANK)
ab2c1de8 1885 && wi::geu_p (bound, GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
1886 || wi::gtu_p (bound, GFC_MAX_DIMENSIONS))
0d2b3c9c 1887 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
09d71cee 1888 "dimension index", upper ? "UBOUND" : "LBOUND",
1889 &expr->where);
4ee9c684 1890 }
9b58b4c7 1891
1892 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
4ee9c684 1893 {
ad8ed98e 1894 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4ee9c684 1895 {
1896 bound = gfc_evaluate_now (bound, &se->pre);
6f5c9335 1897 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1898 bound, build_int_cst (TREE_TYPE (bound), 0));
9b58b4c7 1899 if (as && as->type == AS_ASSUMED_RANK)
edc4866f 1900 tmp = gfc_conv_descriptor_rank (desc);
9b58b4c7 1901 else
1902 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
6f5c9335 1903 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
9b58b4c7 1904 bound, fold_convert(TREE_TYPE (bound), tmp));
6f5c9335 1905 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1906 boolean_type_node, cond, tmp);
da6ffc6d 1907 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1908 gfc_msg_fault);
4ee9c684 1909 }
1910 }
1911
9b58b4c7 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
6b1a9af3 1922 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
1923 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
411ee1e5 1924
c6a41748 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
9b58b4c7 1946 if (!upper && assumed_rank_lb_one)
1947 se->expr = gfc_index_one_node;
1948 else if (as)
c6a41748 1949 {
6b1a9af3 1950 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
09d71cee 1951
6f5c9335 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);
c6a41748 1960
1961 if (upper)
1962 {
0163eeb8 1963 tree cond5;
6f5c9335 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
9b58b4c7 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
6f5c9335 1984 se->expr = fold_build3_loc (input_location, COND_EXPR,
1985 gfc_array_index_type, cond,
9b58b4c7 1986 tmp, gfc_index_zero_node);
c6a41748 1987 }
1988 else
1989 {
1990 if (as->type == AS_ASSUMED_SIZE)
6f5c9335 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));
c6a41748 1994 else
1995 cond = boolean_false_node;
1996
6f5c9335 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);
c6a41748 2001
6f5c9335 2002 se->expr = fold_build3_loc (input_location, COND_EXPR,
2003 gfc_array_index_type, cond,
2004 lbound, gfc_index_one_node);
c6a41748 2005 }
2006 }
2007 else
2008 {
2009 if (upper)
2010 {
6f5c9335 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,
c6a41748 2015 gfc_index_one_node);
6f5c9335 2016 se->expr = fold_build2_loc (input_location, MAX_EXPR,
2017 gfc_array_index_type, se->expr,
2018 gfc_index_zero_node);
c6a41748 2019 }
2020 else
2021 se->expr = gfc_index_one_node;
2022 }
4ee9c684 2023
2024 type = gfc_typenode_for_spec (&expr->ts);
2025 se->expr = convert (type, se->expr);
2026}
2027
2028
076094b7 2029static void
2030conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
2031{
2032 gfc_actual_arglist *arg;
2033 gfc_actual_arglist *arg2;
2034 gfc_se argse;
076094b7 2035 tree bound, resbound, resbound2, desc, cond, tmp;
2036 tree type;
076094b7 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
076094b7 2049 gfc_init_se (&argse, NULL);
636321de 2050 argse.want_coarray = 1;
076094b7 2051
5d34a30f 2052 gfc_conv_expr_descriptor (&argse, arg->expr);
076094b7 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 {
076094b7 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);
bfa43780 2063 gcc_assert (se->ss->info->expr == expr);
076094b7 2064
076094b7 2065 bound = se->loop->loopvar[0];
bee1af95 2066 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2e34dcd8 2067 bound, gfc_rank_cst[arg->expr->rank]);
076094b7 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 {
ab2c1de8 2081 if (wi::ltu_p (bound, 1)
2082 || wi::gtu_p (bound, GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
0d2b3c9c 2083 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
076094b7 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);
bee1af95 2090 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2091 bound, build_int_cst (TREE_TYPE (bound), 1));
076094b7 2092 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
bee1af95 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);
076094b7 2097 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2098 gfc_msg_fault);
2099 }
2100
2101
df084314 2102 /* Subtract 1 to get to zero based and add dimensions. */
076094b7 2103 switch (arg->expr->rank)
2104 {
2105 case 0:
bee1af95 2106 bound = fold_build2_loc (input_location, MINUS_EXPR,
2107 gfc_array_index_type, bound,
2108 gfc_index_one_node);
076094b7 2109 case 1:
2110 break;
2111 default:
bee1af95 2112 bound = fold_build2_loc (input_location, PLUS_EXPR,
2113 gfc_array_index_type, bound,
2114 gfc_rank_cst[arg->expr->rank - 1]);
076094b7 2115 }
2116 }
2117
2118 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
2119
bee1af95 2120 /* Handle UCOBOUND with special handling of the last codimension. */
076094b7 2121 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
2122 {
bee1af95 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(),
09800dba 2128 where size is the product of the extent of all but the last
bee1af95 2129 codimension. */
2130
4fe73152 2131 if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
bee1af95 2132 {
2133 tree cosize;
2134
bee1af95 2135 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
d44f2f7c 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));
bee1af95 2139 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2140 gfc_array_index_type,
d44f2f7c 2141 fold_convert (gfc_array_index_type, tmp),
bee1af95 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 }
4fe73152 2149 else if (flag_coarray != GFC_FCOARRAY_SINGLE)
bee1af95 2150 {
2151 /* ubound = lbound + num_images() - 1. */
d44f2f7c 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));
bee1af95 2155 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2156 gfc_array_index_type,
d44f2f7c 2157 fold_convert (gfc_array_index_type, tmp),
bee1af95 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;
076094b7 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
f9606ba3 2186static void
2187conv_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
4ee9c684 2215static void
2216gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
2217{
a80ae91c 2218 tree arg, cabs;
4ee9c684 2219
5ddb0172 2220 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4ee9c684 2221
2222 switch (expr->value.function.actual->expr->ts.type)
2223 {
2224 case BT_INTEGER:
2225 case BT_REAL:
6f5c9335 2226 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
2227 arg);
4ee9c684 2228 break;
2229
2230 case BT_COMPLEX:
808656b4 2231 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
a80ae91c 2232 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
4ee9c684 2233 break;
2234
2235 default:
22d678e8 2236 gcc_unreachable ();
4ee9c684 2237 }
2238}
2239
2240
2241/* Create a complex value from one or two real components. */
2242
2243static void
2244gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
2245{
4ee9c684 2246 tree real;
2247 tree imag;
2248 tree type;
5ddb0172 2249 tree *args;
2250 unsigned int num_args;
2251
2252 num_args = gfc_intrinsic_argument_list_length (expr);
86b32f71 2253 args = XALLOCAVEC (tree, num_args);
4ee9c684 2254
2255 type = gfc_typenode_for_spec (&expr->ts);
5ddb0172 2256 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2257 real = convert (TREE_TYPE (type), args[0]);
4ee9c684 2258 if (both)
5ddb0172 2259 imag = convert (TREE_TYPE (type), args[1]);
2260 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
4ee9c684 2261 {
6f5c9335 2262 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
2263 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
4ee9c684 2264 imag = convert (TREE_TYPE (type), imag);
2265 }
2266 else
2267 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
2268
6f5c9335 2269 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
4ee9c684 2270}
2271
fa0323b8 2272
8241ce4f 2273/* Remainder function MOD(A, P) = A - INT(A / P) * P
411ee1e5 2274 MODULO(A, P) = A - FLOOR (A / P) * P
fa0323b8 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. */
4ee9c684 2280
2281static void
2282gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
2283{
4ee9c684 2284 tree type;
4ee9c684 2285 tree tmp;
4ee9c684 2286 tree test;
2287 tree test2;
a80ae91c 2288 tree fmod;
fa0323b8 2289 tree zero;
5ddb0172 2290 tree args[2];
4ee9c684 2291
5ddb0172 2292 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4ee9c684 2293
2294 switch (expr->ts.type)
2295 {
2296 case BT_INTEGER:
2297 /* Integer case is easy, we've got a builtin op. */
5ddb0172 2298 type = TREE_TYPE (args[0]);
54ad1b4d 2299
8241ce4f 2300 if (modulo)
6f5c9335 2301 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
2302 args[0], args[1]);
8241ce4f 2303 else
6f5c9335 2304 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
2305 args[0], args[1]);
4ee9c684 2306 break;
2307
2308 case BT_REAL:
a80ae91c 2309 fmod = NULL_TREE;
54ad1b4d 2310 /* Check if we have a builtin fmod. */
808656b4 2311 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
54ad1b4d 2312
fa0323b8 2313 /* The builtin should always be available. */
2314 gcc_assert (fmod != NULL_TREE);
2315
0e49e441 2316 tmp = build_addr (fmod);
fa0323b8 2317 se->expr = build_call_array_loc (input_location,
a80ae91c 2318 TREE_TYPE (TREE_TYPE (fmod)),
5ddb0172 2319 tmp, 2, args);
fa0323b8 2320 if (modulo == 0)
2321 return;
54ad1b4d 2322
5ddb0172 2323 type = TREE_TYPE (args[0]);
54ad1b4d 2324
5ddb0172 2325 args[0] = gfc_evaluate_now (args[0], &se->pre);
2326 args[1] = gfc_evaluate_now (args[1], &se->pre);
4ee9c684 2327
54ad1b4d 2328 /* Definition:
fa0323b8 2329 modulo = arg - floor (arg/arg2) * arg2
2330
2331 In order to calculate the result accurately, we use the fmod
2332 function as follows.
411ee1e5 2333
fa0323b8 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
411ee1e5 2345 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
fa0323b8 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)
54ad1b4d 2353 {
6f5c9335 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);
54ad1b4d 2364 test = gfc_evaluate_now (test, &se->pre);
6f5c9335 2365 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
411ee1e5 2366 fold_build2_loc (input_location,
fa0323b8 2367 PLUS_EXPR,
411ee1e5 2368 type, tmp, args[1]),
fa0323b8 2369 tmp);
54ad1b4d 2370 }
fa0323b8 2371 else
1707eca1 2372 {
fa0323b8 2373 tree expr1, copysign, cscall;
411ee1e5 2374 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
fa0323b8 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,
411ee1e5 2383 fold_build2_loc (input_location,
fa0323b8 2384 PLUS_EXPR,
411ee1e5 2385 type, tmp, args[1]),
fa0323b8 2386 tmp);
2387 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
2388 tmp, zero);
411ee1e5 2389 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
fa0323b8 2390 args[1]);
2391 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
2392 expr1, cscall);
1707eca1 2393 }
fa0323b8 2394 return;
4ee9c684 2395
2396 default:
22d678e8 2397 gcc_unreachable ();
4ee9c684 2398 }
4ee9c684 2399}
2400
f004c7aa 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
2411static void
2412gfc_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
4ee9c684 2457/* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
2458
2459static void
2460gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
2461{
4ee9c684 2462 tree val;
2463 tree tmp;
2464 tree type;
2465 tree zero;
5ddb0172 2466 tree args[2];
4ee9c684 2467
5ddb0172 2468 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2469 type = TREE_TYPE (args[0]);
4ee9c684 2470
6f5c9335 2471 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
4ee9c684 2472 val = gfc_evaluate_now (val, &se->pre);
2473
2474 zero = gfc_build_const (type, integer_zero_node);
6f5c9335 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);
4ee9c684 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:
5687724f 2483 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
4ee9c684 2484 */
2485
2486static void
2487gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
2488{
2489 tree tmp;
4ee9c684 2490 tree type;
5ddb0172 2491 tree args[2];
4ee9c684 2492
5ddb0172 2493 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4ee9c684 2494 if (expr->ts.type == BT_REAL)
2495 {
af9e821d 2496 tree abs;
2497
808656b4 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);
af9e821d 2500
2501 /* We explicitly have to ignore the minus sign. We do so by using
2502 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
829d7a08 2503 if (!flag_sign_zero
af9e821d 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);
6f5c9335 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,
1516b2fb 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]));
af9e821d 2516 }
2517 else
a80ae91c 2518 se->expr = build_call_expr_loc (input_location, tmp, 2,
2519 args[0], args[1]);
4ee9c684 2520 return;
2521 }
2522
5687724f 2523 /* Having excluded floating point types, we know we are now dealing
2524 with signed integer types. */
5ddb0172 2525 type = TREE_TYPE (args[0]);
4ee9c684 2526
5ddb0172 2527 /* Args[0] is used multiple times below. */
2528 args[0] = gfc_evaluate_now (args[0], &se->pre);
5687724f 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. */
6f5c9335 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));
5687724f 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). */
6f5c9335 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);
4ee9c684 2542}
2543
2544
2545/* Test for the presence of an optional argument. */
2546
2547static void
2548gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
2549{
2550 gfc_expr *arg;
2551
2552 arg = expr->value.function.actual->expr;
22d678e8 2553 gcc_assert (arg->expr_type == EXPR_VARIABLE);
4ee9c684 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
2561static void
2562gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
2563{
4ee9c684 2564 tree type;
5ddb0172 2565 tree args[2];
4ee9c684 2566
5ddb0172 2567 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4ee9c684 2568
2569 /* Convert the args to double precision before multiplying. */
2570 type = gfc_typenode_for_spec (&expr->ts);
5ddb0172 2571 args[0] = convert (type, args[0]);
2572 args[1] = convert (type, args[1]);
6f5c9335 2573 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
2574 args[1]);
4ee9c684 2575}
2576
2577
2578/* Return a length one character string containing an ascii character. */
2579
2580static void
2581gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
2582{
6bd88715 2583 tree arg[2];
4ee9c684 2584 tree var;
2585 tree type;
6bd88715 2586 unsigned int num_args;
4ee9c684 2587
6bd88715 2588 num_args = gfc_intrinsic_argument_list_length (expr);
2589 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
4ee9c684 2590
b44437b9 2591 type = gfc_get_char_type (expr->ts.kind);
4ee9c684 2592 var = gfc_create_var (type, "char");
2593
6f5c9335 2594 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
75a70cf9 2595 gfc_add_modify (&se->pre, var, arg[0]);
4ee9c684 2596 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
1557756e 2597 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
4ee9c684 2598}
2599
2600
b902b078 2601static void
2602gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
2603{
2604 tree var;
2605 tree len;
2606 tree tmp;
b902b078 2607 tree cond;
5ddb0172 2608 tree fndecl;
2609 tree *args;
2610 unsigned int num_args;
2611
2612 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
86b32f71 2613 args = XALLOCAVEC (tree, num_args);
b902b078 2614
329f13ad 2615 var = gfc_create_var (pchar_type_node, "pstr");
4f16309a 2616 len = gfc_create_var (gfc_charlen_type_node, "len");
b902b078 2617
5ddb0172 2618 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
86f2ad37 2619 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2620 args[1] = gfc_build_addr_expr (NULL_TREE, len);
b902b078 2621
0e49e441 2622 fndecl = build_addr (gfor_fndecl_ctime);
389dd41b 2623 tmp = build_call_array_loc (input_location,
2624 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
5ddb0172 2625 fndecl, num_args, args);
b902b078 2626 gfc_add_expr_to_block (&se->pre, tmp);
2627
2628 /* Free the temporary afterwards, if necessary. */
6f5c9335 2629 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2630 len, build_int_cst (TREE_TYPE (len), 0));
9915365e 2631 tmp = gfc_call_free (var);
e60a6f7b 2632 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
b902b078 2633 gfc_add_expr_to_block (&se->post, tmp);
2634
2635 se->expr = var;
2636 se->string_length = len;
2637}
2638
2639
2640static void
2641gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
2642{
2643 tree var;
2644 tree len;
2645 tree tmp;
b902b078 2646 tree cond;
5ddb0172 2647 tree fndecl;
2648 tree *args;
2649 unsigned int num_args;
2650
2651 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
86b32f71 2652 args = XALLOCAVEC (tree, num_args);
b902b078 2653
329f13ad 2654 var = gfc_create_var (pchar_type_node, "pstr");
185bc3c7 2655 len = gfc_create_var (gfc_charlen_type_node, "len");
b902b078 2656
5ddb0172 2657 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
86f2ad37 2658 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2659 args[1] = gfc_build_addr_expr (NULL_TREE, len);
b902b078 2660
0e49e441 2661 fndecl = build_addr (gfor_fndecl_fdate);
389dd41b 2662 tmp = build_call_array_loc (input_location,
2663 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
5ddb0172 2664 fndecl, num_args, args);
b902b078 2665 gfc_add_expr_to_block (&se->pre, tmp);
2666
2667 /* Free the temporary afterwards, if necessary. */
6f5c9335 2668 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2669 len, build_int_cst (TREE_TYPE (len), 0));
9915365e 2670 tmp = gfc_call_free (var);
e60a6f7b 2671 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
b902b078 2672 gfc_add_expr_to_block (&se->post, tmp);
2673
2674 se->expr = var;
2675 se->string_length = len;
2676}
2677
2678
c338399c 2679/* Generate a direct call to free() for the FREE subroutine. */
2680
2681static tree
2682conv_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
72ce5390 2700/* Call the SYSTEM_CLOCK library functions, handling the type and kind
2701 conversions. */
2702
2703static tree
2704conv_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;
1e0061a8 2709 tree tmp;
2710 int least;
72ce5390 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
72ce5390 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
1e0061a8 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 }
72ce5390 2758
1e0061a8 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 }
72ce5390 2768
1e0061a8 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 }
72ce5390 2778
293d72e0 2779 /* Make the function call. */
72ce5390 2780 gfc_init_block (&block);
1e0061a8 2781
2782if (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 }
535b0484 2793
1e0061a8 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 }
2804else
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 }
72ce5390 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
dbc97b88 2848/* Return a character string containing the tty name. */
2849
2850static void
2851gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
2852{
2853 tree var;
2854 tree len;
2855 tree tmp;
dbc97b88 2856 tree cond;
5ddb0172 2857 tree fndecl;
5ddb0172 2858 tree *args;
2859 unsigned int num_args;
2860
2861 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
86b32f71 2862 args = XALLOCAVEC (tree, num_args);
dbc97b88 2863
329f13ad 2864 var = gfc_create_var (pchar_type_node, "pstr");
185bc3c7 2865 len = gfc_create_var (gfc_charlen_type_node, "len");
dbc97b88 2866
5ddb0172 2867 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
86f2ad37 2868 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2869 args[1] = gfc_build_addr_expr (NULL_TREE, len);
dbc97b88 2870
0e49e441 2871 fndecl = build_addr (gfor_fndecl_ttynam);
389dd41b 2872 tmp = build_call_array_loc (input_location,
2873 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
5ddb0172 2874 fndecl, num_args, args);
dbc97b88 2875 gfc_add_expr_to_block (&se->pre, tmp);
2876
2877 /* Free the temporary afterwards, if necessary. */
6f5c9335 2878 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2879 len, build_int_cst (TREE_TYPE (len), 0));
9915365e 2880 tmp = gfc_call_free (var);
e60a6f7b 2881 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
dbc97b88 2882 gfc_add_expr_to_block (&se->post, tmp);
2883
2884 se->expr = var;
2885 se->string_length = len;
2886}
2887
2888
4ee9c684 2889/* Get the minimum/maximum value of all the parameters.
2890 minmax (a1, a2, a3, ...)
2891 {
0cc4742f 2892 mvar = a1;
60e19868 2893 if (a2 .op. mvar || isnan (mvar))
4ee9c684 2894 mvar = a2;
60e19868 2895 if (a3 .op. mvar || isnan (mvar))
4ee9c684 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. */
2904static void
d62fb8de 2905gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
4ee9c684 2906{
4ee9c684 2907 tree tmp;
2908 tree mvar;
2909 tree val;
2910 tree thencase;
5ddb0172 2911 tree *args;
4ee9c684 2912 tree type;
edf97ddf 2913 gfc_actual_arglist *argexpr;
0cc4742f 2914 unsigned int i, nargs;
4ee9c684 2915
5ddb0172 2916 nargs = gfc_intrinsic_argument_list_length (expr);
86b32f71 2917 args = XALLOCAVEC (tree, nargs);
5ddb0172 2918
2919 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
4ee9c684 2920 type = gfc_typenode_for_spec (&expr->ts);
2921
edf97ddf 2922 argexpr = expr->value.function.actual;
0cc4742f 2923 if (TREE_TYPE (args[0]) != type)
2924 args[0] = convert (type, args[0]);
4ee9c684 2925 /* Only evaluate the argument once. */
0cc4742f 2926 if (TREE_CODE (args[0]) != VAR_DECL && !TREE_CONSTANT (args[0]))
2927 args[0] = gfc_evaluate_now (args[0], &se->pre);
4ee9c684 2928
2929 mvar = gfc_create_var (type, "M");
75a70cf9 2930 gfc_add_modify (&se->pre, mvar, args[0]);
5ddb0172 2931 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
4ee9c684 2932 {
34203d28 2933 tree cond, isnan;
edf97ddf 2934
411ee1e5 2935 val = args[i];
4ee9c684 2936
edf97ddf 2937 /* Handle absent optional arguments by ignoring the comparison. */
0cc4742f 2938 if (argexpr->expr->expr_type == EXPR_VARIABLE
edf97ddf 2939 && argexpr->expr->symtree->n.sym->attr.optional
2940 && TREE_CODE (val) == INDIRECT_REF)
389dd41b 2941 cond = fold_build2_loc (input_location,
2942 NE_EXPR, boolean_type_node,
411ee1e5 2943 TREE_OPERAND (val, 0),
389dd41b 2944 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
edf97ddf 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 }
4ee9c684 2953
ed52ef8b 2954 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
4ee9c684 2955
6f5c9335 2956 tmp = fold_build2_loc (input_location, op, boolean_type_node,
2957 convert (type, val), mvar);
34203d28 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. */
0cc4742f 2962 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
34203d28 2963 {
389dd41b 2964 isnan = build_call_expr_loc (input_location,
b9a16870 2965 builtin_decl_explicit (BUILT_IN_ISNAN),
2966 1, mvar);
6f5c9335 2967 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2968 boolean_type_node, tmp,
2969 fold_convert (boolean_type_node, isnan));
34203d28 2970 }
e60a6f7b 2971 tmp = build3_v (COND_EXPR, tmp, thencase,
2972 build_empty_stmt (input_location));
edf97ddf 2973
2974 if (cond != NULL_TREE)
e60a6f7b 2975 tmp = build3_v (COND_EXPR, cond, tmp,
2976 build_empty_stmt (input_location));
edf97ddf 2977
4ee9c684 2978 gfc_add_expr_to_block (&se->pre, tmp);
edf97ddf 2979 argexpr = argexpr->next;
4ee9c684 2980 }
2981 se->expr = mvar;
2982}
2983
2984
5fcc6ec2 2985/* Generate library calls for MIN and MAX intrinsics for character
2986 variables. */
2987static void
2988gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
2989{
2990 tree *args;
40b806de 2991 tree var, len, fndecl, tmp, cond, function;
5fcc6ec2 2992 unsigned int nargs;
2993
2994 nargs = gfc_intrinsic_argument_list_length (expr);
86b32f71 2995 args = XALLOCAVEC (tree, nargs + 4);
5fcc6ec2 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");
86f2ad37 3000 args[0] = gfc_build_addr_expr (NULL_TREE, len);
329f13ad 3001 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
5fcc6ec2 3002 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
35bf1214 3003 args[2] = build_int_cst (integer_type_node, op);
3004 args[3] = build_int_cst (integer_type_node, nargs / 2);
5fcc6ec2 3005
40b806de 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
5fcc6ec2 3013 /* Make the function call. */
0e49e441 3014 fndecl = build_addr (function);
389dd41b 3015 tmp = build_call_array_loc (input_location,
3016 TREE_TYPE (TREE_TYPE (function)), fndecl,
40b806de 3017 nargs + 4, args);
5fcc6ec2 3018 gfc_add_expr_to_block (&se->pre, tmp);
3019
3020 /* Free the temporary afterwards, if necessary. */
6f5c9335 3021 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
3022 len, build_int_cst (TREE_TYPE (len), 0));
5fcc6ec2 3023 tmp = gfc_call_free (var);
e60a6f7b 3024 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
5fcc6ec2 3025 gfc_add_expr_to_block (&se->post, tmp);
3026
3027 se->expr = var;
3028 se->string_length = len;
3029}
3030
3031
6f0539a0 3032/* Create a symbol node for this intrinsic. The symbol from the frontend
3033 has the generic name. */
4ee9c684 3034
3035static gfc_symbol *
4b36c1ce 3036gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
4ee9c684 3037{
3038 gfc_symbol *sym;
3039
3040 /* TODO: Add symbols for intrinsic function to the global namespace. */
22d678e8 3041 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
4ee9c684 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
4b36c1ce 3059 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
3060 ignore_optional ? expr->value.function.actual
3061 : NULL);
faa9fea4 3062
4ee9c684 3063 return sym;
3064}
3065
3066/* Generate a call to an external intrinsic function. */
3067static void
3068gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
3069{
3070 gfc_symbol *sym;
f1f41a6c 3071 vec<tree, va_gc> *append_args;
4ee9c684 3072
bfa43780 3073 gcc_assert (!se->ss || se->ss->info->expr == expr);
4ee9c684 3074
3075 if (se->ss)
22d678e8 3076 gcc_assert (expr->rank > 0);
4ee9c684 3077 else
22d678e8 3078 gcc_assert (expr->rank == 0);
4ee9c684 3079
4b36c1ce 3080 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
4e8e57b0 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. */
008f96d8 3084 append_args = NULL;
55cb4417 3085 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
4e8e57b0 3086 && sym->ts.type != BT_LOGICAL)
3087 {
3088 tree cint = gfc_get_int_type (gfc_c_int_kind);
3089
829d7a08 3090 if (flag_external_blas
4e8e57b0 3091 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
19bbb6e7 3092 && (sym->ts.kind == 4 || sym->ts.kind == 8))
4e8e57b0 3093 {
3094 tree gemm_fndecl;
3095
3096 if (sym->ts.type == BT_REAL)
3097 {
19bbb6e7 3098 if (sym->ts.kind == 4)
4e8e57b0 3099 gemm_fndecl = gfor_fndecl_sgemm;
3100 else
3101 gemm_fndecl = gfor_fndecl_dgemm;
3102 }
3103 else
3104 {
19bbb6e7 3105 if (sym->ts.kind == 4)
4e8e57b0 3106 gemm_fndecl = gfor_fndecl_cgemm;
3107 else
3108 gemm_fndecl = gfor_fndecl_zgemm;
3109 }
3110
f1f41a6c 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,
829d7a08 3114 flag_blas_matmul_limit));
f1f41a6c 3115 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
3116 gemm_fndecl));
4e8e57b0 3117 }
3118 else
3119 {
f1f41a6c 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);
4e8e57b0 3124 }
3125 }
3126
64e93293 3127 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
3128 append_args);
16760fe7 3129 gfc_free_symbol (sym);
4ee9c684 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 */
3151static void
d62fb8de 3152gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
4ee9c684 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);
75a70cf9 3180 gfc_add_modify (&se->pre, resvar, tmp);
4ee9c684 3181
3182 /* Walk the arguments. */
3183 arrayss = gfc_walk_expr (actual->expr);
22d678e8 3184 gcc_assert (arrayss != gfc_ss_terminator);
4ee9c684 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);
92f4d1c4 3194 gfc_conv_loop_setup (&loop, &expr->where);
4ee9c684 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);
75a70cf9 3206 gfc_add_modify (&block, resvar, tmp);
4ee9c684 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);
6f5c9335 3221 tmp = fold_build2_loc (input_location, op, boolean_type_node, arrayse.expr,
3222 build_int_cst (TREE_TYPE (arrayse.expr), 0));
e60a6f7b 3223 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
4ee9c684 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. */
3241static void
3242gfc_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");
75a70cf9 3264 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4ee9c684 3265
3266 /* Walk the arguments. */
3267 arrayss = gfc_walk_expr (actual->expr);
22d678e8 3268 gcc_assert (arrayss != gfc_ss_terminator);
4ee9c684 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);
92f4d1c4 3276 gfc_conv_loop_setup (&loop, &expr->where);
4ee9c684 3277
3278 gfc_mark_ss_chain_used (arrayss, 1);
3279 /* Generate the loop body. */
3280 gfc_start_scalarized_body (&loop, &body);
3281
6f5c9335 3282 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
3283 resvar, build_int_cst (TREE_TYPE (resvar), 1));
ed52ef8b 3284 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
4ee9c684 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);
e60a6f7b 3290 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
3291 build_empty_stmt (input_location));
4ee9c684 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
88df5e2f 3306
3307/* Update given gfc_se to have ss component pointing to the nested gfc_ss
3308 struct and return the corresponding loopinfo. */
3309
3310static gfc_loopinfo *
3311enter_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
4ee9c684 3320/* Inline implementation of the sum and product intrinsics. */
3321static void
b4ba8232 3322gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
3323 bool norm2)
4ee9c684 3324{
3325 tree resvar;
b4ba8232 3326 tree scale = NULL_TREE;
4ee9c684 3327 tree type;
3328 stmtblock_t body;
3329 stmtblock_t block;
3330 tree tmp;
cae7ff32 3331 gfc_loopinfo loop, *ploop;
dbef2853 3332 gfc_actual_arglist *arg_array, *arg_mask;
88df5e2f 3333 gfc_ss *arrayss = NULL;
3334 gfc_ss *maskss = NULL;
4ee9c684 3335 gfc_se arrayse;
3336 gfc_se maskse;
85b3b7b7 3337 gfc_se *parent_se;
4ee9c684 3338 gfc_expr *arrayexpr;
3339 gfc_expr *maskexpr;
3340
88df5e2f 3341 if (expr->rank > 0)
4ee9c684 3342 {
88df5e2f 3343 gcc_assert (gfc_inline_intrinsic_function_p (expr));
3344 parent_se = se;
4ee9c684 3345 }
85b3b7b7 3346 else
3347 parent_se = NULL;
4ee9c684 3348
3349 type = gfc_typenode_for_spec (&expr->ts);
3350 /* Initialize the result. */
3351 resvar = gfc_create_var (type, "val");
b4ba8232 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 }
9028d57d 3361 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4ee9c684 3362 tmp = gfc_build_const (type, integer_zero_node);
b4ba8232 3363 else if (op == NE_EXPR)
3364 /* PARITY. */
3365 tmp = convert (type, boolean_false_node);
9028d57d 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));
4ee9c684 3369 else
3370 tmp = gfc_build_const (type, integer_one_node);
3371
75a70cf9 3372 gfc_add_modify (&se->pre, resvar, tmp);
4ee9c684 3373
dbef2853 3374 arg_array = expr->value.function.actual;
3375
dbef2853 3376 arrayexpr = arg_array->expr;
4ee9c684 3377
b4ba8232 3378 if (op == NE_EXPR || norm2)
3379 /* PARITY and NORM2. */
3380 maskexpr = NULL;
3381 else
3382 {
dbef2853 3383 arg_mask = arg_array->next->next;
3384 gcc_assert (arg_mask != NULL);
3385 maskexpr = arg_mask->expr;
b4ba8232 3386 }
3387
88df5e2f 3388 if (expr->rank == 0)
4ee9c684 3389 {
88df5e2f 3390 /* Walk the arguments. */
3391 arrayss = gfc_walk_expr (arrayexpr);
3392 gcc_assert (arrayss != gfc_ss_terminator);
4ee9c684 3393
88df5e2f 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;
4ee9c684 3401
88df5e2f 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);
4ee9c684 3407
88df5e2f 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);
cae7ff32 3423
4ee9c684 3424 /* Generate the loop body. */
cae7ff32 3425 gfc_start_scalarized_body (ploop, &body);
4ee9c684 3426
3427 /* If we have a mask, only add this element if the mask is set. */
190c9d73 3428 if (maskexpr && maskexpr->rank > 0)
4ee9c684 3429 {
85b3b7b7 3430 gfc_init_se (&maskse, parent_se);
cae7ff32 3431 gfc_copy_loopinfo_to_se (&maskse, ploop);
88df5e2f 3432 if (expr->rank == 0)
3433 maskse.ss = maskss;
4ee9c684 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. */
85b3b7b7 3443 gfc_init_se (&arrayse, parent_se);
cae7ff32 3444 gfc_copy_loopinfo_to_se (&arrayse, ploop);
88df5e2f 3445 if (expr->rank == 0)
3446 arrayse.ss = arrayss;
4ee9c684 3447 gfc_conv_expr_val (&arrayse, arrayexpr);
3448 gfc_add_block_to_block (&block, &arrayse.pre);
3449
b4ba8232 3450 if (norm2)
3451 {
60e19868 3452 /* if (x (i) != 0.0)
b4ba8232 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,
6f5c9335 3474 fold_build1_loc (input_location, ABS_EXPR, type,
3475 arrayse.expr));
b4ba8232 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,
6f5c9335 3481 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
3482 absX));
411ee1e5 3483 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
6f5c9335 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));
b4ba8232 3487 gfc_add_modify (&ifblock2, resvar, res1);
3488 gfc_add_modify (&ifblock2, scale, absX);
411ee1e5 3489 res1 = gfc_finish_block (&ifblock2);
b4ba8232 3490
3491 gfc_init_block (&ifblock3);
3492 gfc_add_modify (&ifblock3, val,
6f5c9335 3493 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
3494 scale));
411ee1e5 3495 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
6f5c9335 3496 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
b4ba8232 3497 gfc_add_modify (&ifblock3, resvar, res2);
3498 res2 = gfc_finish_block (&ifblock3);
3499
6f5c9335 3500 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
3501 absX, scale);
b4ba8232 3502 tmp = build3_v (COND_EXPR, cond, res1, res2);
411ee1e5 3503 gfc_add_expr_to_block (&ifblock1, tmp);
b4ba8232 3504 tmp = gfc_finish_block (&ifblock1);
3505
6f5c9335 3506 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
3507 arrayse.expr,
3508 gfc_build_const (type, integer_zero_node));
b4ba8232 3509
3510 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
411ee1e5 3511 gfc_add_expr_to_block (&block, tmp);
b4ba8232 3512 }
3513 else
3514 {
6f5c9335 3515 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
b4ba8232 3516 gfc_add_modify (&block, resvar, tmp);
3517 }
3518
4ee9c684 3519 gfc_add_block_to_block (&block, &arrayse.post);
3520
190c9d73 3521 if (maskexpr && maskexpr->rank > 0)
4ee9c684 3522 {
3523 /* We enclose the above in if (mask) {...} . */
4ee9c684 3524
b4ba8232 3525 tmp = gfc_finish_block (&block);
e60a6f7b 3526 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3527 build_empty_stmt (input_location));
4ee9c684 3528 }
3529 else
3530 tmp = gfc_finish_block (&block);
3531 gfc_add_expr_to_block (&body, tmp);
3532
cae7ff32 3533 gfc_trans_scalarizing_loops (ploop, &body);
91b2f40f 3534
3535 /* For a scalar mask, enclose the loop in an if statement. */
190c9d73 3536 if (maskexpr && maskexpr->rank == 0)
91b2f40f 3537 {
91b2f40f 3538 gfc_init_block (&block);
cae7ff32 3539 gfc_add_block_to_block (&block, &ploop->pre);
3540 gfc_add_block_to_block (&block, &ploop->post);
91b2f40f 3541 tmp = gfc_finish_block (&block);
3542
88df5e2f 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
91b2f40f 3558 gfc_add_expr_to_block (&block, tmp);
3559 gfc_add_block_to_block (&se->pre, &block);
88df5e2f 3560 gcc_assert (se->post.head == NULL);
91b2f40f 3561 }
3562 else
3563 {
cae7ff32 3564 gfc_add_block_to_block (&se->pre, &ploop->pre);
3565 gfc_add_block_to_block (&se->pre, &ploop->post);
91b2f40f 3566 }
3567
88df5e2f 3568 if (expr->rank == 0)
3569 gfc_cleanup_loop (ploop);
4ee9c684 3570
b4ba8232 3571 if (norm2)
3572 {
3573 /* result = scale * sqrt(result). */
3574 tree sqrt;
808656b4 3575 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
b4ba8232 3576 resvar = build_call_expr_loc (input_location,
3577 sqrt, 1, resvar);
6f5c9335 3578 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
b4ba8232 3579 }
3580
4ee9c684 3581 se->expr = resvar;
3582}
3583
0b5dc8b5 3584
3585/* Inline implementation of the dot_product intrinsic. This function
3586 is based on gfc_conv_intrinsic_arith (the previous function). */
3587static void
3588gfc_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)
a69b6929 3606 tmp = build_int_cst (type, 0);
0b5dc8b5 3607 else
3608 tmp = gfc_build_const (type, integer_zero_node);
3609
75a70cf9 3610 gfc_add_modify (&se->pre, resvar, tmp);
0b5dc8b5 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);
92f4d1c4 3631 gfc_conv_loop_setup (&loop, &expr->where);
0b5dc8b5 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)
6f5c9335 3646 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
3647 arrayse1.expr);
0b5dc8b5 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 {
6f5c9335 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);
0b5dc8b5 3663 }
3664 else
3665 {
6f5c9335 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);
0b5dc8b5 3669 }
75a70cf9 3670 gfc_add_modify (&block, resvar, tmp);
0b5dc8b5 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
7ebee933 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
4ee9c684 3751static void
d62fb8de 3752gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
4ee9c684 3753{
3754 stmtblock_t body;
3755 stmtblock_t block;
3756 stmtblock_t ifblock;
622183f4 3757 stmtblock_t elseblock;
4ee9c684 3758 tree limit;
3759 tree type;
3760 tree tmp;
7ebee933 3761 tree cond;
622183f4 3762 tree elsetmp;
4ee9c684 3763 tree ifbody;
30dc020c 3764 tree offset;
7ebee933 3765 tree nonempty;
3766 tree lab1, lab2;
4ee9c684 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");
30dc020c 3786 offset = gfc_create_var (gfc_array_index_type, "offset");
4ee9c684 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);
22d678e8 3793 gcc_assert (arrayss != gfc_ss_terminator);
4ee9c684 3794
3795 actual = actual->next->next;
22d678e8 3796 gcc_assert (actual);
4ee9c684 3797 maskexpr = actual->expr;
7ebee933 3798 nonempty = NULL;
622183f4 3799 if (maskexpr && maskexpr->rank != 0)
4ee9c684 3800 {
3801 maskss = gfc_walk_expr (maskexpr);
22d678e8 3802 gcc_assert (maskss != gfc_ss_terminator);
4ee9c684 3803 }
3804 else
7ebee933 3805 {
3806 mpz_t asize;
60e19868 3807 if (gfc_array_size (arrayexpr, &asize))
7ebee933 3808 {
3809 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
3810 mpz_clear (asize);
6f5c9335 3811 nonempty = fold_build2_loc (input_location, GT_EXPR,
3812 boolean_type_node, nonempty,
3813 gfc_index_zero_node);
7ebee933 3814 }
3815 maskss = NULL;
3816 }
4ee9c684 3817
3818 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
4ee9c684 3819 switch (arrayexpr->ts.type)
3820 {
3821 case BT_REAL:
729e6db2 3822 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
4ee9c684 3823 break;
3824
3825 case BT_INTEGER:
729e6db2 3826 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
4ee9c684 3827 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
3828 arrayexpr->ts.kind);
3829 break;
3830
3831 default:
22d678e8 3832 gcc_unreachable ();
4ee9c684 3833 }
3834
1706268d 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
f6d0e37a 3838 possible value is HUGE in both cases. */
4ee9c684 3839 if (op == GT_EXPR)
6f5c9335 3840 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
053fdea9 3841 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
6f5c9335 3842 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
053fdea9 3843 build_int_cst (TREE_TYPE (tmp), 1));
1706268d 3844
19a12e8d 3845 gfc_add_modify (&se->pre, limit, tmp);
3846
4ee9c684 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);
30eabb0d 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;
92f4d1c4 3872 gfc_conv_loop_setup (&loop, &expr->where);
4ee9c684 3873
22d678e8 3874 gcc_assert (loop.dimen == 1);
7ebee933 3875 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
6f5c9335 3876 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3877 loop.from[0], loop.to[0]);
4ee9c684 3878
7ebee933 3879 lab1 = NULL;
3880 lab2 = NULL;
b1660f25 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
7ebee933 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,
6f5c9335 3888 fold_build3_loc (input_location, COND_EXPR,
3889 gfc_array_index_type,
3890 nonempty, gfc_index_one_node,
3891 gfc_index_zero_node));
7ebee933 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 }
6bcf802b 3900
e816ed35 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
30eabb0d 3909 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
4ee9c684 3910 if (maskss)
30eabb0d 3911 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
4ee9c684 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... */
75a70cf9 3940 gfc_add_modify (&ifblock, limit, arrayse.expr);
4ee9c684 3941
7ebee933 3942 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
3943 {
3944 stmtblock_t ifblock2;
3945 tree ifbody2;
3946
3947 gfc_start_block (&ifblock2);
6f5c9335 3948 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3949 loop.loopvar[0], offset);
7ebee933 3950 gfc_add_modify (&ifblock2, pos, tmp);
3951 ifbody2 = gfc_finish_block (&ifblock2);
6f5c9335 3952 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, pos,
3953 gfc_index_zero_node);
7ebee933 3954 tmp = build3_v (COND_EXPR, cond, ifbody2,
3955 build_empty_stmt (input_location));
3956 gfc_add_expr_to_block (&block, tmp);
3957 }
3958
6f5c9335 3959 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3960 loop.loopvar[0], offset);
75a70cf9 3961 gfc_add_modify (&ifblock, pos, tmp);
4ee9c684 3962
7ebee933 3963 if (lab1)
3964 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
3965
4ee9c684 3966 ifbody = gfc_finish_block (&ifblock);
3967
7ebee933 3968 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
3969 {
3970 if (lab1)
6f5c9335 3971 cond = fold_build2_loc (input_location,
3972 op == GT_EXPR ? GE_EXPR : LE_EXPR,
3973 boolean_type_node, arrayse.expr, limit);
7ebee933 3974 else
6f5c9335 3975 cond = fold_build2_loc (input_location, op, boolean_type_node,
3976 arrayse.expr, limit);
7ebee933 3977
3978 ifbody = build3_v (COND_EXPR, cond, ifbody,
3979 build_empty_stmt (input_location));
3980 }
3981 gfc_add_expr_to_block (&block, ifbody);
4ee9c684 3982
3983 if (maskss)
3984 {
3985 /* We enclose the above in if (mask) {...}. */
3986 tmp = gfc_finish_block (&block);
3987
e60a6f7b 3988 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3989 build_empty_stmt (input_location));
4ee9c684 3990 }
3991 else
3992 tmp = gfc_finish_block (&block);
3993 gfc_add_expr_to_block (&body, tmp);
3994
7ebee933 3995 if (lab1)
3996 {
30eabb0d 3997 gfc_trans_scalarized_loop_boundary (&loop, &body);
7ebee933 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));
7ebee933 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
6f5c9335 4040 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
4041 loop.loopvar[0], offset);
7ebee933 4042 gfc_add_modify (&ifblock, pos, tmp);
4043
4044 ifbody = gfc_finish_block (&ifblock);
4045
6f5c9335 4046 cond = fold_build2_loc (input_location, op, boolean_type_node,
4047 arrayse.expr, limit);
7ebee933 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
4ee9c684 4069 gfc_trans_scalarizing_loops (&loop, &body);
4070
7ebee933 4071 if (lab2)
4072 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
4073
622183f4 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);
75a70cf9 4088 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
622183f4 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 }
4ee9c684 4100 gfc_cleanup_loop (&loop);
4101
30dc020c 4102 se->expr = convert (type, pos);
4ee9c684 4103}
4104
7ebee933 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
4ee9c684 4198static void
d62fb8de 4199gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
4ee9c684 4200{
4201 tree limit;
4202 tree type;
4203 tree tmp;
4204 tree ifbody;
7ebee933 4205 tree nonempty;
4206 tree nonempty_var;
4207 tree lab;
4208 tree fast;
4209 tree huge_cst = NULL, nan_cst = NULL;
4ee9c684 4210 stmtblock_t body;
7ebee933 4211 stmtblock_t block, block2;
4ee9c684 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");
f2d4ef3b 4231 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
4ee9c684 4232 switch (expr->ts.type)
4233 {
4234 case BT_REAL:
7ebee933 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)))
1d8a0522 4246 nan_cst = gfc_build_nan (type, "");
4ee9c684 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:
22d678e8 4254 gcc_unreachable ();
4ee9c684 4255 }
4256
1706268d 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
f6d0e37a 4260 possible value is HUGE in both cases. */
4ee9c684 4261 if (op == GT_EXPR)
7ebee933 4262 {
6f5c9335 4263 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
7ebee933 4264 if (huge_cst)
6f5c9335 4265 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
4266 TREE_TYPE (huge_cst), huge_cst);
7ebee933 4267 }
1706268d 4268
4269 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
6f5c9335 4270 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
4271 tmp, build_int_cst (type, 1));
1706268d 4272
75a70cf9 4273 gfc_add_modify (&se->pre, limit, tmp);
4ee9c684 4274
4275 /* Walk the arguments. */
4276 actual = expr->value.function.actual;
4277 arrayexpr = actual->expr;
4278 arrayss = gfc_walk_expr (arrayexpr);
22d678e8 4279 gcc_assert (arrayss != gfc_ss_terminator);
4ee9c684 4280
4281 actual = actual->next->next;
22d678e8 4282 gcc_assert (actual);
4ee9c684 4283 maskexpr = actual->expr;
7ebee933 4284 nonempty = NULL;
91b2f40f 4285 if (maskexpr && maskexpr->rank != 0)
4ee9c684 4286 {
4287 maskss = gfc_walk_expr (maskexpr);
22d678e8 4288 gcc_assert (maskss != gfc_ss_terminator);
4ee9c684 4289 }
4290 else
7ebee933 4291 {
4292 mpz_t asize;
60e19868 4293 if (gfc_array_size (arrayexpr, &asize))
7ebee933 4294 {
4295 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
4296 mpz_clear (asize);
6f5c9335 4297 nonempty = fold_build2_loc (input_location, GT_EXPR,
4298 boolean_type_node, nonempty,
4299 gfc_index_zero_node);
7ebee933 4300 }
4301 maskss = NULL;
4302 }
4ee9c684 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);
469bafde 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;
92f4d1c4 4328 gfc_conv_loop_setup (&loop, &expr->where);
4ee9c684 4329
7ebee933 4330 if (nonempty == NULL && maskss == NULL
4331 && loop.dimen == 1 && loop.from[0] && loop.to[0])
6f5c9335 4332 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
4333 loop.from[0], loop.to[0]);
7ebee933 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
469bafde 4359 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
4ee9c684 4360 if (maskss)
469bafde 4361 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
4ee9c684 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
7ebee933 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 {
6f5c9335 4393 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
4394 boolean_type_node, arrayse.expr, limit);
7ebee933 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 {
6f5c9335 4416 tmp = fold_build2_loc (input_location, op, boolean_type_node,
4417 arrayse.expr, limit);
7ebee933 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 {
6f5c9335 4425 tmp = fold_build2_loc (input_location,
4426 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
4427 type, arrayse.expr, limit);
7ebee933 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 {
6f5c9335 4441 tmp = fold_build2_loc (input_location, op, boolean_type_node,
4442 arrayse.expr, limit);
7ebee933 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 {
6f5c9335 4449 tmp = fold_build2_loc (input_location,
4450 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
4451 type, arrayse.expr, limit);
7ebee933 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);
4ee9c684 4459
4ee9c684 4460 gfc_add_block_to_block (&block, &arrayse.post);
4461
4462 tmp = gfc_finish_block (&block);
4463 if (maskss)
ed52ef8b 4464 /* We enclose the above in if (mask) {...}. */
e60a6f7b 4465 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
4466 build_empty_stmt (input_location));
4ee9c684 4467 gfc_add_expr_to_block (&body, tmp);
4468
7ebee933 4469 if (lab)
4470 {
469bafde 4471 gfc_trans_scalarized_loop_boundary (&loop, &body);
7ebee933 4472
6f5c9335 4473 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
4474 nan_cst, huge_cst);
7ebee933 4475 gfc_add_modify (&loop.code[0], limit, tmp);
4476 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
4477
7ebee933 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 {
6f5c9335 4504 tmp = fold_build2_loc (input_location, op, boolean_type_node,
4505 arrayse.expr, limit);
7ebee933 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 {
6f5c9335 4513 tmp = fold_build2_loc (input_location,
4514 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
4515 type, arrayse.expr, limit);
7ebee933 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 }
4ee9c684 4531 gfc_trans_scalarizing_loops (&loop, &body);
4532
7ebee933 4533 if (fast)
4534 {
6f5c9335 4535 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
4536 nan_cst, huge_cst);
7ebee933 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 {
6f5c9335 4544 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
4545 huge_cst);
7ebee933 4546 gfc_add_modify (&loop.pre, limit, tmp);
4547 }
4548
91b2f40f 4549 /* For a scalar mask, enclose the loop in an if statement. */
4550 if (maskexpr && maskss == NULL)
4551 {
7ebee933 4552 tree else_stmt;
4553
91b2f40f 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
7ebee933 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);
91b2f40f 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
4ee9c684 4575 gfc_cleanup_loop (&loop);
4576
4577 se->expr = limit;
4578}
4579
4580/* BTEST (i, pos) = (i & (1 << pos)) != 0. */
4581static void
4582gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
4583{
5ddb0172 4584 tree args[2];
4ee9c684 4585 tree type;
4586 tree tmp;
4587
5ddb0172 4588 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4589 type = TREE_TYPE (args[0]);
4ee9c684 4590
6f5c9335 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));
4ee9c684 4596 type = gfc_typenode_for_spec (&expr->ts);
4597 se->expr = convert (type, tmp);
4598}
4599
f004c7aa 4600
4601/* Generate code for BGE, BGT, BLE and BLT intrinsics. */
4602static void
4603gfc_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
4ee9c684 4627/* Generate code to perform the specified operation. */
4628static void
d62fb8de 4629gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
4ee9c684 4630{
5ddb0172 4631 tree args[2];
4ee9c684 4632
5ddb0172 4633 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6f5c9335 4634 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
4635 args[0], args[1]);
4ee9c684 4636}
4637
4638/* Bitwise not. */
4639static void
4640gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
4641{
4642 tree arg;
4643
5ddb0172 4644 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6f5c9335 4645 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
4646 TREE_TYPE (arg), arg);
4ee9c684 4647}
4648
4649/* Set or clear a single bit. */
4650static void
4651gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
4652{
5ddb0172 4653 tree args[2];
4ee9c684 4654 tree type;
4655 tree tmp;
d62fb8de 4656 enum tree_code op;
4ee9c684 4657
5ddb0172 4658 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4659 type = TREE_TYPE (args[0]);
4ee9c684 4660
6f5c9335 4661 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
4662 build_int_cst (type, 1), args[1]);
4ee9c684 4663 if (set)
4664 op = BIT_IOR_EXPR;
4665 else
4666 {
4667 op = BIT_AND_EXPR;
6f5c9335 4668 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
4ee9c684 4669 }
6f5c9335 4670 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
4ee9c684 4671}
4672
4673/* Extract a sequence of bits.
4674 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
4675static void
4676gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
4677{
5ddb0172 4678 tree args[3];
4ee9c684 4679 tree type;
4680 tree tmp;
4681 tree mask;
4682
5ddb0172 4683 gfc_conv_intrinsic_function_args (se, expr, args, 3);
4684 type = TREE_TYPE (args[0]);
4ee9c684 4685
33130b1d 4686 mask = build_int_cst (type, -1);
6f5c9335 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);
4ee9c684 4689
6f5c9335 4690 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
4ee9c684 4691
6f5c9335 4692 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
4ee9c684 4693}
4694
d2fc5bb1 4695static void
f004c7aa 4696gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
4697 bool arithmetic)
d2fc5bb1 4698{
f004c7aa 4699 tree args[2], type, num_bits, cond;
d2fc5bb1 4700
5ddb0172 4701 gfc_conv_intrinsic_function_args (se, expr, args, 2);
d2fc5bb1 4702
f004c7aa 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
6f5c9335 4712 se->expr = fold_build2_loc (input_location,
4713 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
4714 TREE_TYPE (args[0]), args[0], args[1]);
f004c7aa 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);
d2fc5bb1 4728}
4729
4d66f715 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. */
4ee9c684 4734static void
4735gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
4736{
5ddb0172 4737 tree args[2];
4ee9c684 4738 tree type;
4d66f715 4739 tree utype;
4ee9c684 4740 tree tmp;
4d66f715 4741 tree width;
4742 tree num_bits;
4743 tree cond;
4ee9c684 4744 tree lshift;
4745 tree rshift;
4746
5ddb0172 4747 gfc_conv_intrinsic_function_args (se, expr, args, 2);
15da0ca7 4748
4749 args[0] = gfc_evaluate_now (args[0], &se->pre);
4750 args[1] = gfc_evaluate_now (args[1], &se->pre);
4751
5ddb0172 4752 type = TREE_TYPE (args[0]);
71eea85c 4753 utype = unsigned_type_for (type);
4ee9c684 4754
6f5c9335 4755 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
4756 args[1]);
4ee9c684 4757
4d66f715 4758 /* Left shift if positive. */
6f5c9335 4759 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
4d66f715 4760
f50c9c11 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. */
6f5c9335 4766 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
4767 utype, convert (utype, args[0]), width));
4d66f715 4768
6f5c9335 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);
4d66f715 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. */
bdb4cd30 4776 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6f5c9335 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);
4ee9c684 4781}
4782
9dd6c589 4783
4ee9c684 4784/* Circular shift. AKA rotate or barrel shift. */
9dd6c589 4785
4ee9c684 4786static void
4787gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
4788{
5ddb0172 4789 tree *args;
4ee9c684 4790 tree type;
4791 tree tmp;
4792 tree lrot;
4793 tree rrot;
6dbb04e3 4794 tree zero;
5ddb0172 4795 unsigned int num_args;
4ee9c684 4796
5ddb0172 4797 num_args = gfc_intrinsic_argument_list_length (expr);
86b32f71 4798 args = XALLOCAVEC (tree, num_args);
5ddb0172 4799
4800 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4801
4802 if (num_args == 3)
4ee9c684 4803 {
4804 /* Use a library function for the 3 parameter version. */
4d66f715 4805 tree int4type = gfc_get_int_type (4);
4806
5ddb0172 4807 type = TREE_TYPE (args[0]);
4d66f715 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)
5ddb0172 4813 args[0] = convert (int4type, args[0]);
4814
4d66f715 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. */
5ddb0172 4818 args[1] = convert (int4type, args[1]);
4819 args[2] = convert (int4type, args[2]);
4ee9c684 4820
4821 switch (expr->ts.kind)
4822 {
4d66f715 4823 case 1:
4824 case 2:
4ee9c684 4825 case 4:
4826 tmp = gfor_fndecl_math_ishftc4;
4827 break;
4828 case 8:
4829 tmp = gfor_fndecl_math_ishftc8;
4830 break;
920e54ef 4831 case 16:
4832 tmp = gfor_fndecl_math_ishftc16;
4833 break;
4ee9c684 4834 default:
22d678e8 4835 gcc_unreachable ();
4ee9c684 4836 }
389dd41b 4837 se->expr = build_call_expr_loc (input_location,
15da0ca7 4838 tmp, 3, args[0], args[1], args[2]);
4d66f715 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
4ee9c684 4844 return;
4845 }
5ddb0172 4846 type = TREE_TYPE (args[0]);
4ee9c684 4847
15da0ca7 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
4ee9c684 4852 /* Rotate left if positive. */
6f5c9335 4853 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
4ee9c684 4854
4855 /* Rotate right if negative. */
6f5c9335 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);
4ee9c684 4859
5ddb0172 4860 zero = build_int_cst (TREE_TYPE (args[1]), 0);
6f5c9335 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);
4ee9c684 4864
4865 /* Do nothing if shift == 0. */
6f5c9335 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);
4ee9c684 4870}
4871
4bfb5282 4872
0b820f43 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. */
411ee1e5 4882
0b820f43 4883static void
4884gfc_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;
70eb4f1a 4893 tree func;
4894 int s, argsize;
0b820f43 4895
4896 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
70eb4f1a 4897 argsize = TYPE_PRECISION (TREE_TYPE (arg));
0b820f43 4898
4899 /* Which variant of __builtin_clz* should we call? */
70eb4f1a 4900 if (argsize <= INT_TYPE_SIZE)
4901 {
4902 arg_type = unsigned_type_node;
b9a16870 4903 func = builtin_decl_explicit (BUILT_IN_CLZ);
70eb4f1a 4904 }
4905 else if (argsize <= LONG_TYPE_SIZE)
4906 {
4907 arg_type = long_unsigned_type_node;
b9a16870 4908 func = builtin_decl_explicit (BUILT_IN_CLZL);
70eb4f1a 4909 }
4910 else if (argsize <= LONG_LONG_TYPE_SIZE)
4911 {
4912 arg_type = long_long_unsigned_type_node;
b9a16870 4913 func = builtin_decl_explicit (BUILT_IN_CLZLL);
70eb4f1a 4914 }
4915 else
4916 {
4bfb5282 4917 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
70eb4f1a 4918 arg_type = gfc_build_uint_type (argsize);
4bfb5282 4919 func = NULL_TREE;
0b820f43 4920 }
4921
70eb4f1a 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
0b820f43 4924 function. But the return type is of the default INTEGER kind. */
70eb4f1a 4925 arg = fold_convert (gfc_build_uint_type (argsize), arg);
0b820f43 4926 arg = fold_convert (arg_type, arg);
4bfb5282 4927 arg = gfc_evaluate_now (arg, &se->pre);
0b820f43 4928 result_type = gfc_get_int_type (gfc_default_integer_kind);
4929
4930 /* Compute LEADZ for the case i .ne. 0. */
4bfb5282 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:
411ee1e5 4944
4bfb5282 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);
4bfb5282 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). */
b9a16870 4952 tree ullsize, ullmax, tmp1, tmp2, btmp;
4bfb5282 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);
b9a16870 4970 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4bfb5282 4971 tmp1 = fold_convert (result_type,
b9a16870 4972 build_call_expr_loc (input_location, btmp, 1, tmp1));
4bfb5282 4973
4974 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
b9a16870 4975 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4bfb5282 4976 tmp2 = fold_convert (result_type,
b9a16870 4977 build_call_expr_loc (input_location, btmp, 1, tmp2));
4bfb5282 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 }
0b820f43 4984
4985 /* Build BIT_SIZE. */
70eb4f1a 4986 bit_size = build_int_cst (result_type, argsize);
0b820f43 4987
6f5c9335 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);
0b820f43 4992}
4993
4bfb5282 4994
0b820f43 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. */
411ee1e5 5000
0b820f43 5001static void
5002gfc_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;
70eb4f1a 5010 tree func;
5011 int argsize;
0b820f43 5012
5013 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
70eb4f1a 5014 argsize = TYPE_PRECISION (TREE_TYPE (arg));
0b820f43 5015
70eb4f1a 5016 /* Which variant of __builtin_ctz* should we call? */
5017 if (argsize <= INT_TYPE_SIZE)
5018 {
5019 arg_type = unsigned_type_node;
b9a16870 5020 func = builtin_decl_explicit (BUILT_IN_CTZ);
70eb4f1a 5021 }
5022 else if (argsize <= LONG_TYPE_SIZE)
5023 {
5024 arg_type = long_unsigned_type_node;
b9a16870 5025 func = builtin_decl_explicit (BUILT_IN_CTZL);
70eb4f1a 5026 }
5027 else if (argsize <= LONG_LONG_TYPE_SIZE)
5028 {
5029 arg_type = long_long_unsigned_type_node;
b9a16870 5030 func = builtin_decl_explicit (BUILT_IN_CTZLL);
70eb4f1a 5031 }
5032 else
5033 {
4bfb5282 5034 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
70eb4f1a 5035 arg_type = gfc_build_uint_type (argsize);
4bfb5282 5036 func = NULL_TREE;
0b820f43 5037 }
5038
70eb4f1a 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
0b820f43 5041 function. But the return type is of the default INTEGER kind. */
70eb4f1a 5042 arg = fold_convert (gfc_build_uint_type (argsize), arg);
0b820f43 5043 arg = fold_convert (arg_type, arg);
4bfb5282 5044 arg = gfc_evaluate_now (arg, &se->pre);
0b820f43 5045 result_type = gfc_get_int_type (gfc_default_integer_kind);
5046
5047 /* Compute TRAILZ for the case i .ne. 0. */
4bfb5282 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:
411ee1e5 5055
4bfb5282 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). */
b9a16870 5064 tree ullsize, ullmax, tmp1, tmp2, btmp;
4bfb5282 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);
b9a16870 5079 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
4bfb5282 5080 tmp1 = fold_convert (result_type,
b9a16870 5081 build_call_expr_loc (input_location, btmp, 1, tmp1));
4bfb5282 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);
b9a16870 5086 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
4bfb5282 5087 tmp2 = fold_convert (result_type,
b9a16870 5088 build_call_expr_loc (input_location, btmp, 1, tmp2));
4bfb5282 5089
5090 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
5091 cond, tmp1, tmp2);
5092 }
0b820f43 5093
5094 /* Build BIT_SIZE. */
70eb4f1a 5095 bit_size = build_int_cst (result_type, argsize);
0b820f43 5096
6f5c9335 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);
0b820f43 5101}
8572fdb4 5102
41cbc93c 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. */
411ee1e5 5106
41cbc93c 5107static void
5108gfc_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;
b9a16870 5124 func = builtin_decl_explicit (parity
5125 ? BUILT_IN_PARITY
5126 : BUILT_IN_POPCOUNT);
41cbc93c 5127 }
5128 else if (argsize <= LONG_TYPE_SIZE)
5129 {
5130 arg_type = long_unsigned_type_node;
b9a16870 5131 func = builtin_decl_explicit (parity
5132 ? BUILT_IN_PARITYL
5133 : BUILT_IN_POPCOUNTL);
41cbc93c 5134 }
5135 else if (argsize <= LONG_LONG_TYPE_SIZE)
5136 {
5137 arg_type = long_long_unsigned_type_node;
b9a16870 5138 func = builtin_decl_explicit (parity
5139 ? BUILT_IN_PARITYLL
5140 : BUILT_IN_POPCOUNTLL);
41cbc93c 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
b9a16870 5153 func = builtin_decl_explicit (parity
5154 ? BUILT_IN_PARITYLL
5155 : BUILT_IN_POPCOUNTLL);
41cbc93c 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
6f5c9335 5167 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
5168 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
41cbc93c 5169 call2 = build_call_expr_loc (input_location, func, 1,
5170 fold_convert (long_long_unsigned_type_node,
5171 arg2));
411ee1e5 5172
41cbc93c 5173 /* Combine the results. */
5174 if (parity)
6f5c9335 5175 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
5176 call1, call2);
41cbc93c 5177 else
6f5c9335 5178 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
5179 call1, call2);
41cbc93c 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
8572fdb4 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
5203static void
5204conv_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;
f1f41a6c 5212 vec<tree, va_gc> *append_args;
8572fdb4 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. */
008f96d8 5236 append_args = NULL;
8572fdb4 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);
f1f41a6c 5242 vec_alloc (append_args, 1);
5243 append_args->quick_push (dummy);
8572fdb4 5244 }
5245
5246 /* Build the call itself. */
4b36c1ce 5247 gcc_assert (!se->ignore_optional);
5248 sym = gfc_get_symbol_for_expr (expr, false);
64e93293 5249 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
5250 append_args);
a89260f1 5251 gfc_free_symbol (sym);
8572fdb4 5252}
5253
5254
4ee9c684 5255/* The length of a character string. */
5256static void
5257gfc_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
22d678e8 5266 gcc_assert (!se->ss);
4ee9c684 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:
35bf1214 5274 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
4ee9c684 5275 break;
5276
bcb27a87 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;
151af988 5281 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
bcb27a87 5282 break;
5283
926b9532 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
4ee9c684 5294 && (sym->result == sym))
926b9532 5295 decl = gfc_get_fake_result_decl (sym, 0);
5296
eeebe20b 5297 len = sym->ts.u.cl->backend_decl;
926b9532 5298 gcc_assert (len);
5299 break;
4ee9c684 5300 }
926b9532 5301
5302 /* Otherwise fall through. */
5303
5304 default:
5305 /* Anybody stupid enough to do this deserves inefficient code. */
926b9532 5306 gfc_init_se (&argse, se);
5d34a30f 5307 if (arg->rank == 0)
926b9532 5308 gfc_conv_expr (&argse, arg);
5309 else
5d34a30f 5310 gfc_conv_expr_descriptor (&argse, arg);
926b9532 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;
4ee9c684 5314 break;
5315 }
5316 se->expr = convert (type, len);
5317}
5318
5319/* The length of a character string not including trailing blanks. */
5320static void
5321gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
5322{
40b806de 5323 int kind = expr->value.function.actual->expr->ts.kind;
5324 tree args[2], type, fndecl;
4ee9c684 5325
5ddb0172 5326 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4ee9c684 5327 type = gfc_typenode_for_spec (&expr->ts);
40b806de 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
389dd41b 5336 se->expr = build_call_expr_loc (input_location,
5337 fndecl, 2, args[0], args[1]);
4ee9c684 5338 se->expr = convert (type, se->expr);
5339}
5340
5341
5342/* Returns the starting position of a substring within a string. */
5343
5344static void
7fe55cc9 5345gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
5346 tree function)
4ee9c684 5347{
2eb4481b 5348 tree logical4_type_node = gfc_get_logical_type (4);
4ee9c684 5349 tree type;
5ddb0172 5350 tree fndecl;
5351 tree *args;
5352 unsigned int num_args;
4ee9c684 5353
86b32f71 5354 args = XALLOCAVEC (tree, 5);
5ddb0172 5355
24f1d2c4 5356 /* Get number of arguments; characters count double due to the
69b1505f 5357 string length argument. Kind= is not passed to the library
24f1d2c4 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);
4ee9c684 5365 type = gfc_typenode_for_spec (&expr->ts);
5ddb0172 5366
5367 if (num_args == 4)
5368 args[4] = build_int_cst (logical4_type_node, 0);
4ee9c684 5369 else
7fe55cc9 5370 args[4] = convert (logical4_type_node, args[4]);
4ee9c684 5371
0e49e441 5372 fndecl = build_addr (function);
389dd41b 5373 se->expr = build_call_array_loc (input_location,
5374 TREE_TYPE (TREE_TYPE (function)), fndecl,
7fe55cc9 5375 5, args);
4ee9c684 5376 se->expr = convert (type, se->expr);
5ddb0172 5377
4ee9c684 5378}
5379
5380/* The ascii value for a single character. */
5381static void
5382gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
5383{
ec9fd7b7 5384 tree args[3], type, pchartype;
5ac6468c 5385 int nargs;
4ee9c684 5386
5ac6468c 5387 nargs = gfc_intrinsic_argument_list_length (expr);
5388 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
5ddb0172 5389 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
40b806de 5390 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
6f5c9335 5391 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
4ee9c684 5392 type = gfc_typenode_for_spec (&expr->ts);
5393
389dd41b 5394 se->expr = build_fold_indirect_ref_loc (input_location,
5395 args[1]);
4ee9c684 5396 se->expr = convert (type, se->expr);
5397}
5398
5399
4e549567 5400/* Intrinsic ISNAN calls __builtin_isnan. */
5401
5402static void
5403gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
5404{
5405 tree arg;
5406
5407 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
389dd41b 5408 se->expr = build_call_expr_loc (input_location,
b9a16870 5409 builtin_decl_explicit (BUILT_IN_ISNAN),
5410 1, arg);
0a8db768 5411 STRIP_TYPE_NOPS (se->expr);
4e549567 5412 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
5413}
5414
52ed1096 5415
5416/* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
5417 their argument against a constant integer value. */
5418
5419static void
5420gfc_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);
6f5c9335 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));
52ed1096 5428}
5429
5430
5431
4ee9c684 5432/* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
5433
5434static void
5435gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
5436{
4ee9c684 5437 tree tsource;
5438 tree fsource;
5439 tree mask;
5440 tree type;
f24d382c 5441 tree len, len2;
5ddb0172 5442 tree *args;
5443 unsigned int num_args;
5444
5445 num_args = gfc_intrinsic_argument_list_length (expr);
86b32f71 5446 args = XALLOCAVEC (tree, num_args);
4ee9c684 5447
5ddb0172 5448 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
1e812509 5449 if (expr->ts.type != BT_CHARACTER)
5450 {
5ddb0172 5451 tsource = args[0];
5452 fsource = args[1];
5453 mask = args[2];
1e812509 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. */
5ddb0172 5460 len = args[0];
5461 tsource = args[1];
f24d382c 5462 len2 = args[2];
5ddb0172 5463 fsource = args[3];
5464 mask = args[4];
1e812509 5465
9c5786bd 5466 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
5467 &se->pre);
1e812509 5468 se->string_length = len;
5469 }
4ee9c684 5470 type = TREE_TYPE (tsource);
6f5c9335 5471 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
5472 fold_convert (type, fsource));
4ee9c684 5473}
5474
5475
f004c7aa 5476/* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
5477
5478static void
5479gfc_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
5502static void
5503gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
5504{
5505 tree arg, allones, type, utype, res, cond, bitsize;
5506 int i;
411ee1e5 5507
f004c7aa 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
1d8a0522 5554/* FRACTION (s) is translated into:
5555 isfinite (s) ? frexp (s, &dummy_int) : NaN */
34e106da 5556static void
5557gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
5558{
1d8a0522 5559 tree arg, type, tmp, res, frexp, cond;
34e106da 5560
808656b4 5561 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
34e106da 5562
5563 type = gfc_typenode_for_spec (&expr->ts);
5564 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
1d8a0522 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
34e106da 5571 tmp = gfc_create_var (integer_type_node, NULL);
1d8a0522 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, ""));
34e106da 5579}
5580
5581
5582/* NEAREST (s, dir) is translated into
4792ff6e 5583 tmp = copysign (HUGE_VAL, dir);
34e106da 5584 return nextafter (s, tmp);
5585 */
5586static void
5587gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
5588{
a80ae91c 5589 tree args[2], type, tmp, nextafter, copysign, huge_val;
34e106da 5590
808656b4 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);
34e106da 5593
5594 type = gfc_typenode_for_spec (&expr->ts);
5595 gfc_conv_intrinsic_function_args (se, expr, args, 2);
729e6db2 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,
a80ae91c 5599 fold_convert (type, args[1]));
5600 se->expr = build_call_expr_loc (input_location, nextafter, 2,
5601 fold_convert (type, args[0]), tmp);
34e106da 5602 se->expr = fold_convert (type, se->expr);
5603}
5604
5605
5606/* SPACING (s) is translated into
5607 int e;
1d8a0522 5608 if (!isfinite (s))
5609 res = NaN;
5610 else if (s == 0)
34e106da 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
5625static void
5626gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
5627{
5628 tree arg, type, prec, emin, tiny, res, e;
1d8a0522 5629 tree cond, nan, tmp, frexp, scalbn;
a80ae91c 5630 int k;
34e106da 5631 stmtblock_t block;
5632
5633 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
35bf1214 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);
2b6bc4f2 5636 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
34e106da 5637
808656b4 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);
34e106da 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);
a80ae91c 5651 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
5652 gfc_build_addr_expr (NULL_TREE, e));
34e106da 5653 gfc_add_expr_to_block (&block, tmp);
5654
6f5c9335 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));
34e106da 5659
a80ae91c 5660 tmp = build_call_expr_loc (input_location, scalbn, 2,
34e106da 5661 build_real_from_int_cst (type, integer_one_node), e);
75a70cf9 5662 gfc_add_modify (&block, res, tmp);
34e106da 5663
1d8a0522 5664 /* Finish by building the IF statement for value zero. */
6f5c9335 5665 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
5666 build_real_from_int_cst (type, integer_zero_node));
34e106da 5667 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
5668 gfc_finish_block (&block));
5669
1d8a0522 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
34e106da 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);
1d8a0522 5686 if (isfinite (x))
34e106da 5687 {
1d8a0522 5688 if (x != 0)
5689 {
5690 frexp (s, &e);
5691 x = scalbn (x, precision - e);
5692 }
34e106da 5693 }
1d8a0522 5694 else
5695 x = NaN;
34e106da 5696 return x;
5697
5698 where precision is gfc_real_kinds[k].digits. */
5699
5700static void
5701gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
5702{
1d8a0522 5703 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
a80ae91c 5704 int prec, k;
34e106da 5705 stmtblock_t block;
5706
5707 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
5708 prec = gfc_real_kinds[k].digits;
a80ae91c 5709
808656b4 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);
34e106da 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);
75a70cf9 5720 gfc_add_modify (&se->pre, x,
a80ae91c 5721 build_call_expr_loc (input_location, fabs, 1, arg));
34e106da 5722
5723
5724 gfc_start_block (&block);
a80ae91c 5725 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
5726 gfc_build_addr_expr (NULL_TREE, e));
34e106da 5727 gfc_add_expr_to_block (&block, tmp);
5728
6f5c9335 5729 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
35bf1214 5730 build_int_cst (integer_type_node, prec), e);
a80ae91c 5731 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
75a70cf9 5732 gfc_add_modify (&block, x, tmp);
34e106da 5733 stmt = gfc_finish_block (&block);
5734
1d8a0522 5735 /* if (x != 0) */
6f5c9335 5736 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, x,
5737 build_real_from_int_cst (type, integer_zero_node));
e60a6f7b 5738 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
34e106da 5739
1d8a0522 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);
34e106da 5748 se->expr = fold_convert (type, x);
5749}
5750
5751
5752/* SCALE (s, i) is translated into scalbn (s, i). */
5753static void
5754gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
5755{
a80ae91c 5756 tree args[2], type, scalbn;
34e106da 5757
808656b4 5758 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
34e106da 5759
5760 type = gfc_typenode_for_spec (&expr->ts);
5761 gfc_conv_intrinsic_function_args (se, expr, args, 2);
a80ae91c 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]));
34e106da 5765 se->expr = fold_convert (type, se->expr);
5766}
5767
5768
5769/* SET_EXPONENT (s, i) is translated into
1d8a0522 5770 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
34e106da 5771static void
5772gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
5773{
1d8a0522 5774 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
34e106da 5775
808656b4 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);
34e106da 5778
5779 type = gfc_typenode_for_spec (&expr->ts);
5780 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1d8a0522 5781 args[0] = gfc_evaluate_now (args[0], &se->pre);
34e106da 5782
5783 tmp = gfc_create_var (integer_type_node, NULL);
a80ae91c 5784 tmp = build_call_expr_loc (input_location, frexp, 2,
5785 fold_convert (type, args[0]),
5786 gfc_build_addr_expr (NULL_TREE, tmp));
1d8a0522 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);
34e106da 5799}
5800
5801
4ee9c684 5802static void
5803gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
5804{
5805 gfc_actual_arglist *actual;
dd145961 5806 tree arg1;
4ee9c684 5807 tree type;
dd145961 5808 tree fncall0;
5809 tree fncall1;
4ee9c684 5810 gfc_se argse;
4ee9c684 5811
5812 gfc_init_se (&argse, NULL);
5813 actual = expr->value.function.actual;
5814
fd23cc08 5815 if (actual->expr->ts.type == BT_CLASS)
5816 gfc_add_class_array_ref (actual->expr);
5817
4ee9c684 5818 argse.want_pointer = 1;
e6a3cabf 5819 argse.data_not_needed = 1;
5d34a30f 5820 gfc_conv_expr_descriptor (&argse, actual->expr);
4ee9c684 5821 gfc_add_block_to_block (&se->pre, &argse.pre);
5822 gfc_add_block_to_block (&se->post, &argse.post);
dd145961 5823 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
5824
5825 /* Build the call to size0. */
389dd41b 5826 fncall0 = build_call_expr_loc (input_location,
5827 gfor_fndecl_size0, 1, arg1);
4ee9c684 5828
5829 actual = actual->next;
dd145961 5830
4ee9c684 5831 if (actual->expr)
5832 {
5833 gfc_init_se (&argse, NULL);
dd145961 5834 gfc_conv_expr_type (&argse, actual->expr,
5835 gfc_array_index_type);
4ee9c684 5836 gfc_add_block_to_block (&se->pre, &argse.pre);
dd145961 5837
dd145961 5838 /* Unusually, for an intrinsic, size does not exclude
411ee1e5 5839 an optional arg2, so we must test for it. */
dd145961 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;
43021eb9 5845 /* Build the call to size1. */
389dd41b 5846 fncall1 = build_call_expr_loc (input_location,
5847 gfor_fndecl_size1, 2,
43021eb9 5848 arg1, argse.expr);
5849
75367391 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);
6f5c9335 5855 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5856 argse.expr, null_pointer_node);
dd145961 5857 tmp = gfc_evaluate_now (tmp, &se->pre);
6f5c9335 5858 se->expr = fold_build3_loc (input_location, COND_EXPR,
5859 pvoid_type_node, tmp, fncall1, fncall0);
dd145961 5860 }
5861 else
43021eb9 5862 {
5863 se->expr = NULL_TREE;
6f5c9335 5864 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
5865 gfc_array_index_type,
5866 argse.expr, gfc_index_one_node);
43021eb9 5867 }
5868 }
5869 else if (expr->value.function.actual->expr->rank == 1)
5870 {
4b6af10a 5871 argse.expr = gfc_index_zero_node;
43021eb9 5872 se->expr = NULL_TREE;
4ee9c684 5873 }
5874 else
dd145961 5875 se->expr = fncall0;
4ee9c684 5876
43021eb9 5877 if (se->expr == NULL_TREE)
5878 {
5879 tree ubound, lbound;
5880
389dd41b 5881 arg1 = build_fold_indirect_ref_loc (input_location,
5882 arg1);
6b1a9af3 5883 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
5884 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
6f5c9335 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);
43021eb9 5893 }
5894
4ee9c684 5895 type = gfc_typenode_for_spec (&expr->ts);
5896 se->expr = convert (type, se->expr);
5897}
5898
5899
329f13ad 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
13d7216c 5904tree
329f13ad 5905size_of_string_in_bytes (int kind, tree string_length)
5906{
5907 tree bytesize;
5908 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
411ee1e5 5909
329f13ad 5910 bytesize = build_int_cst (gfc_array_index_type,
5911 gfc_character_kinds[i].bit_size / 8);
5912
6f5c9335 5913 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5914 bytesize,
5915 fold_convert (gfc_array_index_type, string_length));
329f13ad 5916}
5917
5918
1318f16c 5919static void
5920gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
5921{
5922 gfc_expr *arg;
1318f16c 5923 gfc_se argse;
1318f16c 5924 tree source_bytes;
1318f16c 5925 tree tmp;
5926 tree lower;
5927 tree upper;
7bd6248b 5928 tree byte_size;
1318f16c 5929 int n;
5930
1318f16c 5931 gfc_init_se (&argse, NULL);
7bd6248b 5932 arg = expr->value.function.actual->expr;
1318f16c 5933
7bd6248b 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
384d1ed7 5942 the size from the descriptor. */
7bd6248b 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 {
10c26e1e 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. */
c6793847 5963 if (arg->rank < 0
5964 || (arg->rank > 0 && !VAR_P (argse.expr)
10c26e1e 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)))))
535b0484 5969 byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
c6793847 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));
7bd6248b 5975 else
535b0484 5976 byte_size = gfc_class_vtab_size_get (argse.expr);
7bd6248b 5977 }
5978 else
1318f16c 5979 {
1318f16c 5980 if (arg->ts.type == BT_CHARACTER)
7bd6248b 5981 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
1318f16c 5982 else
7bd6248b 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 }
1318f16c 5992 }
7bd6248b 5993
5994 if (arg->rank == 0)
5995 se->expr = byte_size;
1318f16c 5996 else
5997 {
189ffda5 5998 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
7bd6248b 5999 gfc_add_modify (&argse.pre, source_bytes, byte_size);
1318f16c 6000
7bd6248b 6001 if (arg->rank == -1)
1318f16c 6002 {
7bd6248b 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);
6f5c9335 6032 tmp = fold_build2_loc (input_location, MULT_EXPR,
6033 gfc_array_index_type, tmp, source_bytes);
7bd6248b 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 }
1318f16c 6064 }
189ffda5 6065 se->expr = source_bytes;
1318f16c 6066 }
6067
6068 gfc_add_block_to_block (&se->pre, &argse.pre);
1318f16c 6069}
6070
6071
95bf00d5 6072static void
6073gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
6074{
6075 gfc_expr *arg;
b3453f4d 6076 gfc_se argse;
95bf00d5 6077 tree type, result_type, tmp;
6078
6079 arg = expr->value.function.actual->expr;
411ee1e5 6080
95bf00d5 6081 gfc_init_se (&argse, NULL);
95bf00d5 6082 result_type = gfc_get_int_type (expr->ts.kind);
6083
5d34a30f 6084 if (arg->rank == 0)
95bf00d5 6085 {
6086 if (arg->ts.type == BT_CLASS)
7bd6248b 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 }
95bf00d5 6094
6095 gfc_conv_expr_reference (&argse, arg);
411ee1e5 6096 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
95bf00d5 6097 argse.expr));
6098 }
6099 else
6100 {
6101 argse.want_pointer = 0;
5d34a30f 6102 gfc_conv_expr_descriptor (&argse, arg);
7bd6248b 6103 if (arg->ts.type == BT_CLASS)
6104 {
c6793847 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));
7bd6248b 6110 tmp = fold_convert (result_type, tmp);
6111 goto done;
6112 }
95bf00d5 6113 type = gfc_get_element_type (TREE_TYPE (argse.expr));
6114 }
411ee1e5 6115
95bf00d5 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
411ee1e5 6120 tmp = size_in_bytes (type);
b3453f4d 6121 tmp = fold_convert (result_type, tmp);
95bf00d5 6122
6123done:
6f5c9335 6124 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
b3453f4d 6125 build_int_cst (result_type, BITS_PER_UNIT));
95bf00d5 6126 gfc_add_block_to_block (&se->pre, &argse.pre);
6127}
6128
6129
4ee9c684 6130/* Intrinsic string comparison functions. */
6131
1318f16c 6132static void
d62fb8de 6133gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
4ee9c684 6134{
5ddb0172 6135 tree args[4];
27781b86 6136
5ddb0172 6137 gfc_conv_intrinsic_function_args (se, expr, args, 4);
4ee9c684 6138
40b806de 6139 se->expr
6140 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
a313dc3a 6141 expr->value.function.actual->expr->ts.kind,
6142 op);
6f5c9335 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));
4ee9c684 6146}
6147
6148/* Generate a call to the adjustl/adjustr library function. */
6149static void
6150gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
6151{
5ddb0172 6152 tree args[3];
4ee9c684 6153 tree len;
6154 tree type;
6155 tree var;
6156 tree tmp;
6157
5ddb0172 6158 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
6159 len = args[1];
4ee9c684 6160
5ddb0172 6161 type = TREE_TYPE (args[2]);
4ee9c684 6162 var = gfc_conv_string_tmp (se, type, len);
5ddb0172 6163 args[0] = var;
4ee9c684 6164
389dd41b 6165 tmp = build_call_expr_loc (input_location,
6166 fndecl, 3, args[0], args[1], args[2]);
4ee9c684 6167 gfc_add_expr_to_block (&se->pre, tmp);
6168 se->expr = var;
6169 se->string_length = len;
6170}
6171
6172
891756c7 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(:)),
4eaa93a5 6187 sizeof (DEST(0) * SIZE). */
4eaa93a5 6188static void
891756c7 6189gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
4eaa93a5 6190{
6191 tree tmp;
891756c7 6192 tree tmpdecl;
6193 tree ptr;
4eaa93a5 6194 tree extent;
6195 tree source;
8957d6ed 6196 tree source_type;
4eaa93a5 6197 tree source_bytes;
8957d6ed 6198 tree mold_type;
4eaa93a5 6199 tree dest_word_len;
6200 tree size_words;
6201 tree size_bytes;
6202 tree upper;
6203 tree lower;
4eaa93a5 6204 tree stmt;
6205 gfc_actual_arglist *arg;
6206 gfc_se argse;
ea686fef 6207 gfc_array_info *info;
4eaa93a5 6208 stmtblock_t block;
6209 int n;
891756c7 6210 bool scalar_mold;
50a0a4ff 6211 gfc_expr *source_expr, *mold_expr;
4eaa93a5 6212
891756c7 6213 info = NULL;
6214 if (se->loop)
b8f38347 6215 info = &se->ss->info->data.array;
4eaa93a5 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;
50a0a4ff 6221 source_expr = arg->expr;
891756c7 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
4eaa93a5 6233 gfc_init_se (&argse, NULL);
4eaa93a5 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. */
5d34a30f 6238 if (arg->expr->rank == 0)
4eaa93a5 6239 {
6240 gfc_conv_expr_reference (&argse, arg->expr);
50a0a4ff 6241 if (arg->expr->ts.type == BT_CLASS)
6242 source = gfc_class_data_get (argse.expr);
6243 else
6244 source = argse.expr;
8957d6ed 6245
4eaa93a5 6246 /* Obtain the source word length. */
50a0a4ff 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:
535b0484 6254 tmp = gfc_class_vtab_size_get (argse.expr);
50a0a4ff 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 }
4eaa93a5 6263 }
6264 else
6265 {
4eaa93a5 6266 argse.want_pointer = 0;
5d34a30f 6267 gfc_conv_expr_descriptor (&argse, arg->expr);
4eaa93a5 6268 source = gfc_conv_descriptor_data_get (argse.expr);
8957d6ed 6269 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
4eaa93a5 6270
11972221 6271 /* Repack the source if not simply contiguous. */
38bb9313 6272 if (!gfc_is_simply_contiguous (arg->expr, false, true))
4eaa93a5 6273 {
86f2ad37 6274 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
92f4d1c4 6275
8290d53f 6276 if (warn_array_temporaries)
4166acc7 6277 gfc_warning (OPT_Warray_temporaries,
6278 "Creating array temporary at %L", &expr->where);
92f4d1c4 6279
389dd41b 6280 source = build_call_expr_loc (input_location,
6281 gfor_fndecl_in_pack, 1, tmp);
4eaa93a5 6282 source = gfc_evaluate_now (source, &argse.pre);
6283
6284 /* Free the temporary. */
6285 gfc_start_block (&block);
1d5e34dd 6286 tmp = gfc_call_free (source);
4eaa93a5 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);
6f5c9335 6293 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6294 source, tmp);
e60a6f7b 6295 tmp = build3_v (COND_EXPR, tmp, stmt,
6296 build_empty_stmt (input_location));
4eaa93a5 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. */
8957d6ed 6304 if (arg->expr->ts.type == BT_CHARACTER)
329f13ad 6305 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
6306 argse.string_length);
8957d6ed 6307 else
6308 tmp = fold_convert (gfc_array_index_type,
411ee1e5 6309 size_in_bytes (source_type));
4eaa93a5 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];
75a70cf9 6317 gfc_add_modify (&argse.pre, source_bytes, tmp);
6b1a9af3 6318 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
6319 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
6f5c9335 6320 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6321 gfc_array_index_type, upper, lower);
75a70cf9 6322 gfc_add_modify (&argse.pre, extent, tmp);
6f5c9335 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);
4eaa93a5 6328 }
6329 }
6330
75a70cf9 6331 gfc_add_modify (&argse.pre, source_bytes, tmp);
4eaa93a5 6332 gfc_add_block_to_block (&se->pre, &argse.pre);
6333 gfc_add_block_to_block (&se->post, &argse.post);
6334
8957d6ed 6335 /* Now convert MOLD. The outputs are:
6336 mold_type = the TREE type of MOLD
4eaa93a5 6337 dest_word_len = destination word length in bytes. */
6338 arg = arg->next;
50a0a4ff 6339 mold_expr = arg->expr;
4eaa93a5 6340
6341 gfc_init_se (&argse, NULL);
4eaa93a5 6342
891756c7 6343 scalar_mold = arg->expr->rank == 0;
6344
5d34a30f 6345 if (arg->expr->rank == 0)
4eaa93a5 6346 {
6347 gfc_conv_expr_reference (&argse, arg->expr);
389dd41b 6348 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
50a0a4ff 6349 argse.expr));
4eaa93a5 6350 }
6351 else
6352 {
6353 gfc_init_se (&argse, NULL);
6354 argse.want_pointer = 0;
5d34a30f 6355 gfc_conv_expr_descriptor (&argse, arg->expr);
8957d6ed 6356 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
4eaa93a5 6357 }
6358
891756c7 6359 gfc_add_block_to_block (&se->pre, &argse.pre);
6360 gfc_add_block_to_block (&se->post, &argse.post);
6361
95b7221a 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
50a0a4ff 6370 /* Obtain the destination word length. */
6371 switch (arg->expr->ts.type)
8957d6ed 6372 {
50a0a4ff 6373 case BT_CHARACTER:
329f13ad 6374 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
8957d6ed 6375 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
50a0a4ff 6376 break;
6377 case BT_CLASS:
535b0484 6378 tmp = gfc_class_vtab_size_get (argse.expr);
50a0a4ff 6379 break;
6380 default:
6381 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
6382 break;
8957d6ed 6383 }
4eaa93a5 6384 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
75a70cf9 6385 gfc_add_modify (&se->pre, dest_word_len, tmp);
4eaa93a5 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,
389dd41b 6396 build_fold_indirect_ref_loc (input_location,
6397 argse.expr));
4eaa93a5 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
891756c7 6404 /* Separate array and scalar results. */
6405 if (scalar_mold && tmp == NULL_TREE)
6406 goto scalar_transfer;
6407
4eaa93a5 6408 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
6409 if (tmp != NULL_TREE)
6f5c9335 6410 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6411 tmp, dest_word_len);
4eaa93a5 6412 else
6413 tmp = source_bytes;
6414
75a70cf9 6415 gfc_add_modify (&se->pre, size_bytes, tmp);
6416 gfc_add_modify (&se->pre, size_words,
6f5c9335 6417 fold_build2_loc (input_location, CEIL_DIV_EXPR,
6418 gfc_array_index_type,
6419 size_bytes, dest_word_len));
4eaa93a5 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 {
6f5c9335 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,
1318f16c 6433 tmp, size_words);
75a70cf9 6434 gfc_add_modify (&se->pre, size_words, tmp);
6435 gfc_add_modify (&se->pre, size_bytes,
6f5c9335 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);
4eaa93a5 6443 }
6444 else
6445 {
6f5c9335 6446 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6447 size_words, gfc_index_one_node);
4eaa93a5 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
891756c7 6454 data field. */
fc09773a 6455 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
6456 NULL_TREE, false, true, false, &expr->where);
8957d6ed 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);
4eaa93a5 6461
7544787a 6462 /* Use memcpy to do the transfer. */
e740e6a6 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)));
7544787a 6473 gfc_add_expr_to_block (&se->pre, tmp);
6474
4eaa93a5 6475 se->expr = info->descriptor;
6476 if (expr->ts.type == BT_CHARACTER)
1557756e 6477 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
4eaa93a5 6478
891756c7 6479 return;
4eaa93a5 6480
891756c7 6481/* Deal with scalar results. */
6482scalar_transfer:
6f5c9335 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);
4ee9c684 6487
891756c7 6488 if (expr->ts.type == BT_CHARACTER)
6489 {
5e75682e 6490 tree direct, indirect, free;
4ee9c684 6491
891756c7 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");
4ee9c684 6495
891756c7 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);
3b51aab9 6501
891756c7 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));
389dd41b 6509 tmp = build_call_expr_loc (input_location,
b9a16870 6510 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
891756c7 6511 fold_convert (pvoid_type_node, tmpdecl),
6512 fold_convert (pvoid_type_node, ptr),
e740e6a6 6513 fold_convert (size_type_node, extent));
891756c7 6514 gfc_add_expr_to_block (&block, tmp);
6515 indirect = gfc_finish_block (&block);
6516
6517 /* Wrap it up with the condition. */
6f5c9335 6518 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
6519 dest_word_len, source_bytes);
891756c7 6520 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
6521 gfc_add_expr_to_block (&se->pre, tmp);
6522
5e75682e 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
891756c7 6530 se->expr = tmpdecl;
7632f39a 6531 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
4ee9c684 6532 }
6533 else
6534 {
891756c7 6535 tmpdecl = gfc_create_var (mold_type, "transfer");
6536
6537 ptr = convert (build_pointer_type (mold_type), source);
3b51aab9 6538
50a0a4ff 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
3b51aab9 6548 /* Use memcpy to do the transfer. */
50a0a4ff 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
389dd41b 6554 tmp = build_call_expr_loc (input_location,
b9a16870 6555 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
c2f47e15 6556 fold_convert (pvoid_type_node, tmp),
6557 fold_convert (pvoid_type_node, ptr),
e740e6a6 6558 fold_convert (size_type_node, extent));
3b51aab9 6559 gfc_add_expr_to_block (&se->pre, tmp);
6560
50a0a4ff 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
3b51aab9 6573 se->expr = tmpdecl;
4ee9c684 6574 }
6575}
6576
6577
6578/* Generate code for the ALLOCATED intrinsic.
6579 Generate inline code that directly check the address of the argument. */
6580
6581static void
6582gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
6583{
6584 gfc_actual_arglist *arg1;
6585 gfc_se arg1se;
4ee9c684 6586 tree tmp;
6587
6588 gfc_init_se (&arg1se, NULL);
6589 arg1 = expr->value.function.actual;
fd23cc08 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
5d34a30f 6602 if (arg1->expr->rank == 0)
eb67c215 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;
5d34a30f 6613 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
eb67c215 6614 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
6615 }
6616
6f5c9335 6617 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
6618 fold_convert (TREE_TYPE (tmp), null_pointer_node));
4ee9c684 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
6629static void
6630gfc_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;
d9963cc2 6638 tree nonzero_charlen;
6639 tree nonzero_arraylen;
5d34a30f 6640 gfc_ss *ss;
6641 bool scalar;
4ee9c684 6642
6643 gfc_init_se (&arg1se, NULL);
6644 gfc_init_se (&arg2se, NULL);
6645 arg1 = expr->value.function.actual;
6646 arg2 = arg1->next;
5d34a30f 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);
4ee9c684 6654
6655 if (!arg2->expr)
6656 {
6657 /* No optional target. */
5d34a30f 6658 if (scalar)
4ee9c684 6659 {
4b17ee64 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);
411ee1e5 6667 if (arg1->expr->ts.type == BT_CLASS)
6668 {
75246a04 6669 tmp2 = gfc_class_data_get (arg1se.expr);
411ee1e5 6670 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
6671 tmp2 = gfc_conv_descriptor_data_get (tmp2);
6672 }
75246a04 6673 else
6674 tmp2 = arg1se.expr;
4ee9c684 6675 }
6676 else
6677 {
6678 /* A pointer to an array. */
5d34a30f 6679 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
94be45c9 6680 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
4ee9c684 6681 }
98ac6651 6682 gfc_add_block_to_block (&se->pre, &arg1se.pre);
6683 gfc_add_block_to_block (&se->post, &arg1se.post);
6f5c9335 6684 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp2,
6685 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
4ee9c684 6686 se->expr = tmp;
6687 }
6688 else
6689 {
6690 /* An optional target. */
db6e5c08 6691 if (arg2->expr->ts.type == BT_CLASS)
607ae689 6692 gfc_add_data_component (arg2->expr);
e815d37d 6693
6694 nonzero_charlen = NULL_TREE;
6695 if (arg1->expr->ts.type == BT_CHARACTER)
6f5c9335 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);
5d34a30f 6700 if (scalar)
4ee9c684 6701 {
4b17ee64 6702 /* A pointer to a scalar. */
4b17ee64 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);
75246a04 6709 if (arg1->expr->ts.type == BT_CLASS)
6710 arg1se.expr = gfc_class_data_get (arg1se.expr);
4b17ee64 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);
98ac6651 6718 gfc_add_block_to_block (&se->pre, &arg1se.pre);
6719 gfc_add_block_to_block (&se->post, &arg1se.post);
814b1ca2 6720 gfc_add_block_to_block (&se->pre, &arg2se.pre);
6721 gfc_add_block_to_block (&se->post, &arg2se.post);
6f5c9335 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);
4ee9c684 6728 }
6729 else
6730 {
e815d37d 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);
f00f6dd6 6735 if (arg1->expr->rank == -1)
6736 {
edc4866f 6737 tmp = gfc_conv_descriptor_rank (arg1se.expr);
f00f6dd6 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);
6f5c9335 6744 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
6745 boolean_type_node, tmp,
6746 build_int_cst (TREE_TYPE (tmp), 0));
e815d37d 6747
4ee9c684 6748 /* A pointer to an array, call library function _gfor_associated. */
4ee9c684 6749 arg1se.want_pointer = 1;
5d34a30f 6750 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
e815d37d 6751
4ee9c684 6752 arg2se.want_pointer = 1;
5d34a30f 6753 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
4ee9c684 6754 gfc_add_block_to_block (&se->pre, &arg2se.pre);
6755 gfc_add_block_to_block (&se->post, &arg2se.post);
389dd41b 6756 se->expr = build_call_expr_loc (input_location,
6757 gfor_fndecl_associated, 2,
c1c66d1d 6758 arg1se.expr, arg2se.expr);
6759 se->expr = convert (boolean_type_node, se->expr);
6f5c9335 6760 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6761 boolean_type_node, se->expr,
6762 nonzero_arraylen);
4ee9c684 6763 }
e815d37d 6764
6765 /* If target is present zero character length pointers cannot
6766 be associated. */
6767 if (nonzero_charlen != NULL_TREE)
6f5c9335 6768 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6769 boolean_type_node,
6770 se->expr, nonzero_charlen);
e815d37d 6771 }
6772
4ee9c684 6773 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6774}
6775
6776
1de1b1a9 6777/* Generate code for the SAME_TYPE_AS intrinsic.
6778 Generate inline code that directly checks the vindices. */
6779
6780static void
6781gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
6782{
6783 gfc_expr *a, *b;
6784 gfc_se se1, se2;
6785 tree tmp;
a90fe829 6786 tree conda = NULL_TREE, condb = NULL_TREE;
1de1b1a9 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
a90fe829 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
1de1b1a9 6808 if (a->ts.type == BT_CLASS)
bdfbc762 6809 {
607ae689 6810 gfc_add_vptr_component (a);
6811 gfc_add_hash_component (a);
bdfbc762 6812 }
1de1b1a9 6813 else if (a->ts.type == BT_DERIVED)
126387b5 6814 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
6815 a->ts.u.derived->hash_value);
1de1b1a9 6816
6817 if (b->ts.type == BT_CLASS)
bdfbc762 6818 {
607ae689 6819 gfc_add_vptr_component (b);
6820 gfc_add_hash_component (b);
bdfbc762 6821 }
1de1b1a9 6822 else if (b->ts.type == BT_DERIVED)
126387b5 6823 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
6824 b->ts.u.derived->hash_value);
1de1b1a9 6825
6826 gfc_conv_expr (&se1, a);
6827 gfc_conv_expr (&se2, b);
6828
a90fe829 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
1de1b1a9 6841 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
6842}
6843
6844
59e2a584 6845/* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
6846
6847static void
6848gfc_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);
389dd41b 6853 se->expr = build_call_expr_loc (input_location,
6854 gfor_fndecl_sc_kind, 2, args[0], args[1]);
59e2a584 6855 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
6856}
6857
6858
4ee9c684 6859/* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
6860
6861static void
e2d2dbf9 6862gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
4ee9c684 6863{
e2d2dbf9 6864 tree arg, type;
4ee9c684 6865
5ddb0172 6866 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
e2d2dbf9 6867
6868 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
411ee1e5 6869 type = gfc_get_int_type (4);
86f2ad37 6870 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
e2d2dbf9 6871
6872 /* Convert it to the required type. */
6873 type = gfc_typenode_for_spec (&expr->ts);
389dd41b 6874 se->expr = build_call_expr_loc (input_location,
6875 gfor_fndecl_si_kind, 1, arg);
e2d2dbf9 6876 se->expr = fold_convert (type, se->expr);
4ee9c684 6877}
6878
e2d2dbf9 6879
5ce6c67e 6880/* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
4ee9c684 6881
6882static void
e2d2dbf9 6883gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
4ee9c684 6884{
6885 gfc_actual_arglist *actual;
414c3a2c 6886 tree type;
4ee9c684 6887 gfc_se argse;
f1f41a6c 6888 vec<tree, va_gc> *args = NULL;
4ee9c684 6889
4ee9c684 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
e2d2dbf9 6898 {
6899 gfc_typespec ts;
52179f31 6900 gfc_clear_ts (&ts);
6901
e2d2dbf9 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);
411ee1e5 6910 }
4ee9c684 6911
6912 gfc_add_block_to_block (&se->pre, &argse.pre);
6913 gfc_add_block_to_block (&se->post, &argse.post);
f1f41a6c 6914 vec_safe_push (args, argse.expr);
4ee9c684 6915 }
e2d2dbf9 6916
6917 /* Convert it to the required type. */
6918 type = gfc_typenode_for_spec (&expr->ts);
414c3a2c 6919 se->expr = build_call_expr_loc_vec (input_location,
6920 gfor_fndecl_sr_kind, args);
e2d2dbf9 6921 se->expr = fold_convert (type, se->expr);
4ee9c684 6922}
6923
6924
6925/* Generate code for TRIM (A) intrinsic function. */
6926
6927static void
6928gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
6929{
6930 tree var;
6931 tree len;
6932 tree addr;
6933 tree tmp;
4ee9c684 6934 tree cond;
5ddb0172 6935 tree fndecl;
40b806de 6936 tree function;
5ddb0172 6937 tree *args;
6938 unsigned int num_args;
4ee9c684 6939
5ddb0172 6940 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
86b32f71 6941 args = XALLOCAVEC (tree, num_args);
4ee9c684 6942
329f13ad 6943 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
4ee9c684 6944 addr = gfc_build_addr_expr (ppvoid_type_node, var);
185bc3c7 6945 len = gfc_create_var (gfc_charlen_type_node, "len");
4ee9c684 6946
5ddb0172 6947 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
86f2ad37 6948 args[0] = gfc_build_addr_expr (NULL_TREE, len);
5ddb0172 6949 args[1] = addr;
6bcf802b 6950
40b806de 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
0e49e441 6958 fndecl = build_addr (function);
389dd41b 6959 tmp = build_call_array_loc (input_location,
6960 TREE_TYPE (TREE_TYPE (function)), fndecl,
40b806de 6961 num_args, args);
4ee9c684 6962 gfc_add_expr_to_block (&se->pre, tmp);
6963
6964 /* Free the temporary afterwards, if necessary. */
6f5c9335 6965 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6966 len, build_int_cst (TREE_TYPE (len), 0));
9915365e 6967 tmp = gfc_call_free (var);
e60a6f7b 6968 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4ee9c684 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
6978static void
6979gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
6980{
5ddb0172 6981 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
f62816ef 6982 tree type, cond, tmp, count, exit_label, n, max, largest;
b44437b9 6983 tree size;
f62816ef 6984 stmtblock_t block, body;
6985 int i;
4ee9c684 6986
329f13ad 6987 /* We store in charsize the size of a character. */
b44437b9 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
f62816ef 6991 /* Get the arguments. */
5ddb0172 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);
f62816ef 6996 ncopies_type = TREE_TYPE (ncopies);
6997
6998 /* Check that NCOPIES is not negative. */
6f5c9335 6999 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, ncopies,
7000 build_int_cst (ncopies_type, 0));
da6ffc6d 7001 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
399aecc1 7002 "Argument NCOPIES of REPEAT intrinsic is negative "
517c89e5 7003 "(its value is %ld)",
399aecc1 7004 fold_convert (long_integer_type_node, ncopies));
bfe7d4b1 7005
f62816ef 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");
6f5c9335 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);
75a70cf9 7013 gfc_add_modify (&se->pre, n, tmp);
f62816ef 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);
6f5c9335 7022 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node,
7023 fold_convert (size_type_node, max), slen);
f62816ef 7024 largest = TYPE_PRECISION (size_type_node) > TYPE_PRECISION (ncopies_type)
7025 ? size_type_node : ncopies_type;
6f5c9335 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);
da6ffc6d 7033 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
399aecc1 7034 "Argument NCOPIES of REPEAT intrinsic is too large");
f62816ef 7035
bfe7d4b1 7036 /* Compute the destination length. */
6f5c9335 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));
eeebe20b 7040 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
f62816ef 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++)
b44437b9 7045 memmove (dest + (i * slen * size), src, slen*size); */
f62816ef 7046 gfc_start_block (&block);
7047 count = gfc_create_var (ncopies_type, "count");
75a70cf9 7048 gfc_add_modify (&block, count, build_int_cst (ncopies_type, 0));
f62816ef 7049 exit_label = gfc_build_label_decl (NULL_TREE);
7050
7051 /* Start the loop body. */
7052 gfc_start_block (&body);
4ee9c684 7053
f62816ef 7054 /* Exit the loop if count >= ncopies. */
6f5c9335 7055 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, count,
7056 ncopies);
f62816ef 7057 tmp = build1_v (GOTO_EXPR, exit_label);
7058 TREE_USED (exit_label) = 1;
6f5c9335 7059 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
7060 build_empty_stmt (input_location));
f62816ef 7061 gfc_add_expr_to_block (&body, tmp);
7062
b44437b9 7063 /* Call memmove (dest + (i*slen*size), src, slen*size). */
6f5c9335 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));
2cc66f2a 7069 tmp = fold_build_pointer_plus_loc (input_location,
7070 fold_convert (pvoid_type_node, dest), tmp);
389dd41b 7071 tmp = build_call_expr_loc (input_location,
b9a16870 7072 builtin_decl_explicit (BUILT_IN_MEMMOVE),
7073 3, tmp, src,
6f5c9335 7074 fold_build2_loc (input_location, MULT_EXPR,
7075 size_type_node, slen,
7076 fold_convert (size_type_node,
7077 size)));
f62816ef 7078 gfc_add_expr_to_block (&body, tmp);
7079
7080 /* Increment count. */
6f5c9335 7081 tmp = fold_build2_loc (input_location, PLUS_EXPR, ncopies_type,
7082 count, build_int_cst (TREE_TYPE (count), 1));
75a70cf9 7083 gfc_add_modify (&body, count, tmp);
f62816ef 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);
4ee9c684 7095 gfc_add_expr_to_block (&se->pre, tmp);
7096
f62816ef 7097 /* Set the result value. */
7098 se->expr = dest;
7099 se->string_length = dlen;
4ee9c684 7100}
7101
7102
f0f2da44 7103/* Generate code for the IARGC intrinsic. */
9b057c29 7104
7105static void
f0f2da44 7106gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
9b057c29 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;
389dd41b 7114 tmp = build_call_expr_loc (input_location,
7115 fndecl, 0);
9b057c29 7116
7117 /* Convert it to the required type. */
7118 type = gfc_typenode_for_spec (&expr->ts);
7119 tmp = fold_convert (type, tmp);
7120
9b057c29 7121 se->expr = tmp;
7122}
7123
b549d2a5 7124
7125/* The loc intrinsic returns the address of its argument as
7126 gfc_index_integer_kind integer. */
7127
7128static void
fe537a55 7129gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
b549d2a5 7130{
7131 tree temp_var;
7132 gfc_expr *arg_expr;
b549d2a5 7133
7134 gcc_assert (!se->ss);
7135
7136 arg_expr = expr->value.function.actual->expr;
5d34a30f 7137 if (arg_expr->rank == 0)
c6793847 7138 {
7139 if (arg_expr->ts.type == BT_CLASS)
7140 gfc_add_component_ref (arg_expr, "_data");
7141 gfc_conv_expr_reference (se, arg_expr);
7142 }
b549d2a5 7143 else
5d34a30f 7144 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
97b9ac34 7145 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
411ee1e5 7146
7147 /* Create a temporary variable for loc return value. Without this,
b549d2a5 7148 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
fe537a55 7149 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
75a70cf9 7150 gfc_add_modify (&se->pre, temp_var, se->expr);
b549d2a5 7151 se->expr = temp_var;
7152}
7153
07f0c434 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
7161static void
7162conv_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);
38bb9313 7170 else if (gfc_is_simply_contiguous (arg->expr, false, false))
07f0c434 7171 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
09d9523d 7172 else
7173 {
7174 gfc_conv_expr_descriptor (se, arg->expr);
7175 se->expr = gfc_conv_descriptor_data_get (se->expr);
7176 }
07f0c434 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
7244static tree
7245conv_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
293d72e0 7324 /* Set bounds and stride. */
07f0c434 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
293d72e0 7333 /* Calculate offset. */
07f0c434 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
d7333535 7361/* Save and restore floating-point state. */
7362
7363tree
7364gfc_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
7382void
7383gfc_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
7395static void
7396conv_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
7424static void
7425conv_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
7443static void
7444conv_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
7467static void
7468conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
7469{
d351aaf5 7470 tree arg, signbit, isnan;
d7333535 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
d351aaf5 7481 signbit = build_call_expr_loc (input_location,
7482 builtin_decl_explicit (BUILT_IN_SIGNBIT),
7483 1, arg);
d7333535 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
7498static void
7499conv_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
7523static void
7524conv_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
7556static void
7557conv_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
7583static void
7584conv_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
7622static void
7623conv_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. */
d351aaf5 7631 sign = build_call_expr_loc (input_location,
7632 builtin_decl_explicit (BUILT_IN_SIGNBIT),
7633 1, args[1]);
d7333535 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
7656bool
7657gfc_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
c338399c 7696/* Generate a direct call to malloc() for the MALLOC intrinsic. */
7697
7698static void
7699gfc_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
4ee9c684 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
7716void
7717gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
7718{
c231e334 7719 const char *name;
40b806de 7720 int lib, kind;
7721 tree fndecl;
4ee9c684 7722
4ee9c684 7723 name = &expr->value.function.name[2];
7724
1274527b 7725 if (expr->rank > 0)
4ee9c684 7726 {
7727 lib = gfc_is_intrinsic_libcall (expr);
7728 if (lib != 0)
7729 {
7730 if (lib == 1)
7731 se->ignore_optional = 1;
8572fdb4 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
4ee9c684 7748 return;
7749 }
7750 }
7751
55cb4417 7752 switch (expr->value.function.isym->id)
4ee9c684 7753 {
7754 case GFC_ISYM_NONE:
22d678e8 7755 gcc_unreachable ();
4ee9c684 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
59e2a584 7765 case GFC_ISYM_SC_KIND:
7766 gfc_conv_intrinsic_sc_kind (se, expr);
7767 break;
7768
4ee9c684 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
4ee9c684 7781 case GFC_ISYM_SCAN:
40b806de 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);
4ee9c684 7791 break;
7792
7793 case GFC_ISYM_VERIFY:
40b806de 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);
4ee9c684 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
1de1b1a9 7813 case GFC_ISYM_SAME_TYPE_AS:
7814 gfc_conv_same_type_as (se, expr);
7815 break;
7816
4ee9c684 7817 case GFC_ISYM_ABS:
7818 gfc_conv_intrinsic_abs (se, expr);
7819 break;
7820
7821 case GFC_ISYM_ADJUSTL:
40b806de 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);
4ee9c684 7830 break;
7831
7832 case GFC_ISYM_ADJUSTR:
40b806de 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);
4ee9c684 7841 break;
7842
7843 case GFC_ISYM_AIMAG:
7844 gfc_conv_intrinsic_imagpart (se, expr);
7845 break;
7846
7847 case GFC_ISYM_AINT:
8a1417cb 7848 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
4ee9c684 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:
8a1417cb 7856 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
4ee9c684 7857 break;
7858
16de8065 7859 case GFC_ISYM_AND:
7860 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
7861 break;
7862
4ee9c684 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
f004c7aa 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
07f0c434 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
4ee9c684 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
7b3423b9 7905 /* Integer conversions are handled separately to make sure we get the
4ee9c684 7906 correct rounding mode. */
7907 case GFC_ISYM_INT:
c7347b39 7908 case GFC_ISYM_INT2:
7909 case GFC_ISYM_INT8:
7910 case GFC_ISYM_LONG:
8a1417cb 7911 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
4ee9c684 7912 break;
7913
7914 case GFC_ISYM_NINT:
8a1417cb 7915 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
4ee9c684 7916 break;
7917
7918 case GFC_ISYM_CEILING:
8a1417cb 7919 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
4ee9c684 7920 break;
7921
7922 case GFC_ISYM_FLOOR:
8a1417cb 7923 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
4ee9c684 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
5f4a118e 7934 case GFC_ISYM_CAF_GET:
9f1c76f9 7935 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE);
5f4a118e 7936 break;
7937
4ee9c684 7938 case GFC_ISYM_CMPLX:
7939 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
7940 break;
7941
9b057c29 7942 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
f0f2da44 7943 gfc_conv_intrinsic_iargc (se, expr);
9b057c29 7944 break;
7945
16de8065 7946 case GFC_ISYM_COMPLEX:
7947 gfc_conv_intrinsic_cmplx (se, expr, 1);
7948 break;
7949
4ee9c684 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
b902b078 7958 case GFC_ISYM_CTIME:
7959 gfc_conv_intrinsic_ctime (se, expr);
7960 break;
7961
4ee9c684 7962 case GFC_ISYM_DIM:
7963 gfc_conv_intrinsic_dim (se, expr);
7964 break;
7965
0b5dc8b5 7966 case GFC_ISYM_DOT_PRODUCT:
7967 gfc_conv_intrinsic_dot_product (se, expr);
7968 break;
7969
4ee9c684 7970 case GFC_ISYM_DPROD:
7971 gfc_conv_intrinsic_dprod (se, expr);
7972 break;
7973
f004c7aa 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
b902b078 7982 case GFC_ISYM_FDATE:
7983 gfc_conv_intrinsic_fdate (se, expr);
7984 break;
7985
34e106da 7986 case GFC_ISYM_FRACTION:
7987 gfc_conv_intrinsic_fraction (se, expr);
7988 break;
7989
9028d57d 7990 case GFC_ISYM_IALL:
7991 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
7992 break;
7993
4ee9c684 7994 case GFC_ISYM_IAND:
7995 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
7996 break;
7997
9028d57d 7998 case GFC_ISYM_IANY:
7999 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
8000 break;
8001
4ee9c684 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
9b057c29 8020 case GFC_ISYM_IARGC:
f0f2da44 8021 gfc_conv_intrinsic_iargc (se, expr);
9b057c29 8022 break;
8023
4ee9c684 8024 case GFC_ISYM_IEOR:
8025 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
8026 break;
8027
8028 case GFC_ISYM_INDEX:
40b806de 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);
4ee9c684 8038 break;
8039
8040 case GFC_ISYM_IOR:
8041 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
8042 break;
8043
9028d57d 8044 case GFC_ISYM_IPARITY:
8045 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
8046 break;
8047
52ed1096 8048 case GFC_ISYM_IS_IOSTAT_END:
18f0b7df 8049 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
52ed1096 8050 break;
8051
8052 case GFC_ISYM_IS_IOSTAT_EOR:
18f0b7df 8053 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
52ed1096 8054 break;
8055
4e549567 8056 case GFC_ISYM_ISNAN:
8057 gfc_conv_intrinsic_isnan (se, expr);
8058 break;
8059
d2fc5bb1 8060 case GFC_ISYM_LSHIFT:
f004c7aa 8061 gfc_conv_intrinsic_shift (se, expr, false, false);
d2fc5bb1 8062 break;
8063
8064 case GFC_ISYM_RSHIFT:
f004c7aa 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);
d2fc5bb1 8078 break;
8079
4ee9c684 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
0b820f43 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
41cbc93c 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
4ee9c684 8104 case GFC_ISYM_LBOUND:
8105 gfc_conv_intrinsic_bound (se, expr, 0);
8106 break;
8107
076094b7 8108 case GFC_ISYM_LCOBOUND:
8109 conv_intrinsic_cobound (se, expr);
8110 break;
8111
018ef8b8 8112 case GFC_ISYM_TRANSPOSE:
1274527b 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);
018ef8b8 8116 break;
8117
4ee9c684 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
c338399c 8142 case GFC_ISYM_MALLOC:
8143 gfc_conv_intrinsic_malloc (se, expr);
8144 break;
8145
f004c7aa 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
4ee9c684 8154 case GFC_ISYM_MAX:
5fcc6ec2 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);
4ee9c684 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
f004c7aa 8173 case GFC_ISYM_MERGE_BITS:
8174 gfc_conv_intrinsic_merge_bits (se, expr);
8175 break;
8176
4ee9c684 8177 case GFC_ISYM_MIN:
5fcc6ec2 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);
4ee9c684 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
34e106da 8192 case GFC_ISYM_NEAREST:
8193 gfc_conv_intrinsic_nearest (se, expr);
8194 break;
8195
b4ba8232 8196 case GFC_ISYM_NORM2:
8197 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
8198 break;
8199
4ee9c684 8200 case GFC_ISYM_NOT:
8201 gfc_conv_intrinsic_not (se, expr);
8202 break;
8203
16de8065 8204 case GFC_ISYM_OR:
8205 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
8206 break;
8207
b4ba8232 8208 case GFC_ISYM_PARITY:
8209 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
8210 break;
8211
4ee9c684 8212 case GFC_ISYM_PRESENT:
8213 gfc_conv_intrinsic_present (se, expr);
8214 break;
8215
8216 case GFC_ISYM_PRODUCT:
b4ba8232 8217 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
4ee9c684 8218 break;
90342c73 8219
8220 case GFC_ISYM_RANK:
8221 gfc_conv_intrinsic_rank (se, expr);
8222 break;
4ee9c684 8223
34e106da 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
4ee9c684 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
1318f16c 8244 case GFC_ISYM_SIZEOF:
95bf00d5 8245 case GFC_ISYM_C_SIZEOF:
1318f16c 8246 gfc_conv_intrinsic_sizeof (se, expr);
8247 break;
8248
95bf00d5 8249 case GFC_ISYM_STORAGE_SIZE:
8250 gfc_conv_intrinsic_storage_size (se, expr);
8251 break;
8252
34e106da 8253 case GFC_ISYM_SPACING:
8254 gfc_conv_intrinsic_spacing (se, expr);
8255 break;
8256
f9606ba3 8257 case GFC_ISYM_STRIDE:
8258 conv_intrinsic_stride (se, expr);
8259 break;
8260
4ee9c684 8261 case GFC_ISYM_SUM:
b4ba8232 8262 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
4ee9c684 8263 break;
8264
8265 case GFC_ISYM_TRANSFER:
1b3fff24 8266 if (se->ss && se->ss->info->useflags)
1f2a3eec 8267 /* Access the previously obtained result. */
8268 gfc_conv_tmp_array_ref (se);
4eaa93a5 8269 else
891756c7 8270 gfc_conv_intrinsic_transfer (se, expr);
dbc97b88 8271 break;
8272
8273 case GFC_ISYM_TTYNAM:
8274 gfc_conv_intrinsic_ttynam (se, expr);
4ee9c684 8275 break;
8276
8277 case GFC_ISYM_UBOUND:
8278 gfc_conv_intrinsic_bound (se, expr, 1);
8279 break;
8280
076094b7 8281 case GFC_ISYM_UCOBOUND:
8282 conv_intrinsic_cobound (se, expr);
8283 break;
8284
16de8065 8285 case GFC_ISYM_XOR:
8286 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
8287 break;
8288
b549d2a5 8289 case GFC_ISYM_LOC:
8290 gfc_conv_intrinsic_loc (se, expr);
8291 break;
8292
70b5944a 8293 case GFC_ISYM_THIS_IMAGE:
2e34dcd8 8294 /* For num_images() == 1, handle as LCOBOUND. */
8295 if (expr->value.function.actual->expr
4fe73152 8296 && flag_coarray == GFC_FCOARRAY_SINGLE)
076094b7 8297 conv_intrinsic_cobound (se, expr);
8298 else
8299 trans_this_image (se, expr);
70b5944a 8300 break;
8301
09800dba 8302 case GFC_ISYM_IMAGE_INDEX:
8303 trans_image_index (se, expr);
8304 break;
8305
70b5944a 8306 case GFC_ISYM_NUM_IMAGES:
3427a543 8307 trans_num_images (se, expr);
70b5944a 8308 break;
8309
d2fc5bb1 8310 case GFC_ISYM_ACCESS:
4dd3972f 8311 case GFC_ISYM_CHDIR:
d2fc5bb1 8312 case GFC_ISYM_CHMOD:
dd6c1457 8313 case GFC_ISYM_DTIME:
041de113 8314 case GFC_ISYM_ETIME:
bdfbc762 8315 case GFC_ISYM_EXTENDS_TYPE_OF:
16de8065 8316 case GFC_ISYM_FGET:
8317 case GFC_ISYM_FGETC:
771c1b50 8318 case GFC_ISYM_FNUM:
16de8065 8319 case GFC_ISYM_FPUT:
8320 case GFC_ISYM_FPUTC:
771c1b50 8321 case GFC_ISYM_FSTAT:
16de8065 8322 case GFC_ISYM_FTELL:
169bb4d1 8323 case GFC_ISYM_GETCWD:
adad6c74 8324 case GFC_ISYM_GETGID:
8325 case GFC_ISYM_GETPID:
8326 case GFC_ISYM_GETUID:
4dd3972f 8327 case GFC_ISYM_HOSTNM:
8328 case GFC_ISYM_KILL:
8329 case GFC_ISYM_IERRNO:
771c1b50 8330 case GFC_ISYM_IRAND:
60d77e0d 8331 case GFC_ISYM_ISATTY:
faa9fea4 8332 case GFC_ISYM_JN2:
4dd3972f 8333 case GFC_ISYM_LINK:
c7347b39 8334 case GFC_ISYM_LSTAT:
771c1b50 8335 case GFC_ISYM_MATMUL:
c7347b39 8336 case GFC_ISYM_MCLOCK:
8337 case GFC_ISYM_MCLOCK8:
771c1b50 8338 case GFC_ISYM_RAND:
4dd3972f 8339 case GFC_ISYM_RENAME:
771c1b50 8340 case GFC_ISYM_SECOND:
10387833 8341 case GFC_ISYM_SECNDS:
247981ce 8342 case GFC_ISYM_SIGNAL:
771c1b50 8343 case GFC_ISYM_STAT:
4dd3972f 8344 case GFC_ISYM_SYMLNK:
82bbe4ec 8345 case GFC_ISYM_SYSTEM:
4dd3972f 8346 case GFC_ISYM_TIME:
8347 case GFC_ISYM_TIME8:
ab5619bc 8348 case GFC_ISYM_UMASK:
8349 case GFC_ISYM_UNLINK:
faa9fea4 8350 case GFC_ISYM_YN2:
4ee9c684 8351 gfc_conv_intrinsic_funcall (se, expr);
8352 break;
8353
8572fdb4 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
4ee9c684 8362 default:
8363 gfc_conv_intrinsic_lib_function (se, expr);
8364 break;
8365 }
8366}
8367
8368
1274527b 8369static gfc_ss *
8370walk_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 {
45f39826 8384 if (tmp_ss->info->type != GFC_SS_SCALAR
8385 && tmp_ss->info->type != GFC_SS_REFERENCE)
1274527b 8386 {
91c54654 8387 gcc_assert (tmp_ss->dimen == 2);
1274527b 8388
8389 /* We just invert dimensions. */
dfcf26a5 8390 std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
1274527b 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
88df5e2f 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
8410static gfc_ss *
8411nest_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
8465static gfc_ss *
8466walk_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
1274527b 8516static gfc_ss *
8517walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
8518{
8519
8520 switch (expr->value.function.isym->id)
8521 {
88df5e2f 8522 case GFC_ISYM_PRODUCT:
8523 case GFC_ISYM_SUM:
8524 return walk_inline_intrinsic_arith (ss, expr);
8525
1274527b 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
4ee9c684 8536/* This generates code to execute before entering the scalarization loop.
8537 Currently does nothing. */
8538
8539void
8540gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
8541{
bfa43780 8542 switch (ss->info->expr->value.function.isym->id)
4ee9c684 8543 {
8544 case GFC_ISYM_UBOUND:
8545 case GFC_ISYM_LBOUND:
076094b7 8546 case GFC_ISYM_UCOBOUND:
8547 case GFC_ISYM_LCOBOUND:
8548 case GFC_ISYM_THIS_IMAGE:
4ee9c684 8549 break;
8550
8551 default:
22d678e8 8552 gcc_unreachable ();
4ee9c684 8553 }
8554}
8555
8556
076094b7 8557/* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
8558 are expanded into code inside the scalarization loop. */
4ee9c684 8559
8560static gfc_ss *
8561gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
8562{
fd23cc08 8563 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
8564 gfc_add_class_array_ref (expr->value.function.actual->expr);
8565
4ee9c684 8566 /* The two argument version returns a scalar. */
8567 if (expr->value.function.actual->next->expr)
8568 return ss;
8569
f912e858 8570 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
4ee9c684 8571}
8572
8573
8574/* Walk an intrinsic array libcall. */
8575
8576static gfc_ss *
8577gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
8578{
22d678e8 8579 gcc_assert (expr->rank > 0);
f912e858 8580 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
4ee9c684 8581}
8582
8583
1274527b 8584/* Return whether the function call expression EXPR will be expanded
8585 inline by gfc_conv_intrinsic_function. */
8586
8587bool
8588gfc_inline_intrinsic_function_p (gfc_expr *expr)
8589{
88df5e2f 8590 gfc_actual_arglist *args;
8591
1274527b 8592 if (!expr->value.function.isym)
8593 return false;
8594
8595 switch (expr->value.function.isym->id)
8596 {
88df5e2f 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
1274527b 8610 case GFC_ISYM_TRANSPOSE:
8611 return true;
8612
8613 default:
8614 return false;
8615 }
8616}
8617
8618
69b1505f 8619/* Returns nonzero if the specified intrinsic function call maps directly to
4ee9c684 8620 an external library call. Should only be used for functions that return
8621 arrays. */
8622
8623int
8624gfc_is_intrinsic_libcall (gfc_expr * expr)
8625{
22d678e8 8626 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
8627 gcc_assert (expr->rank > 0);
4ee9c684 8628
1274527b 8629 if (gfc_inline_intrinsic_function_p (expr))
8630 return 0;
8631
55cb4417 8632 switch (expr->value.function.isym->id)
4ee9c684 8633 {
8634 case GFC_ISYM_ALL:
8635 case GFC_ISYM_ANY:
8636 case GFC_ISYM_COUNT:
faa9fea4 8637 case GFC_ISYM_JN2:
9028d57d 8638 case GFC_ISYM_IANY:
8639 case GFC_ISYM_IALL:
8640 case GFC_ISYM_IPARITY:
4ee9c684 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:
b4ba8232 8646 case GFC_ISYM_NORM2:
8647 case GFC_ISYM_PARITY:
4ee9c684 8648 case GFC_ISYM_PRODUCT:
8649 case GFC_ISYM_SUM:
8650 case GFC_ISYM_SHAPE:
8651 case GFC_ISYM_SPREAD:
faa9fea4 8652 case GFC_ISYM_YN2:
4ee9c684 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. */
8670gfc_ss *
8671gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
8672 gfc_intrinsic_sym * isym)
8673{
22d678e8 8674 gcc_assert (isym);
4ee9c684 8675
8676 if (isym->elemental)
1274527b 8677 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
4fd5163b 8678 NULL, GFC_SS_SCALAR);
4ee9c684 8679
8680 if (expr->rank == 0)
8681 return ss;
8682
1274527b 8683 if (gfc_inline_intrinsic_function_p (expr))
8684 return walk_inline_intrinsic_function (ss, expr);
8685
4ee9c684 8686 if (gfc_is_intrinsic_libcall (expr))
8687 return gfc_walk_intrinsic_libfunc (ss, expr);
8688
8689 /* Special cases. */
55cb4417 8690 switch (isym->id)
4ee9c684 8691 {
8692 case GFC_ISYM_LBOUND:
076094b7 8693 case GFC_ISYM_LCOBOUND:
4ee9c684 8694 case GFC_ISYM_UBOUND:
076094b7 8695 case GFC_ISYM_UCOBOUND:
8696 case GFC_ISYM_THIS_IMAGE:
4ee9c684 8697 return gfc_walk_intrinsic_bound (ss, expr);
8698
4eaa93a5 8699 case GFC_ISYM_TRANSFER:
5f4a118e 8700 case GFC_ISYM_CAF_GET:
4eaa93a5 8701 return gfc_walk_intrinsic_libfunc (ss, expr);
8702
4ee9c684 8703 default:
8704 /* This probably meant someone forgot to add an intrinsic to the above
cbbac028 8705 list(s) when they implemented it, or something's gone horribly
8706 wrong. */
8707 gcc_unreachable ();
4ee9c684 8708 }
8709}
8710
0fc13348 8711
79ed4a8e 8712static tree
52306a18 8713conv_co_collective (gfc_code *code)
79ed4a8e 8714{
8715 gfc_se argse;
8716 stmtblock_t block, post_block;
5f4a118e 8717 tree fndecl, array, strlen, image_index, stat, errmsg, errmsg_len;
e39efcef 8718 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
79ed4a8e 8719
8720 gfc_start_block (&block);
8721 gfc_init_block (&post_block);
8722
e39efcef 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
79ed4a8e 8738 /* stat. */
e39efcef 8739 if (stat_expr)
79ed4a8e 8740 {
8741 gfc_init_se (&argse, NULL);
e39efcef 8742 gfc_conv_expr (&argse, stat_expr);
79ed4a8e 8743 gfc_add_block_to_block (&block, &argse.pre);
8744 gfc_add_block_to_block (&post_block, &argse.post);
8745 stat = argse.expr;
4fe73152 8746 if (flag_coarray != GFC_FCOARRAY_SINGLE)
79ed4a8e 8747 stat = gfc_build_addr_expr (NULL_TREE, stat);
8748 }
4fe73152 8749 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
79ed4a8e 8750 stat = NULL_TREE;
8751 else
8752 stat = null_pointer_node;
8753
8754 /* Early exit for GFC_FCOARRAY_SINGLE. */
4fe73152 8755 if (flag_coarray == GFC_FCOARRAY_SINGLE)
79ed4a8e 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
79ed4a8e 8790 /* image_index. */
e39efcef 8791 if (image_idx_expr)
79ed4a8e 8792 {
8793 gfc_init_se (&argse, NULL);
e39efcef 8794 gfc_conv_expr (&argse, image_idx_expr);
79ed4a8e 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. */
e39efcef 8803 if (errmsg_expr)
79ed4a8e 8804 {
8805 gfc_init_se (&argse, NULL);
e39efcef 8806 gfc_conv_expr (&argse, errmsg_expr);
79ed4a8e 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. */
52306a18 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;
e39efcef 8830 case GFC_ISYM_CO_REDUCE:
8831 fndecl = gfor_fndecl_co_reduce;
8832 break;
52306a18 8833 case GFC_ISYM_CO_SUM:
8834 fndecl = gfor_fndecl_co_sum;
8835 break;
411ee1e5 8836 default:
52306a18 8837 gcc_unreachable ();
8838 }
79ed4a8e 8839
52306a18 8840 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
8841 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
8c68cf35 8842 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
8843 image_index, stat, errmsg, errmsg_len);
e39efcef 8844 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
8c68cf35 8845 fndecl = build_call_expr_loc (input_location, fndecl, 6, array, image_index,
8846 stat, errmsg, strlen, errmsg_len);
e39efcef 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);
af80543e 8877 opr = argse.expr;
e39efcef 8878 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr, opr_flags,
8879 image_index, stat, errmsg, strlen, errmsg_len);
8880 }
8881
79ed4a8e 8882 gfc_add_expr_to_block (&block, fndecl);
8883 gfc_add_block_to_block (&block, &post_block);
8884
79ed4a8e 8885 return gfc_finish_block (&block);
8886}
8887
8888
6ccde1eb 8889static tree
75fe6d70 8890conv_intrinsic_atomic_op (gfc_code *code)
6ccde1eb 8891{
97b9ac34 8892 gfc_se argse;
8893 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
75fe6d70 8894 stmtblock_t block, post_block;
5f4a118e 8895 gfc_expr *atom_expr = code->ext.actual->expr;
97b9ac34 8896 gfc_expr *stat_expr;
75fe6d70 8897 built_in_function fn;
5f4a118e 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;
6ccde1eb 8903
75fe6d70 8904 gfc_start_block (&block);
8905 gfc_init_block (&post_block);
97b9ac34 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);
4fe73152 8915 if (flag_coarray == GFC_FCOARRAY_LIB
97b9ac34 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;
4fe73152 8931 if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 8932 old = null_pointer_node;
8933 break;
8934 default:
8935 gfc_init_se (&argse, NULL);
4fe73152 8936 if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 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);
4fe73152 8950 if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 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 }
4fe73152 8957 else if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 8958 stat = null_pointer_node;
8959
4fe73152 8960 if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 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))
384d1ed7 8995 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
97b9ac34 8996 else
8997 image_index = integer_zero_node;
8998
8dcb21db 8999 if (!POINTER_TYPE_P (TREE_TYPE (value)))
97b9ac34 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
384d1ed7 9006 gfc_get_caf_token_offset (&token, &offset, caf_decl, atom, atom_expr);
97b9ac34 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
6ccde1eb 9029
75fe6d70 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
97b9ac34 9055 tmp = TREE_TYPE (TREE_TYPE (atom));
75fe6d70 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);
97b9ac34 9060 tree itype = TREE_TYPE (TREE_TYPE (atom));
75fe6d70 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:
97b9ac34 9070 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
9071 fold_convert (itype, value),
75fe6d70 9072 build_int_cst (NULL, MEMMODEL_RELAXED));
9073 gfc_add_expr_to_block (&block, tmp);
9074 break;
9075 default:
97b9ac34 9076 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
9077 fold_convert (itype, value),
75fe6d70 9078 build_int_cst (NULL, MEMMODEL_RELAXED));
97b9ac34 9079 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
75fe6d70 9080 break;
9081 }
9082
97b9ac34 9083 if (stat != NULL_TREE)
9084 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
75fe6d70 9085 gfc_add_block_to_block (&block, &post_block);
6ccde1eb 9086 return gfc_finish_block (&block);
9087}
9088
9089
9090static tree
9091conv_intrinsic_atomic_ref (gfc_code *code)
9092{
97b9ac34 9093 gfc_se argse;
9094 tree tmp, atom, value, stat = NULL_TREE;
75fe6d70 9095 stmtblock_t block, post_block;
9096 built_in_function fn;
9097 gfc_expr *atom_expr = code->ext.actual->next->expr;
5f4a118e 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;
6ccde1eb 9103
75fe6d70 9104 gfc_start_block (&block);
9105 gfc_init_block (&post_block);
97b9ac34 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);
4fe73152 9114 if (flag_coarray == GFC_FCOARRAY_LIB
3906f8fc 9115 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
97b9ac34 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
75fe6d70 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);
97b9ac34 9127 gfc_init_se (&argse, NULL);
4fe73152 9128 if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 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 }
4fe73152 9135 else if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 9136 stat = null_pointer_node;
9137
4fe73152 9138 if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 9139 {
9140 tree image_index, caf_decl, offset, token;
3906f8fc 9141 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
97b9ac34 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))
384d1ed7 9148 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
97b9ac34 9149 else
9150 image_index = integer_zero_node;
9151
384d1ed7 9152 gfc_get_caf_token_offset (&token, &offset, caf_decl, atom, atom_expr);
97b9ac34 9153
3906f8fc 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
97b9ac34 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);
3906f8fc 9169 if (vardecl != NULL_TREE)
9170 gfc_add_modify (&block, orig_value,
9171 fold_convert (TREE_TYPE (orig_value), vardecl));
97b9ac34 9172 gfc_add_block_to_block (&block, &post_block);
9173 return gfc_finish_block (&block);
75fe6d70 9174 }
97b9ac34 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));
75fe6d70 9188 gfc_add_block_to_block (&block, &post_block);
9189 return gfc_finish_block (&block);
9190}
9191
9192
9193static tree
9194conv_intrinsic_atomic_cas (gfc_code *code)
9195{
9196 gfc_se argse;
97b9ac34 9197 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
75fe6d70 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;
6ccde1eb 9206
9207 gfc_init_block (&block);
75fe6d70 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);
4fe73152 9215 if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 9216 argse.want_pointer = 1;
75fe6d70 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);
4fe73152 9223 if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 9224 argse.want_pointer = 1;
75fe6d70 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);
4fe73152 9231 if (flag_coarray == GFC_FCOARRAY_LIB
97b9ac34 9232 && code->ext.actual->next->next->next->expr->ts.kind
9233 == atom_expr->ts.kind)
9234 argse.want_pointer = 1;
75fe6d70 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
97b9ac34 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);
4fe73152 9246 if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 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 }
4fe73152 9254 else if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 9255 stat = null_pointer_node;
9256
4fe73152 9257 if (flag_coarray == GFC_FCOARRAY_LIB)
97b9ac34 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))
384d1ed7 9266 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
97b9ac34 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
384d1ed7 9285 gfc_get_caf_token_offset (&token, &offset, caf_decl, atom, atom_expr);
97b9ac34 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
75fe6d70 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);
411ee1e5 9312
97b9ac34 9313 if (stat != NULL_TREE)
9314 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
75fe6d70 9315 gfc_add_block_to_block (&block, &post_block);
6ccde1eb 9316 return gfc_finish_block (&block);
9317}
9318
bd47f0bc 9319static tree
9320conv_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}
6ccde1eb 9467
9468static tree
9469conv_intrinsic_move_alloc (gfc_code *code)
0fc13348 9470{
5ce6c67e 9471 stmtblock_t block;
9472 gfc_expr *from_expr, *to_expr;
dd0cebe1 9473 gfc_expr *to_expr2, *from_expr2 = NULL;
5ce6c67e 9474 gfc_se from_se, to_se;
5ce6c67e 9475 tree tmp;
fc378a70 9476 bool coarray;
0fc13348 9477
5ce6c67e 9478 gfc_start_block (&block);
0fc13348 9479
5ce6c67e 9480 from_expr = code->ext.actual->expr;
9481 to_expr = code->ext.actual->next->expr;
0fc13348 9482
5ce6c67e 9483 gfc_init_se (&from_se, NULL);
9484 gfc_init_se (&to_se, NULL);
3e223d53 9485
3a19c063 9486 gcc_assert (from_expr->ts.type != BT_CLASS
9487 || to_expr->ts.type == BT_CLASS);
fc378a70 9488 coarray = gfc_get_corank (from_expr) != 0;
3a19c063 9489
fc378a70 9490 if (from_expr->rank == 0 && !coarray)
5ce6c67e 9491 {
9492 if (from_expr->ts.type != BT_CLASS)
dd0cebe1 9493 from_expr2 = from_expr;
9494 else
5ce6c67e 9495 {
dd0cebe1 9496 from_expr2 = gfc_copy_expr (from_expr);
9497 gfc_add_data_component (from_expr2);
5ce6c67e 9498 }
dd0cebe1 9499
9500 if (to_expr->ts.type != BT_CLASS)
9501 to_expr2 = to_expr;
0fc13348 9502 else
5ce6c67e 9503 {
9504 to_expr2 = gfc_copy_expr (to_expr);
5ce6c67e 9505 gfc_add_data_component (to_expr2);
9506 }
0fc13348 9507
5ce6c67e 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,
9f78c31e 9517 to_expr, to_expr->ts);
0fc13348 9518 gfc_add_expr_to_block (&block, tmp);
9519
5ce6c67e 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. */
dd0cebe1 9532 if (to_expr->ts.type == BT_CLASS)
5ce6c67e 9533 {
c87bf31f 9534 gfc_symbol *vtab;
9535
dd0cebe1 9536 gfc_free_expr (to_expr2);
5ce6c67e 9537 gfc_init_se (&to_se, NULL);
5ce6c67e 9538 to_se.want_pointer = 1;
5ce6c67e 9539 gfc_add_vptr_component (to_expr);
5ce6c67e 9540 gfc_conv_expr (&to_se, to_expr);
dd0cebe1 9541
9542 if (from_expr->ts.type == BT_CLASS)
9543 {
7434f296 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 }
c87bf31f 9551
dd0cebe1 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);
c87bf31f 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. */
66d4dd66 9562 if (vtab == NULL)
9563 /* Unlimited polymorphic. */
7434f296 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 }
dd0cebe1 9573 }
9574 else
9575 {
25014fa7 9576 vtab = gfc_find_vtab (&from_expr->ts);
dd0cebe1 9577 gcc_assert (vtab);
9578 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
c87bf31f 9579 gfc_add_modify_loc (input_location, &block, to_se.expr,
9580 fold_convert (TREE_TYPE (to_se.expr), tmp));
dd0cebe1 9581 }
5ce6c67e 9582 }
9583
6f29994c 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
0fc13348 9594 return gfc_finish_block (&block);
9595 }
5ce6c67e 9596
9597 /* Update _vptr component. */
dd0cebe1 9598 if (to_expr->ts.type == BT_CLASS)
5ce6c67e 9599 {
c87bf31f 9600 gfc_symbol *vtab;
9601
5ce6c67e 9602 to_se.want_pointer = 1;
5ce6c67e 9603 to_expr2 = gfc_copy_expr (to_expr);
5ce6c67e 9604 gfc_add_vptr_component (to_expr2);
5ce6c67e 9605 gfc_conv_expr (&to_se, to_expr2);
9606
dd0cebe1 9607 if (from_expr->ts.type == BT_CLASS)
9608 {
7434f296 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 }
c87bf31f 9616
dd0cebe1 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);
c87bf31f 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. */
66d4dd66 9626 if (vtab == NULL)
9627 /* Unlimited polymorphic. */
7434f296 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 }
dd0cebe1 9637 }
9638 else
9639 {
25014fa7 9640 vtab = gfc_find_vtab (&from_expr->ts);
dd0cebe1 9641 gcc_assert (vtab);
9642 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
c87bf31f 9643 gfc_add_modify_loc (input_location, &block, to_se.expr,
9644 fold_convert (TREE_TYPE (to_se.expr), tmp));
dd0cebe1 9645 }
9646
5ce6c67e 9647 gfc_free_expr (to_expr2);
5ce6c67e 9648 gfc_init_se (&to_se, NULL);
dd0cebe1 9649
9650 if (from_expr->ts.type == BT_CLASS)
9651 {
9652 gfc_free_expr (from_expr2);
9653 gfc_init_se (&from_se, NULL);
9654 }
5ce6c67e 9655 }
9656
5d34a30f 9657
5ce6c67e 9658 /* Deallocate "to". */
5d34a30f 9659 if (from_expr->rank == 0)
fc378a70 9660 {
5d34a30f 9661 to_se.want_coarray = 1;
9662 from_se.want_coarray = 1;
fc378a70 9663 }
5d34a30f 9664 gfc_conv_expr_descriptor (&to_se, to_expr);
9665 gfc_conv_expr_descriptor (&from_se, from_expr);
5ce6c67e 9666
fc378a70 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. */
4fe73152 9669 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
fc378a70 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 {
6f29994c 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
fc378a70 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 }
5ce6c67e 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
c87bf31f 9710 /* Set "from" to NULL. */
5ce6c67e 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
6f29994c 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
5ce6c67e 9726 return gfc_finish_block (&block);
0fc13348 9727}
9728
9729
6ccde1eb 9730tree
9731gfc_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
75fe6d70 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:
6ccde1eb 9749 case GFC_ISYM_ATOMIC_DEF:
75fe6d70 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);
6ccde1eb 9757 break;
9758
9759 case GFC_ISYM_ATOMIC_REF:
9760 res = conv_intrinsic_atomic_ref (code);
9761 break;
9762
bd47f0bc 9763 case GFC_ISYM_EVENT_QUERY:
9764 res = conv_intrinsic_event_query (code);
9765 break;
9766
07f0c434 9767 case GFC_ISYM_C_F_POINTER:
9768 case GFC_ISYM_C_F_PROCPOINTER:
9769 res = conv_isocbinding_subroutine (code);
9770 break;
9771
5f4a118e 9772 case GFC_ISYM_CAF_SEND:
9773 res = conv_caf_send (code);
9774 break;
9775
52306a18 9776 case GFC_ISYM_CO_BROADCAST:
79ed4a8e 9777 case GFC_ISYM_CO_MIN:
9778 case GFC_ISYM_CO_MAX:
e39efcef 9779 case GFC_ISYM_CO_REDUCE:
79ed4a8e 9780 case GFC_ISYM_CO_SUM:
52306a18 9781 res = conv_co_collective (code);
79ed4a8e 9782 break;
07f0c434 9783
c338399c 9784 case GFC_ISYM_FREE:
9785 res = conv_intrinsic_free (code);
9786 break;
9787
72ce5390 9788 case GFC_ISYM_SYSTEM_CLOCK:
9789 res = conv_intrinsic_system_clock (code);
9790 break;
9791
6ccde1eb 9792 default:
9793 res = NULL_TREE;
9794 break;
9795 }
9796
9797 return res;
9798}
9799
4ee9c684 9800#include "gt-fortran-trans-intrinsic.h"