]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-intrinsic.c
This patch rewrites the old VEC macro-based interface into a new one
[thirdparty/gcc.git] / gcc / fortran / trans-intrinsic.c
CommitLineData
4ee9c684 1/* Intrinsic translation
d0d776fb 2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3 2011, 2012
5687724f 4 Free Software Foundation, Inc.
4ee9c684 5 Contributed by Paul Brook <paul@nowt.org>
6 and Steven Bosscher <s.bosscher@student.tudelft.nl>
7
c84b470d 8This file is part of GCC.
4ee9c684 9
c84b470d 10GCC is free software; you can redistribute it and/or modify it under
11the terms of the GNU General Public License as published by the Free
bdabe786 12Software Foundation; either version 3, or (at your option) any later
c84b470d 13version.
4ee9c684 14
c84b470d 15GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18for more details.
4ee9c684 19
20You should have received a copy of the GNU General Public License
bdabe786 21along with GCC; see the file COPYING3. If not see
22<http://www.gnu.org/licenses/>. */
4ee9c684 23
24/* trans-intrinsic.c-- generate GENERIC trees for calls to intrinsics. */
25
26#include "config.h"
27#include "system.h"
28#include "coretypes.h"
989adef3 29#include "tm.h" /* For UNITS_PER_WORD. */
4ee9c684 30#include "tree.h"
4ee9c684 31#include "ggc.h"
7cbc820e 32#include "diagnostic-core.h" /* For internal_error. */
33#include "toplev.h" /* For rest_of_decl_compilation. */
4ee9c684 34#include "flags.h"
4ee9c684 35#include "gfortran.h"
4b1085db 36#include "arith.h"
4ee9c684 37#include "intrinsic.h"
38#include "trans.h"
39#include "trans-const.h"
40#include "trans-types.h"
41#include "trans-array.h"
4ee9c684 42/* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
43#include "trans-stmt.h"
44
df084314 45/* This maps Fortran intrinsic math functions to external library or GCC
4ee9c684 46 builtin functions. */
fb1e4f4a 47typedef struct GTY(()) gfc_intrinsic_map_t {
4ee9c684 48 /* The explicit enum is required to work around inadequacies in the
49 garbage collection/gengtype parsing mechanism. */
55cb4417 50 enum gfc_isym_id id;
4ee9c684 51
52 /* Enum value from the "language-independent", aka C-centric, part
53 of gcc, or END_BUILTINS of no such value set. */
a80ae91c 54 enum built_in_function float_built_in;
55 enum built_in_function double_built_in;
56 enum built_in_function long_double_built_in;
57 enum built_in_function complex_float_built_in;
58 enum built_in_function complex_double_built_in;
59 enum built_in_function complex_long_double_built_in;
4ee9c684 60
61 /* True if the naming pattern is to prepend "c" for complex and
62 append "f" for kind=4. False if the naming pattern is to
920e54ef 63 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
4ee9c684 64 bool libm_name;
65
66 /* True if a complex version of the function exists. */
67 bool complex_available;
68
69 /* True if the function should be marked const. */
70 bool is_constant;
71
72 /* The base library name of this function. */
73 const char *name;
74
75 /* Cache decls created for the various operand types. */
76 tree real4_decl;
77 tree real8_decl;
920e54ef 78 tree real10_decl;
79 tree real16_decl;
4ee9c684 80 tree complex4_decl;
81 tree complex8_decl;
920e54ef 82 tree complex10_decl;
83 tree complex16_decl;
4ee9c684 84}
85gfc_intrinsic_map_t;
86
87/* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
88 defines complex variants of all of the entries in mathbuiltins.def
89 except for atan2. */
920e54ef 90#define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
91 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
a80ae91c 92 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
93 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
94 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
920e54ef 95
96#define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
97 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
a80ae91c 98 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
99 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
100 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
4ee9c684 101
ff4425cf 102#define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
a80ae91c 103 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
104 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
ff4425cf 105 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
106 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
107
c6599767 108#define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
a80ae91c 109 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
110 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
c6599767 111 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
a80ae91c 112 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
113
4ee9c684 114static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
115{
a80ae91c 116 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
117 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
118 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
4ee9c684 119#include "mathbuiltins.def"
120
ff4425cf 121 /* Functions in libgfortran. */
122 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
123
4ee9c684 124 /* End the list. */
ff4425cf 125 LIB_FUNCTION (NONE, NULL, false)
126
4ee9c684 127};
a80ae91c 128#undef OTHER_BUILTIN
ff4425cf 129#undef LIB_FUNCTION
4ee9c684 130#undef DEFINE_MATH_BUILTIN
158e0e64 131#undef DEFINE_MATH_BUILTIN_C
4ee9c684 132
4ee9c684 133
8a1417cb 134enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
4ee9c684 135
a80ae91c 136
137/* Find the correct variant of a given builtin from its argument. */
138static tree
139builtin_decl_for_precision (enum built_in_function base_built_in,
140 int precision)
141{
b9a16870 142 enum built_in_function i = END_BUILTINS;
a80ae91c 143
144 gfc_intrinsic_map_t *m;
145 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
146 ;
147
148 if (precision == TYPE_PRECISION (float_type_node))
149 i = m->float_built_in;
150 else if (precision == TYPE_PRECISION (double_type_node))
151 i = m->double_built_in;
152 else if (precision == TYPE_PRECISION (long_double_type_node))
153 i = m->long_double_built_in;
c6599767 154 else if (precision == TYPE_PRECISION (float128_type_node))
155 {
156 /* Special treatment, because it is not exactly a built-in, but
157 a library function. */
158 return m->real16_decl;
159 }
a80ae91c 160
b9a16870 161 return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
a80ae91c 162}
163
164
808656b4 165tree
166gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
167 int kind)
a80ae91c 168{
169 int i = gfc_validate_kind (BT_REAL, kind, false);
c6599767 170
171 if (gfc_real_kinds[i].c_float128)
172 {
173 /* For __float128, the story is a bit different, because we return
174 a decl to a library function rather than a built-in. */
175 gfc_intrinsic_map_t *m;
176 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
177 ;
178
179 return m->real16_decl;
180 }
181
a80ae91c 182 return builtin_decl_for_precision (double_built_in,
183 gfc_real_kinds[i].mode_precision);
184}
185
186
5ddb0172 187/* Evaluate the arguments to an intrinsic function. The value
188 of NARGS may be less than the actual number of arguments in EXPR
189 to allow optional "KIND" arguments that are not included in the
190 generated code to be ignored. */
4ee9c684 191
5ddb0172 192static void
193gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
194 tree *argarray, int nargs)
4ee9c684 195{
196 gfc_actual_arglist *actual;
bd24f178 197 gfc_expr *e;
198 gfc_intrinsic_arg *formal;
4ee9c684 199 gfc_se argse;
5ddb0172 200 int curr_arg;
4ee9c684 201
bd24f178 202 formal = expr->value.function.isym->formal;
5ddb0172 203 actual = expr->value.function.actual;
bd24f178 204
5ddb0172 205 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
206 actual = actual->next,
207 formal = formal ? formal->next : NULL)
4ee9c684 208 {
5ddb0172 209 gcc_assert (actual);
bd24f178 210 e = actual->expr;
9ca15c9b 211 /* Skip omitted optional arguments. */
bd24f178 212 if (!e)
5ddb0172 213 {
214 --curr_arg;
215 continue;
216 }
4ee9c684 217
218 /* Evaluate the parameter. This will substitute scalarized
b14e2757 219 references automatically. */
4ee9c684 220 gfc_init_se (&argse, se);
221
bd24f178 222 if (e->ts.type == BT_CHARACTER)
4ee9c684 223 {
bd24f178 224 gfc_conv_expr (&argse, e);
4ee9c684 225 gfc_conv_string_parameter (&argse);
5ddb0172 226 argarray[curr_arg++] = argse.string_length;
227 gcc_assert (curr_arg < nargs);
4ee9c684 228 }
229 else
bd24f178 230 gfc_conv_expr_val (&argse, e);
231
232 /* If an optional argument is itself an optional dummy argument,
233 check its presence and substitute a null if absent. */
24146844 234 if (e->expr_type == EXPR_VARIABLE
bd24f178 235 && e->symtree->n.sym->attr.optional
236 && formal
237 && formal->optional)
2abe085f 238 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
4ee9c684 239
240 gfc_add_block_to_block (&se->pre, &argse.pre);
241 gfc_add_block_to_block (&se->post, &argse.post);
5ddb0172 242 argarray[curr_arg] = argse.expr;
243 }
244}
245
246/* Count the number of actual arguments to the intrinsic function EXPR
247 including any "hidden" string length arguments. */
248
249static unsigned int
250gfc_intrinsic_argument_list_length (gfc_expr *expr)
251{
252 int n = 0;
253 gfc_actual_arglist *actual;
254
255 for (actual = expr->value.function.actual; actual; actual = actual->next)
256 {
257 if (!actual->expr)
258 continue;
259
260 if (actual->expr->ts.type == BT_CHARACTER)
261 n += 2;
262 else
263 n++;
8889e071 264 }
5ddb0172 265
266 return n;
4ee9c684 267}
268
269
270/* Conversions between different types are output by the frontend as
271 intrinsic functions. We implement these directly with inline code. */
272
273static void
274gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
275{
276 tree type;
5ddb0172 277 tree *args;
278 int nargs;
4ee9c684 279
5ddb0172 280 nargs = gfc_intrinsic_argument_list_length (expr);
86b32f71 281 args = XALLOCAVEC (tree, nargs);
5ddb0172 282
283 /* Evaluate all the arguments passed. Whilst we're only interested in the
284 first one here, there are other parts of the front-end that assume this
285 and will trigger an ICE if it's not the case. */
4ee9c684 286 type = gfc_typenode_for_spec (&expr->ts);
22d678e8 287 gcc_assert (expr->value.function.actual->expr);
5ddb0172 288 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
4ee9c684 289
b44437b9 290 /* Conversion between character kinds involves a call to a library
291 function. */
292 if (expr->ts.type == BT_CHARACTER)
293 {
294 tree fndecl, var, addr, tmp;
295
296 if (expr->ts.kind == 1
297 && expr->value.function.actual->expr->ts.kind == 4)
298 fndecl = gfor_fndecl_convert_char4_to_char1;
299 else if (expr->ts.kind == 4
300 && expr->value.function.actual->expr->ts.kind == 1)
301 fndecl = gfor_fndecl_convert_char1_to_char4;
302 else
303 gcc_unreachable ();
304
305 /* Create the variable storing the converted value. */
306 type = gfc_get_pchar_type (expr->ts.kind);
307 var = gfc_create_var (type, "str");
308 addr = gfc_build_addr_expr (build_pointer_type (type), var);
309
310 /* Call the library function that will perform the conversion. */
311 gcc_assert (nargs >= 2);
389dd41b 312 tmp = build_call_expr_loc (input_location,
313 fndecl, 3, addr, args[0], args[1]);
b44437b9 314 gfc_add_expr_to_block (&se->pre, tmp);
315
316 /* Free the temporary afterwards. */
317 tmp = gfc_call_free (var);
318 gfc_add_expr_to_block (&se->post, tmp);
319
320 se->expr = var;
321 se->string_length = args[0];
322
323 return;
324 }
325
4ee9c684 326 /* Conversion from complex to non-complex involves taking the real
327 component of the value. */
5ddb0172 328 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
4ee9c684 329 && expr->ts.type != BT_COMPLEX)
330 {
331 tree artype;
332
5ddb0172 333 artype = TREE_TYPE (TREE_TYPE (args[0]));
6f5c9335 334 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
335 args[0]);
4ee9c684 336 }
337
5ddb0172 338 se->expr = convert (type, args[0]);
4ee9c684 339}
340
e41f2c1a 341/* This is needed because the gcc backend only implements
342 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
343 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
4ee9c684 344 Similarly for CEILING. */
345
346static tree
347build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
348{
349 tree tmp;
350 tree cond;
351 tree argtype;
352 tree intval;
353
354 argtype = TREE_TYPE (arg);
355 arg = gfc_evaluate_now (arg, pblock);
356
357 intval = convert (type, arg);
358 intval = gfc_evaluate_now (intval, pblock);
359
360 tmp = convert (argtype, intval);
6f5c9335 361 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
362 boolean_type_node, tmp, arg);
4ee9c684 363
6f5c9335 364 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
365 intval, build_int_cst (type, 1));
366 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
4ee9c684 367 return tmp;
368}
369
370
ef080b63 371/* Round to nearest integer, away from zero. */
4ee9c684 372
373static tree
ef080b63 374build_round_expr (tree arg, tree restype)
4ee9c684 375{
4ee9c684 376 tree argtype;
ef080b63 377 tree fn;
ef080b63 378 int argprec, resprec;
4ee9c684 379
380 argtype = TREE_TYPE (arg);
ef080b63 381 argprec = TYPE_PRECISION (argtype);
382 resprec = TYPE_PRECISION (restype);
4ee9c684 383
f5fdea80 384 /* Depending on the type of the result, choose the int intrinsic
fb1fb9d3 385 (iround, available only as a builtin, therefore cannot use it for
386 __float128), long int intrinsic (lround family) or long long
387 intrinsic (llround). We might also need to convert the result
388 afterwards. */
389 if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
f5fdea80 390 fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
391 else if (resprec <= LONG_TYPE_SIZE)
392 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
ef080b63 393 else if (resprec <= LONG_LONG_TYPE_SIZE)
a80ae91c 394 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
ef080b63 395 else
f5fdea80 396 gcc_unreachable ();
ef080b63 397
389dd41b 398 return fold_convert (restype, build_call_expr_loc (input_location,
399 fn, 1, arg));
4ee9c684 400}
401
402
403/* Convert a real to an integer using a specific rounding mode.
404 Ideally we would just build the corresponding GENERIC node,
405 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
406
407static tree
4bbc8816 408build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
8a1417cb 409 enum rounding_mode op)
4ee9c684 410{
411 switch (op)
412 {
8a1417cb 413 case RND_FLOOR:
4ee9c684 414 return build_fixbound_expr (pblock, arg, type, 0);
415 break;
416
8a1417cb 417 case RND_CEIL:
4ee9c684 418 return build_fixbound_expr (pblock, arg, type, 1);
419 break;
420
8a1417cb 421 case RND_ROUND:
ef080b63 422 return build_round_expr (arg, type);
423 break;
4ee9c684 424
ef080b63 425 case RND_TRUNC:
6f5c9335 426 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
ef080b63 427 break;
428
429 default:
430 gcc_unreachable ();
4ee9c684 431 }
432}
433
434
435/* Round a real value using the specified rounding mode.
436 We use a temporary integer of that same kind size as the result.
4bbc8816 437 Values larger than those that can be represented by this kind are
8e2caf1e 438 unchanged, as they will not be accurate enough to represent the
4bbc8816 439 rounding.
4ee9c684 440 huge = HUGE (KIND (a))
441 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
442 */
443
444static void
8a1417cb 445gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
4ee9c684 446{
447 tree type;
448 tree itype;
ea8ac4ce 449 tree arg[2];
4ee9c684 450 tree tmp;
451 tree cond;
a80ae91c 452 tree decl;
4b1085db 453 mpfr_t huge;
ea8ac4ce 454 int n, nargs;
4ee9c684 455 int kind;
456
457 kind = expr->ts.kind;
15da0ca7 458 nargs = gfc_intrinsic_argument_list_length (expr);
4ee9c684 459
a80ae91c 460 decl = NULL_TREE;
4ee9c684 461 /* We have builtin functions for some cases. */
462 switch (op)
463 {
8a1417cb 464 case RND_ROUND:
808656b4 465 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
4ee9c684 466 break;
467
8a1417cb 468 case RND_TRUNC:
808656b4 469 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
4bbc8816 470 break;
471
472 default:
473 gcc_unreachable ();
4ee9c684 474 }
475
476 /* Evaluate the argument. */
22d678e8 477 gcc_assert (expr->value.function.actual->expr);
ea8ac4ce 478 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
4ee9c684 479
480 /* Use a builtin function if one exists. */
a80ae91c 481 if (decl != NULL_TREE)
4ee9c684 482 {
a80ae91c 483 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
4ee9c684 484 return;
485 }
486
487 /* This code is probably redundant, but we'll keep it lying around just
488 in case. */
489 type = gfc_typenode_for_spec (&expr->ts);
ea8ac4ce 490 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
4ee9c684 491
492 /* Test if the value is too large to handle sensibly. */
4b1085db 493 gfc_set_model_kind (kind);
494 mpfr_init (huge);
f2d4ef3b 495 n = gfc_validate_kind (BT_INTEGER, kind, false);
4b1085db 496 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
2b6bc4f2 497 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
6f5c9335 498 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, arg[0],
499 tmp);
4ee9c684 500
4b1085db 501 mpfr_neg (huge, huge, GFC_RND_MODE);
2b6bc4f2 502 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
6f5c9335 503 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, arg[0],
504 tmp);
505 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
506 cond, tmp);
4ee9c684 507 itype = gfc_get_int_type (kind);
508
ea8ac4ce 509 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
4ee9c684 510 tmp = convert (type, tmp);
6f5c9335 511 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
512 arg[0]);
4b1085db 513 mpfr_clear (huge);
4ee9c684 514}
515
516
517/* Convert to an integer using the specified rounding mode. */
518
519static void
8a1417cb 520gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
4ee9c684 521{
522 tree type;
99614c0d 523 tree *args;
524 int nargs;
4ee9c684 525
99614c0d 526 nargs = gfc_intrinsic_argument_list_length (expr);
86b32f71 527 args = XALLOCAVEC (tree, nargs);
99614c0d 528
529 /* Evaluate the argument, we process all arguments even though we only
530 use the first one for code generation purposes. */
4ee9c684 531 type = gfc_typenode_for_spec (&expr->ts);
22d678e8 532 gcc_assert (expr->value.function.actual->expr);
99614c0d 533 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
4ee9c684 534
99614c0d 535 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
4ee9c684 536 {
537 /* Conversion to a different integer kind. */
99614c0d 538 se->expr = convert (type, args[0]);
4ee9c684 539 }
540 else
541 {
542 /* Conversion from complex to non-complex involves taking the real
543 component of the value. */
99614c0d 544 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
4ee9c684 545 && expr->ts.type != BT_COMPLEX)
546 {
547 tree artype;
548
99614c0d 549 artype = TREE_TYPE (TREE_TYPE (args[0]));
6f5c9335 550 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
551 args[0]);
4ee9c684 552 }
553
99614c0d 554 se->expr = build_fix_expr (&se->pre, args[0], type, op);
4ee9c684 555 }
556}
557
558
559/* Get the imaginary component of a value. */
560
561static void
562gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
563{
564 tree arg;
565
5ddb0172 566 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6f5c9335 567 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
568 TREE_TYPE (TREE_TYPE (arg)), arg);
4ee9c684 569}
570
571
572/* Get the complex conjugate of a value. */
573
574static void
575gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
576{
577 tree arg;
578
5ddb0172 579 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6f5c9335 580 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
4ee9c684 581}
582
583
c6599767 584
585static tree
586define_quad_builtin (const char *name, tree type, bool is_const)
587{
588 tree fndecl;
589 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
590 type);
591
592 /* Mark the decl as external. */
593 DECL_EXTERNAL (fndecl) = 1;
594 TREE_PUBLIC (fndecl) = 1;
595
596 /* Mark it __attribute__((const)). */
597 TREE_READONLY (fndecl) = is_const;
598
599 rest_of_decl_compilation (fndecl, 1, 0);
600
601 return fndecl;
602}
603
604
605
4ee9c684 606/* Initialize function decls for library functions. The external functions
607 are created as required. Builtin functions are added here. */
608
609void
610gfc_build_intrinsic_lib_fndecls (void)
611{
612 gfc_intrinsic_map_t *m;
e8428f9c 613 tree quad_decls[END_BUILTINS + 1];
c6599767 614
615 if (gfc_real16_is_float128)
616 {
617 /* If we have soft-float types, we create the decls for their
618 C99-like library functions. For now, we only handle __float128
619 q-suffixed functions. */
620
cfcdd3f1 621 tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
f5fdea80 622 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
c6599767 623
e8428f9c 624 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
c6599767 625
cfcdd3f1 626 type = float128_type_node;
627 complex_type = complex_float128_type_node;
c6599767 628 /* type (*) (type) */
cfcdd3f1 629 func_1 = build_function_type_list (type, type, NULL_TREE);
f5fdea80 630 /* int (*) (type) */
631 func_iround = build_function_type_list (integer_type_node,
632 type, NULL_TREE);
c6599767 633 /* long (*) (type) */
cfcdd3f1 634 func_lround = build_function_type_list (long_integer_type_node,
635 type, NULL_TREE);
c6599767 636 /* long long (*) (type) */
cfcdd3f1 637 func_llround = build_function_type_list (long_long_integer_type_node,
638 type, NULL_TREE);
c6599767 639 /* type (*) (type, type) */
cfcdd3f1 640 func_2 = build_function_type_list (type, type, type, NULL_TREE);
c6599767 641 /* type (*) (type, &int) */
cfcdd3f1 642 func_frexp
643 = build_function_type_list (type,
644 type,
645 build_pointer_type (integer_type_node),
646 NULL_TREE);
c6599767 647 /* type (*) (type, int) */
cfcdd3f1 648 func_scalbn = build_function_type_list (type,
649 type, integer_type_node, NULL_TREE);
c6599767 650 /* type (*) (complex type) */
cfcdd3f1 651 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
808656b4 652 /* complex type (*) (complex type, complex type) */
cfcdd3f1 653 func_cpow
654 = build_function_type_list (complex_type,
655 complex_type, complex_type, NULL_TREE);
c6599767 656
657#define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
658#define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
659#define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
660
661 /* Only these built-ins are actually needed here. These are used directly
662 from the code, when calling builtin_decl_for_precision() or
663 builtin_decl_for_float_type(). The others are all constructed by
664 gfc_get_intrinsic_lib_fndecl(). */
665#define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
666 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
667
668#include "mathbuiltins.def"
669
670#undef OTHER_BUILTIN
671#undef LIB_FUNCTION
672#undef DEFINE_MATH_BUILTIN
673#undef DEFINE_MATH_BUILTIN_C
674
675 }
4ee9c684 676
677 /* Add GCC builtin functions. */
a80ae91c 678 for (m = gfc_intrinsic_map;
679 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
680 {
681 if (m->float_built_in != END_BUILTINS)
b9a16870 682 m->real4_decl = builtin_decl_explicit (m->float_built_in);
a80ae91c 683 if (m->complex_float_built_in != END_BUILTINS)
b9a16870 684 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
a80ae91c 685 if (m->double_built_in != END_BUILTINS)
b9a16870 686 m->real8_decl = builtin_decl_explicit (m->double_built_in);
a80ae91c 687 if (m->complex_double_built_in != END_BUILTINS)
b9a16870 688 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
a80ae91c 689
690 /* If real(kind=10) exists, it is always long double. */
691 if (m->long_double_built_in != END_BUILTINS)
b9a16870 692 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
a80ae91c 693 if (m->complex_long_double_built_in != END_BUILTINS)
b9a16870 694 m->complex10_decl
695 = builtin_decl_explicit (m->complex_long_double_built_in);
a80ae91c 696
c6599767 697 if (!gfc_real16_is_float128)
698 {
699 if (m->long_double_built_in != END_BUILTINS)
b9a16870 700 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
c6599767 701 if (m->complex_long_double_built_in != END_BUILTINS)
b9a16870 702 m->complex16_decl
703 = builtin_decl_explicit (m->complex_long_double_built_in);
c6599767 704 }
705 else if (quad_decls[m->double_built_in] != NULL_TREE)
706 {
707 /* Quad-precision function calls are constructed when first
708 needed by builtin_decl_for_precision(), except for those
709 that will be used directly (define by OTHER_BUILTIN). */
710 m->real16_decl = quad_decls[m->double_built_in];
711 }
712 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
713 {
714 /* Same thing for the complex ones. */
715 m->complex16_decl = quad_decls[m->double_built_in];
c6599767 716 }
4ee9c684 717 }
718}
719
720
721/* Create a fndecl for a simple intrinsic library function. */
722
723static tree
724gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
725{
726 tree type;
f1f41a6c 727 vec<tree, va_gc> *argtypes;
4ee9c684 728 tree fndecl;
729 gfc_actual_arglist *actual;
730 tree *pdecl;
731 gfc_typespec *ts;
732 char name[GFC_MAX_SYMBOL_LEN + 3];
733
734 ts = &expr->ts;
735 if (ts->type == BT_REAL)
736 {
737 switch (ts->kind)
738 {
739 case 4:
740 pdecl = &m->real4_decl;
741 break;
742 case 8:
743 pdecl = &m->real8_decl;
744 break;
920e54ef 745 case 10:
746 pdecl = &m->real10_decl;
747 break;
748 case 16:
749 pdecl = &m->real16_decl;
750 break;
4ee9c684 751 default:
22d678e8 752 gcc_unreachable ();
4ee9c684 753 }
754 }
755 else if (ts->type == BT_COMPLEX)
756 {
22d678e8 757 gcc_assert (m->complex_available);
4ee9c684 758
759 switch (ts->kind)
760 {
761 case 4:
762 pdecl = &m->complex4_decl;
763 break;
764 case 8:
765 pdecl = &m->complex8_decl;
766 break;
920e54ef 767 case 10:
768 pdecl = &m->complex10_decl;
769 break;
770 case 16:
771 pdecl = &m->complex16_decl;
772 break;
4ee9c684 773 default:
22d678e8 774 gcc_unreachable ();
4ee9c684 775 }
776 }
777 else
22d678e8 778 gcc_unreachable ();
4ee9c684 779
780 if (*pdecl)
781 return *pdecl;
782
783 if (m->libm_name)
784 {
a80ae91c 785 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
786 if (gfc_real_kinds[n].c_float)
112f3d57 787 snprintf (name, sizeof (name), "%s%s%s",
a80ae91c 788 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
789 else if (gfc_real_kinds[n].c_double)
112f3d57 790 snprintf (name, sizeof (name), "%s%s",
a80ae91c 791 ts->type == BT_COMPLEX ? "c" : "", m->name);
792 else if (gfc_real_kinds[n].c_long_double)
793 snprintf (name, sizeof (name), "%s%s%s",
794 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
c6599767 795 else if (gfc_real_kinds[n].c_float128)
796 snprintf (name, sizeof (name), "%s%s%s",
797 ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
112f3d57 798 else
a80ae91c 799 gcc_unreachable ();
4ee9c684 800 }
801 else
802 {
803 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
804 ts->type == BT_COMPLEX ? 'c' : 'r',
805 ts->kind);
806 }
807
5edc3af9 808 argtypes = NULL;
4ee9c684 809 for (actual = expr->value.function.actual; actual; actual = actual->next)
810 {
811 type = gfc_typenode_for_spec (&actual->expr->ts);
f1f41a6c 812 vec_safe_push (argtypes, type);
4ee9c684 813 }
5edc3af9 814 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
e60a6f7b 815 fndecl = build_decl (input_location,
816 FUNCTION_DECL, get_identifier (name), type);
4ee9c684 817
818 /* Mark the decl as external. */
819 DECL_EXTERNAL (fndecl) = 1;
820 TREE_PUBLIC (fndecl) = 1;
821
822 /* Mark it __attribute__((const)), if possible. */
823 TREE_READONLY (fndecl) = m->is_constant;
824
b2c4af5e 825 rest_of_decl_compilation (fndecl, 1, 0);
4ee9c684 826
827 (*pdecl) = fndecl;
828 return fndecl;
829}
830
831
832/* Convert an intrinsic function into an external or builtin call. */
833
834static void
835gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
836{
837 gfc_intrinsic_map_t *m;
4ee9c684 838 tree fndecl;
5ddb0172 839 tree rettype;
840 tree *args;
841 unsigned int num_args;
55cb4417 842 gfc_isym_id id;
4ee9c684 843
55cb4417 844 id = expr->value.function.isym->id;
4ee9c684 845 /* Find the entry for this function. */
a80ae91c 846 for (m = gfc_intrinsic_map;
847 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
4ee9c684 848 {
849 if (id == m->id)
850 break;
851 }
852
853 if (m->id == GFC_ISYM_NONE)
854 {
855 internal_error ("Intrinsic function %s(%d) not recognized",
856 expr->value.function.name, id);
857 }
858
859 /* Get the decl and generate the call. */
5ddb0172 860 num_args = gfc_intrinsic_argument_list_length (expr);
86b32f71 861 args = XALLOCAVEC (tree, num_args);
5ddb0172 862
863 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4ee9c684 864 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
5ddb0172 865 rettype = TREE_TYPE (TREE_TYPE (fndecl));
866
867 fndecl = build_addr (fndecl, current_function_decl);
389dd41b 868 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
4ee9c684 869}
870
f24d382c 871
872/* If bounds-checking is enabled, create code to verify at runtime that the
873 string lengths for both expressions are the same (needed for e.g. MERGE).
874 If bounds-checking is not enabled, does nothing. */
875
9c5786bd 876void
877gfc_trans_same_strlen_check (const char* intr_name, locus* where,
878 tree a, tree b, stmtblock_t* target)
f24d382c 879{
880 tree cond;
881 tree name;
882
883 /* If bounds-checking is disabled, do nothing. */
ad8ed98e 884 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
f24d382c 885 return;
886
887 /* Compare the two string lengths. */
6f5c9335 888 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, a, b);
f24d382c 889
890 /* Output the runtime-check. */
891 name = gfc_build_cstring_const (intr_name);
892 name = gfc_build_addr_expr (pchar_type_node, name);
893 gfc_trans_runtime_check (true, false, cond, target, where,
9c5786bd 894 "Unequal character lengths (%ld/%ld) in %s",
f24d382c 895 fold_convert (long_integer_type_node, a),
896 fold_convert (long_integer_type_node, b), name);
897}
898
899
34e106da 900/* The EXPONENT(s) intrinsic function is translated into
901 int ret;
902 frexp (s, &ret);
903 return ret;
904 */
4ee9c684 905
906static void
9dd6c589 907gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
4ee9c684 908{
a80ae91c 909 tree arg, type, res, tmp, frexp;
4ee9c684 910
808656b4 911 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
a80ae91c 912 expr->value.function.actual->expr->ts.kind);
4ee9c684 913
34e106da 914 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
915
916 res = gfc_create_var (integer_type_node, NULL);
a80ae91c 917 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
918 gfc_build_addr_expr (NULL_TREE, res));
34e106da 919 gfc_add_expr_to_block (&se->pre, tmp);
920
9dd6c589 921 type = gfc_typenode_for_spec (&expr->ts);
34e106da 922 se->expr = fold_convert (type, res);
4ee9c684 923}
924
09800dba 925
70b5944a 926static void
2e34dcd8 927trans_this_image (gfc_se * se, gfc_expr *expr)
70b5944a 928{
2e34dcd8 929 stmtblock_t loop;
930 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
931 lbound, ubound, extent, ml;
932 gfc_se argse;
2e34dcd8 933 int rank, corank;
934
935 /* The case -fcoarray=single is handled elsewhere. */
936 gcc_assert (gfc_option.coarray != GFC_FCOARRAY_SINGLE);
937
642970a3 938 gfc_init_coarray_decl (false);
2e34dcd8 939
940 /* Argument-free version: THIS_IMAGE(). */
941 if (expr->value.function.actual->expr == NULL)
942 {
9a457ae7 943 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
944 gfort_gvar_caf_this_image);
2e34dcd8 945 return;
946 }
947
948 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
949
950 type = gfc_get_int_type (gfc_default_integer_kind);
951 corank = gfc_get_corank (expr->value.function.actual->expr);
952 rank = expr->value.function.actual->expr->rank;
953
954 /* Obtain the descriptor of the COARRAY. */
955 gfc_init_se (&argse, NULL);
636321de 956 argse.want_coarray = 1;
5d34a30f 957 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
2e34dcd8 958 gfc_add_block_to_block (&se->pre, &argse.pre);
959 gfc_add_block_to_block (&se->post, &argse.post);
960 desc = argse.expr;
961
962 if (se->ss)
963 {
964 /* Create an implicit second parameter from the loop variable. */
965 gcc_assert (!expr->value.function.actual->next->expr);
966 gcc_assert (corank > 0);
967 gcc_assert (se->loop->dimen == 1);
bfa43780 968 gcc_assert (se->ss->info->expr == expr);
2e34dcd8 969
970 dim_arg = se->loop->loopvar[0];
971 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
972 gfc_array_index_type, dim_arg,
69777e5d 973 build_int_cst (TREE_TYPE (dim_arg), 1));
2e34dcd8 974 gfc_advance_se_ss_chain (se);
975 }
976 else
977 {
978 /* Use the passed DIM= argument. */
979 gcc_assert (expr->value.function.actual->next->expr);
980 gfc_init_se (&argse, NULL);
981 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
982 gfc_array_index_type);
983 gfc_add_block_to_block (&se->pre, &argse.pre);
984 dim_arg = argse.expr;
985
986 if (INTEGER_CST_P (dim_arg))
987 {
988 int hi, co_dim;
989
990 hi = TREE_INT_CST_HIGH (dim_arg);
991 co_dim = TREE_INT_CST_LOW (dim_arg);
992 if (hi || co_dim < 1
993 || co_dim > GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc)))
994 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
995 "dimension index", expr->value.function.isym->name,
996 &expr->where);
997 }
998 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
999 {
1000 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
1001 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1002 dim_arg,
1003 build_int_cst (TREE_TYPE (dim_arg), 1));
1004 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
1005 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1006 dim_arg, tmp);
1007 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1008 boolean_type_node, cond, tmp);
1009 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1010 gfc_msg_fault);
1011 }
1012 }
1013
1014 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
1015 one always has a dim_arg argument.
1016
9a457ae7 1017 m = this_image() - 1
bfc5d51b 1018 if (corank == 1)
1019 {
1020 sub(1) = m + lcobound(corank)
1021 return;
1022 }
2e34dcd8 1023 i = rank
69777e5d 1024 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2e34dcd8 1025 for (;;)
1026 {
1027 extent = gfc_extent(i)
1028 ml = m
1029 m = m/extent
1030 if (i >= min_var)
1031 goto exit_label
1032 i++
1033 }
1034 exit_label:
1035 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
1036 : m + lcobound(corank)
1037 */
1038
bfc5d51b 1039 /* this_image () - 1. */
1040 tmp = fold_convert (type, gfort_gvar_caf_this_image);
1041 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, tmp,
1042 build_int_cst (type, 1));
1043 if (corank == 1)
1044 {
1045 /* sub(1) = m + lcobound(corank). */
1046 lbound = gfc_conv_descriptor_lbound_get (desc,
1047 build_int_cst (TREE_TYPE (gfc_array_index_type),
1048 corank+rank-1));
1049 lbound = fold_convert (type, lbound);
1050 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
1051
1052 se->expr = tmp;
1053 return;
1054 }
1055
2e34dcd8 1056 m = gfc_create_var (type, NULL);
1057 ml = gfc_create_var (type, NULL);
1058 loop_var = gfc_create_var (integer_type_node, NULL);
1059 min_var = gfc_create_var (integer_type_node, NULL);
1060
1061 /* m = this_image () - 1. */
2e34dcd8 1062 gfc_add_modify (&se->pre, m, tmp);
1063
69777e5d 1064 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
1065 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
1066 fold_convert (integer_type_node, dim_arg),
1067 build_int_cst (integer_type_node, rank - 1));
2e34dcd8 1068 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
1069 build_int_cst (integer_type_node, rank + corank - 2),
69777e5d 1070 tmp);
2e34dcd8 1071 gfc_add_modify (&se->pre, min_var, tmp);
1072
1073 /* i = rank. */
1074 tmp = build_int_cst (integer_type_node, rank);
1075 gfc_add_modify (&se->pre, loop_var, tmp);
1076
1077 exit_label = gfc_build_label_decl (NULL_TREE);
1078 TREE_USED (exit_label) = 1;
1079
1080 /* Loop body. */
1081 gfc_init_block (&loop);
1082
1083 /* ml = m. */
1084 gfc_add_modify (&loop, ml, m);
1085
1086 /* extent = ... */
1087 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
1088 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
1089 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1090 extent = fold_convert (type, extent);
1091
1092 /* m = m/extent. */
1093 gfc_add_modify (&loop, m,
1094 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
1095 m, extent));
1096
1097 /* Exit condition: if (i >= min_var) goto exit_label. */
1098 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, loop_var,
1099 min_var);
1100 tmp = build1_v (GOTO_EXPR, exit_label);
1101 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
1102 build_empty_stmt (input_location));
1103 gfc_add_expr_to_block (&loop, tmp);
1104
1105 /* Increment loop variable: i++. */
1106 gfc_add_modify (&loop, loop_var,
1107 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
1108 loop_var,
1109 build_int_cst (integer_type_node, 1)));
1110
1111 /* Making the loop... actually loop! */
1112 tmp = gfc_finish_block (&loop);
1113 tmp = build1_v (LOOP_EXPR, tmp);
1114 gfc_add_expr_to_block (&se->pre, tmp);
1115
1116 /* The exit label. */
1117 tmp = build1_v (LABEL_EXPR, exit_label);
1118 gfc_add_expr_to_block (&se->pre, tmp);
1119
1120 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
1121 : m + lcobound(corank) */
1122
1123 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, dim_arg,
1124 build_int_cst (TREE_TYPE (dim_arg), corank));
1125
1126 lbound = gfc_conv_descriptor_lbound_get (desc,
69777e5d 1127 fold_build2_loc (input_location, PLUS_EXPR,
1128 gfc_array_index_type, dim_arg,
1129 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
2e34dcd8 1130 lbound = fold_convert (type, lbound);
1131
1132 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
1133 fold_build2_loc (input_location, MULT_EXPR, type,
1134 m, extent));
1135 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
1136
1137 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
1138 fold_build2_loc (input_location, PLUS_EXPR, type,
1139 m, lbound));
70b5944a 1140}
1141
09800dba 1142
1143static void
1144trans_image_index (gfc_se * se, gfc_expr *expr)
1145{
1146 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
1147 tmp, invalid_bound;
1148 gfc_se argse, subse;
09800dba 1149 int rank, corank, codim;
1150
1151 type = gfc_get_int_type (gfc_default_integer_kind);
1152 corank = gfc_get_corank (expr->value.function.actual->expr);
1153 rank = expr->value.function.actual->expr->rank;
1154
1155 /* Obtain the descriptor of the COARRAY. */
1156 gfc_init_se (&argse, NULL);
636321de 1157 argse.want_coarray = 1;
5d34a30f 1158 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
09800dba 1159 gfc_add_block_to_block (&se->pre, &argse.pre);
1160 gfc_add_block_to_block (&se->post, &argse.post);
1161 desc = argse.expr;
1162
1163 /* Obtain a handle to the SUB argument. */
1164 gfc_init_se (&subse, NULL);
5d34a30f 1165 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
09800dba 1166 gfc_add_block_to_block (&se->pre, &subse.pre);
1167 gfc_add_block_to_block (&se->post, &subse.post);
1168 subdesc = build_fold_indirect_ref_loc (input_location,
1169 gfc_conv_descriptor_data_get (subse.expr));
1170
1171 /* Fortran 2008 does not require that the values remain in the cobounds,
1172 thus we need explicitly check this - and return 0 if they are exceeded. */
1173
1174 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
1175 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
1176 invalid_bound = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1177 fold_convert (gfc_array_index_type, tmp),
1178 lbound);
1179
1180 for (codim = corank + rank - 2; codim >= rank; codim--)
1181 {
1182 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1183 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
1184 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
1185 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1186 fold_convert (gfc_array_index_type, tmp),
1187 lbound);
1188 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1189 boolean_type_node, invalid_bound, cond);
1190 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1191 fold_convert (gfc_array_index_type, tmp),
1192 ubound);
1193 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1194 boolean_type_node, invalid_bound, cond);
1195 }
1196
1197 invalid_bound = gfc_unlikely (invalid_bound);
1198
1199
1200 /* See Fortran 2008, C.10 for the following algorithm. */
1201
1202 /* coindex = sub(corank) - lcobound(n). */
1203 coindex = fold_convert (gfc_array_index_type,
1204 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
1205 NULL));
1206 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
1207 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1208 fold_convert (gfc_array_index_type, coindex),
1209 lbound);
1210
1211 for (codim = corank + rank - 2; codim >= rank; codim--)
1212 {
1213 tree extent, ubound;
1214
1215 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
1216 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1217 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
1218 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1219
1220 /* coindex *= extent. */
1221 coindex = fold_build2_loc (input_location, MULT_EXPR,
1222 gfc_array_index_type, coindex, extent);
1223
1224 /* coindex += sub(codim). */
1225 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
1226 coindex = fold_build2_loc (input_location, PLUS_EXPR,
1227 gfc_array_index_type, coindex,
1228 fold_convert (gfc_array_index_type, tmp));
1229
1230 /* coindex -= lbound(codim). */
1231 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
1232 coindex = fold_build2_loc (input_location, MINUS_EXPR,
1233 gfc_array_index_type, coindex, lbound);
1234 }
1235
1236 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
1237 fold_convert(type, coindex),
1238 build_int_cst (type, 1));
1239
1240 /* Return 0 if "coindex" exceeds num_images(). */
1241
1242 if (gfc_option.coarray == GFC_FCOARRAY_SINGLE)
1243 num_images = build_int_cst (type, 1);
1244 else
1245 {
642970a3 1246 gfc_init_coarray_decl (false);
9a457ae7 1247 num_images = fold_convert (type, gfort_gvar_caf_num_images);
09800dba 1248 }
1249
1250 tmp = gfc_create_var (type, NULL);
1251 gfc_add_modify (&se->pre, tmp, coindex);
1252
1253 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, tmp,
1254 num_images);
1255 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
1256 cond,
1257 fold_convert (boolean_type_node, invalid_bound));
1258 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
1259 build_int_cst (type, 0), tmp);
1260}
1261
1262
70b5944a 1263static void
1264trans_num_images (gfc_se * se)
1265{
642970a3 1266 gfc_init_coarray_decl (false);
9a457ae7 1267 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
1268 gfort_gvar_caf_num_images);
70b5944a 1269}
1270
076094b7 1271
90342c73 1272static void
1273gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
1274{
1275 gfc_se argse;
90342c73 1276
90342c73 1277 gfc_init_se (&argse, NULL);
1278 argse.data_not_needed = 1;
f00f6dd6 1279 argse.descriptor_only = 1;
90342c73 1280
5d34a30f 1281 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
90342c73 1282 gfc_add_block_to_block (&se->pre, &argse.pre);
1283 gfc_add_block_to_block (&se->post, &argse.post);
f00f6dd6 1284
edc4866f 1285 se->expr = gfc_conv_descriptor_rank (argse.expr);
90342c73 1286}
1287
1288
4ee9c684 1289/* Evaluate a single upper or lower bound. */
231e961a 1290/* TODO: bound intrinsic generates way too much unnecessary code. */
4ee9c684 1291
1292static void
1293gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
1294{
1295 gfc_actual_arglist *arg;
1296 gfc_actual_arglist *arg2;
1297 tree desc;
1298 tree type;
1299 tree bound;
1300 tree tmp;
66a56860 1301 tree cond, cond1, cond3, cond4, size;
c6a41748 1302 tree ubound;
1303 tree lbound;
4ee9c684 1304 gfc_se argse;
c6a41748 1305 gfc_array_spec * as;
9b58b4c7 1306 bool assumed_rank_lb_one;
4ee9c684 1307
4ee9c684 1308 arg = expr->value.function.actual;
1309 arg2 = arg->next;
1310
1311 if (se->ss)
1312 {
1313 /* Create an implicit second parameter from the loop variable. */
22d678e8 1314 gcc_assert (!arg2->expr);
1315 gcc_assert (se->loop->dimen == 1);
bfa43780 1316 gcc_assert (se->ss->info->expr == expr);
4ee9c684 1317 gfc_advance_se_ss_chain (se);
1318 bound = se->loop->loopvar[0];
6f5c9335 1319 bound = fold_build2_loc (input_location, MINUS_EXPR,
1320 gfc_array_index_type, bound,
1321 se->loop->from[0]);
4ee9c684 1322 }
1323 else
1324 {
1325 /* use the passed argument. */
076094b7 1326 gcc_assert (arg2->expr);
4ee9c684 1327 gfc_init_se (&argse, NULL);
076094b7 1328 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
4ee9c684 1329 gfc_add_block_to_block (&se->pre, &argse.pre);
1330 bound = argse.expr;
1331 /* Convert from one based to zero based. */
6f5c9335 1332 bound = fold_build2_loc (input_location, MINUS_EXPR,
1333 gfc_array_index_type, bound,
1334 gfc_index_one_node);
4ee9c684 1335 }
1336
1337 /* TODO: don't re-evaluate the descriptor on each iteration. */
1338 /* Get a descriptor for the first parameter. */
ec9200dc 1339 gfc_init_se (&argse, NULL);
5d34a30f 1340 gfc_conv_expr_descriptor (&argse, arg->expr);
4ee9c684 1341 gfc_add_block_to_block (&se->pre, &argse.pre);
1342 gfc_add_block_to_block (&se->post, &argse.post);
1343
1344 desc = argse.expr;
1345
9b58b4c7 1346 as = gfc_get_full_arrayspec_from_expr (arg->expr);
1347
4ee9c684 1348 if (INTEGER_CST_P (bound))
1349 {
09d71cee 1350 int hi, low;
1351
1352 hi = TREE_INT_CST_HIGH (bound);
1353 low = TREE_INT_CST_LOW (bound);
9b58b4c7 1354 if (hi || low < 0
1355 || ((!as || as->type != AS_ASSUMED_RANK)
1356 && low >= GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)))
1357 || low > GFC_MAX_DIMENSIONS)
09d71cee 1358 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
1359 "dimension index", upper ? "UBOUND" : "LBOUND",
1360 &expr->where);
4ee9c684 1361 }
9b58b4c7 1362
1363 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
4ee9c684 1364 {
ad8ed98e 1365 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4ee9c684 1366 {
1367 bound = gfc_evaluate_now (bound, &se->pre);
6f5c9335 1368 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1369 bound, build_int_cst (TREE_TYPE (bound), 0));
9b58b4c7 1370 if (as && as->type == AS_ASSUMED_RANK)
edc4866f 1371 tmp = gfc_conv_descriptor_rank (desc);
9b58b4c7 1372 else
1373 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
6f5c9335 1374 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
9b58b4c7 1375 bound, fold_convert(TREE_TYPE (bound), tmp));
6f5c9335 1376 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1377 boolean_type_node, cond, tmp);
da6ffc6d 1378 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1379 gfc_msg_fault);
4ee9c684 1380 }
1381 }
1382
9b58b4c7 1383 /* Take care of the lbound shift for assumed-rank arrays, which are
1384 nonallocatable and nonpointers. Those has a lbound of 1. */
1385 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
1386 && ((arg->expr->ts.type != BT_CLASS
1387 && !arg->expr->symtree->n.sym->attr.allocatable
1388 && !arg->expr->symtree->n.sym->attr.pointer)
1389 || (arg->expr->ts.type == BT_CLASS
1390 && !CLASS_DATA (arg->expr)->attr.allocatable
1391 && !CLASS_DATA (arg->expr)->attr.class_pointer));
1392
6b1a9af3 1393 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
1394 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
c6a41748 1395
c6a41748 1396 /* 13.14.53: Result value for LBOUND
1397
1398 Case (i): For an array section or for an array expression other than a
1399 whole array or array structure component, LBOUND(ARRAY, DIM)
1400 has the value 1. For a whole array or array structure
1401 component, LBOUND(ARRAY, DIM) has the value:
1402 (a) equal to the lower bound for subscript DIM of ARRAY if
1403 dimension DIM of ARRAY does not have extent zero
1404 or if ARRAY is an assumed-size array of rank DIM,
1405 or (b) 1 otherwise.
1406
1407 13.14.113: Result value for UBOUND
1408
1409 Case (i): For an array section or for an array expression other than a
1410 whole array or array structure component, UBOUND(ARRAY, DIM)
1411 has the value equal to the number of elements in the given
1412 dimension; otherwise, it has a value equal to the upper bound
1413 for subscript DIM of ARRAY if dimension DIM of ARRAY does
1414 not have size zero and has value zero if dimension DIM has
1415 size zero. */
1416
9b58b4c7 1417 if (!upper && assumed_rank_lb_one)
1418 se->expr = gfc_index_one_node;
1419 else if (as)
c6a41748 1420 {
6b1a9af3 1421 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
09d71cee 1422
6f5c9335 1423 cond1 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1424 ubound, lbound);
1425 cond3 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
1426 stride, gfc_index_zero_node);
1427 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1428 boolean_type_node, cond3, cond1);
1429 cond4 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1430 stride, gfc_index_zero_node);
c6a41748 1431
1432 if (upper)
1433 {
0163eeb8 1434 tree cond5;
6f5c9335 1435 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1436 boolean_type_node, cond3, cond4);
1437 cond5 = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1438 gfc_index_one_node, lbound);
1439 cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1440 boolean_type_node, cond4, cond5);
1441
1442 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1443 boolean_type_node, cond, cond5);
1444
9b58b4c7 1445 if (assumed_rank_lb_one)
1446 {
1447 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1448 gfc_array_index_type, ubound, lbound);
1449 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1450 gfc_array_index_type, tmp, gfc_index_one_node);
1451 }
1452 else
1453 tmp = ubound;
1454
6f5c9335 1455 se->expr = fold_build3_loc (input_location, COND_EXPR,
1456 gfc_array_index_type, cond,
9b58b4c7 1457 tmp, gfc_index_zero_node);
c6a41748 1458 }
1459 else
1460 {
1461 if (as->type == AS_ASSUMED_SIZE)
6f5c9335 1462 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1463 bound, build_int_cst (TREE_TYPE (bound),
1464 arg->expr->rank - 1));
c6a41748 1465 else
1466 cond = boolean_false_node;
1467
6f5c9335 1468 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1469 boolean_type_node, cond3, cond4);
1470 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1471 boolean_type_node, cond, cond1);
c6a41748 1472
6f5c9335 1473 se->expr = fold_build3_loc (input_location, COND_EXPR,
1474 gfc_array_index_type, cond,
1475 lbound, gfc_index_one_node);
c6a41748 1476 }
1477 }
1478 else
1479 {
1480 if (upper)
1481 {
6f5c9335 1482 size = fold_build2_loc (input_location, MINUS_EXPR,
1483 gfc_array_index_type, ubound, lbound);
1484 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
1485 gfc_array_index_type, size,
c6a41748 1486 gfc_index_one_node);
6f5c9335 1487 se->expr = fold_build2_loc (input_location, MAX_EXPR,
1488 gfc_array_index_type, se->expr,
1489 gfc_index_zero_node);
c6a41748 1490 }
1491 else
1492 se->expr = gfc_index_one_node;
1493 }
4ee9c684 1494
1495 type = gfc_typenode_for_spec (&expr->ts);
1496 se->expr = convert (type, se->expr);
1497}
1498
1499
076094b7 1500static void
1501conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
1502{
1503 gfc_actual_arglist *arg;
1504 gfc_actual_arglist *arg2;
1505 gfc_se argse;
076094b7 1506 tree bound, resbound, resbound2, desc, cond, tmp;
1507 tree type;
076094b7 1508 int corank;
1509
1510 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
1511 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
1512 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
1513
1514 arg = expr->value.function.actual;
1515 arg2 = arg->next;
1516
1517 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
1518 corank = gfc_get_corank (arg->expr);
1519
076094b7 1520 gfc_init_se (&argse, NULL);
636321de 1521 argse.want_coarray = 1;
076094b7 1522
5d34a30f 1523 gfc_conv_expr_descriptor (&argse, arg->expr);
076094b7 1524 gfc_add_block_to_block (&se->pre, &argse.pre);
1525 gfc_add_block_to_block (&se->post, &argse.post);
1526 desc = argse.expr;
1527
1528 if (se->ss)
1529 {
076094b7 1530 /* Create an implicit second parameter from the loop variable. */
1531 gcc_assert (!arg2->expr);
1532 gcc_assert (corank > 0);
1533 gcc_assert (se->loop->dimen == 1);
bfa43780 1534 gcc_assert (se->ss->info->expr == expr);
076094b7 1535
076094b7 1536 bound = se->loop->loopvar[0];
bee1af95 1537 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2e34dcd8 1538 bound, gfc_rank_cst[arg->expr->rank]);
076094b7 1539 gfc_advance_se_ss_chain (se);
1540 }
1541 else
1542 {
1543 /* use the passed argument. */
1544 gcc_assert (arg2->expr);
1545 gfc_init_se (&argse, NULL);
1546 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
1547 gfc_add_block_to_block (&se->pre, &argse.pre);
1548 bound = argse.expr;
1549
1550 if (INTEGER_CST_P (bound))
1551 {
1552 int hi, low;
1553
1554 hi = TREE_INT_CST_HIGH (bound);
1555 low = TREE_INT_CST_LOW (bound);
1556 if (hi || low < 1 || low > GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc)))
1557 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
1558 "dimension index", expr->value.function.isym->name,
1559 &expr->where);
1560 }
1561 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1562 {
1563 bound = gfc_evaluate_now (bound, &se->pre);
bee1af95 1564 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1565 bound, build_int_cst (TREE_TYPE (bound), 1));
076094b7 1566 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
bee1af95 1567 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1568 bound, tmp);
1569 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1570 boolean_type_node, cond, tmp);
076094b7 1571 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
1572 gfc_msg_fault);
1573 }
1574
1575
df084314 1576 /* Subtract 1 to get to zero based and add dimensions. */
076094b7 1577 switch (arg->expr->rank)
1578 {
1579 case 0:
bee1af95 1580 bound = fold_build2_loc (input_location, MINUS_EXPR,
1581 gfc_array_index_type, bound,
1582 gfc_index_one_node);
076094b7 1583 case 1:
1584 break;
1585 default:
bee1af95 1586 bound = fold_build2_loc (input_location, PLUS_EXPR,
1587 gfc_array_index_type, bound,
1588 gfc_rank_cst[arg->expr->rank - 1]);
076094b7 1589 }
1590 }
1591
1592 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
1593
bee1af95 1594 /* Handle UCOBOUND with special handling of the last codimension. */
076094b7 1595 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
1596 {
bee1af95 1597 /* Last codimension: For -fcoarray=single just return
1598 the lcobound - otherwise add
1599 ceiling (real (num_images ()) / real (size)) - 1
1600 = (num_images () + size - 1) / size - 1
1601 = (num_images - 1) / size(),
09800dba 1602 where size is the product of the extent of all but the last
bee1af95 1603 codimension. */
1604
1605 if (gfc_option.coarray != GFC_FCOARRAY_SINGLE && corank > 1)
1606 {
1607 tree cosize;
1608
642970a3 1609 gfc_init_coarray_decl (false);
bee1af95 1610 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
1611
1612 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1613 gfc_array_index_type,
9a457ae7 1614 fold_convert (gfc_array_index_type,
1615 gfort_gvar_caf_num_images),
bee1af95 1616 build_int_cst (gfc_array_index_type, 1));
1617 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1618 gfc_array_index_type, tmp,
1619 fold_convert (gfc_array_index_type, cosize));
1620 resbound = fold_build2_loc (input_location, PLUS_EXPR,
1621 gfc_array_index_type, resbound, tmp);
1622 }
1623 else if (gfc_option.coarray != GFC_FCOARRAY_SINGLE)
1624 {
1625 /* ubound = lbound + num_images() - 1. */
642970a3 1626 gfc_init_coarray_decl (false);
bee1af95 1627 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1628 gfc_array_index_type,
9a457ae7 1629 fold_convert (gfc_array_index_type,
1630 gfort_gvar_caf_num_images),
bee1af95 1631 build_int_cst (gfc_array_index_type, 1));
1632 resbound = fold_build2_loc (input_location, PLUS_EXPR,
1633 gfc_array_index_type, resbound, tmp);
1634 }
1635
1636 if (corank > 1)
1637 {
1638 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1639 bound,
1640 build_int_cst (TREE_TYPE (bound),
1641 arg->expr->rank + corank - 1));
1642
1643 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
1644 se->expr = fold_build3_loc (input_location, COND_EXPR,
1645 gfc_array_index_type, cond,
1646 resbound, resbound2);
1647 }
1648 else
1649 se->expr = resbound;
076094b7 1650 }
1651 else
1652 se->expr = resbound;
1653
1654 type = gfc_typenode_for_spec (&expr->ts);
1655 se->expr = convert (type, se->expr);
1656}
1657
1658
4ee9c684 1659static void
1660gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
1661{
a80ae91c 1662 tree arg, cabs;
4ee9c684 1663
5ddb0172 1664 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4ee9c684 1665
1666 switch (expr->value.function.actual->expr->ts.type)
1667 {
1668 case BT_INTEGER:
1669 case BT_REAL:
6f5c9335 1670 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
1671 arg);
4ee9c684 1672 break;
1673
1674 case BT_COMPLEX:
808656b4 1675 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
a80ae91c 1676 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
4ee9c684 1677 break;
1678
1679 default:
22d678e8 1680 gcc_unreachable ();
4ee9c684 1681 }
1682}
1683
1684
1685/* Create a complex value from one or two real components. */
1686
1687static void
1688gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
1689{
4ee9c684 1690 tree real;
1691 tree imag;
1692 tree type;
5ddb0172 1693 tree *args;
1694 unsigned int num_args;
1695
1696 num_args = gfc_intrinsic_argument_list_length (expr);
86b32f71 1697 args = XALLOCAVEC (tree, num_args);
4ee9c684 1698
1699 type = gfc_typenode_for_spec (&expr->ts);
5ddb0172 1700 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
1701 real = convert (TREE_TYPE (type), args[0]);
4ee9c684 1702 if (both)
5ddb0172 1703 imag = convert (TREE_TYPE (type), args[1]);
1704 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
4ee9c684 1705 {
6f5c9335 1706 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
1707 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
4ee9c684 1708 imag = convert (TREE_TYPE (type), imag);
1709 }
1710 else
1711 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
1712
6f5c9335 1713 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
4ee9c684 1714}
1715
fa0323b8 1716
8241ce4f 1717/* Remainder function MOD(A, P) = A - INT(A / P) * P
fa0323b8 1718 MODULO(A, P) = A - FLOOR (A / P) * P
1719
1720 The obvious algorithms above are numerically instable for large
1721 arguments, hence these intrinsics are instead implemented via calls
1722 to the fmod family of functions. It is the responsibility of the
1723 user to ensure that the second argument is non-zero. */
4ee9c684 1724
1725static void
1726gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
1727{
4ee9c684 1728 tree type;
4ee9c684 1729 tree tmp;
4ee9c684 1730 tree test;
1731 tree test2;
a80ae91c 1732 tree fmod;
fa0323b8 1733 tree zero;
5ddb0172 1734 tree args[2];
4ee9c684 1735
5ddb0172 1736 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4ee9c684 1737
1738 switch (expr->ts.type)
1739 {
1740 case BT_INTEGER:
1741 /* Integer case is easy, we've got a builtin op. */
5ddb0172 1742 type = TREE_TYPE (args[0]);
54ad1b4d 1743
8241ce4f 1744 if (modulo)
6f5c9335 1745 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
1746 args[0], args[1]);
8241ce4f 1747 else
6f5c9335 1748 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
1749 args[0], args[1]);
4ee9c684 1750 break;
1751
1752 case BT_REAL:
a80ae91c 1753 fmod = NULL_TREE;
54ad1b4d 1754 /* Check if we have a builtin fmod. */
808656b4 1755 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
54ad1b4d 1756
fa0323b8 1757 /* The builtin should always be available. */
1758 gcc_assert (fmod != NULL_TREE);
1759
1760 tmp = build_addr (fmod, current_function_decl);
1761 se->expr = build_call_array_loc (input_location,
a80ae91c 1762 TREE_TYPE (TREE_TYPE (fmod)),
5ddb0172 1763 tmp, 2, args);
fa0323b8 1764 if (modulo == 0)
1765 return;
54ad1b4d 1766
5ddb0172 1767 type = TREE_TYPE (args[0]);
54ad1b4d 1768
5ddb0172 1769 args[0] = gfc_evaluate_now (args[0], &se->pre);
1770 args[1] = gfc_evaluate_now (args[1], &se->pre);
4ee9c684 1771
54ad1b4d 1772 /* Definition:
fa0323b8 1773 modulo = arg - floor (arg/arg2) * arg2
1774
1775 In order to calculate the result accurately, we use the fmod
1776 function as follows.
1777
1778 res = fmod (arg, arg2);
1779 if (res)
1780 {
1781 if ((arg < 0) xor (arg2 < 0))
1782 res += arg2;
1783 }
1784 else
1785 res = copysign (0., arg2);
1786
1787 => As two nested ternary exprs:
1788
1789 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
1790 : copysign (0., arg2);
1791
1792 */
1793
1794 zero = gfc_build_const (type, integer_zero_node);
1795 tmp = gfc_evaluate_now (se->expr, &se->pre);
1796 if (!flag_signed_zeros)
54ad1b4d 1797 {
6f5c9335 1798 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1799 args[0], zero);
1800 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1801 args[1], zero);
1802 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
1803 boolean_type_node, test, test2);
1804 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1805 tmp, zero);
1806 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
1807 boolean_type_node, test, test2);
54ad1b4d 1808 test = gfc_evaluate_now (test, &se->pre);
6f5c9335 1809 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
fa0323b8 1810 fold_build2_loc (input_location,
1811 PLUS_EXPR,
1812 type, tmp, args[1]),
1813 tmp);
54ad1b4d 1814 }
fa0323b8 1815 else
1707eca1 1816 {
fa0323b8 1817 tree expr1, copysign, cscall;
1818 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
1819 expr->ts.kind);
1820 test = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1821 args[0], zero);
1822 test2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1823 args[1], zero);
1824 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
1825 boolean_type_node, test, test2);
1826 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
1827 fold_build2_loc (input_location,
1828 PLUS_EXPR,
1829 type, tmp, args[1]),
1830 tmp);
1831 test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1832 tmp, zero);
1833 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
1834 args[1]);
1835 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
1836 expr1, cscall);
1707eca1 1837 }
fa0323b8 1838 return;
4ee9c684 1839
1840 default:
22d678e8 1841 gcc_unreachable ();
4ee9c684 1842 }
4ee9c684 1843}
1844
f004c7aa 1845/* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
1846 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
1847 where the right shifts are logical (i.e. 0's are shifted in).
1848 Because SHIFT_EXPR's want shifts strictly smaller than the integral
1849 type width, we have to special-case both S == 0 and S == BITSIZE(J):
1850 DSHIFTL(I,J,0) = I
1851 DSHIFTL(I,J,BITSIZE) = J
1852 DSHIFTR(I,J,0) = J
1853 DSHIFTR(I,J,BITSIZE) = I. */
1854
1855static void
1856gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
1857{
1858 tree type, utype, stype, arg1, arg2, shift, res, left, right;
1859 tree args[3], cond, tmp;
1860 int bitsize;
1861
1862 gfc_conv_intrinsic_function_args (se, expr, args, 3);
1863
1864 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
1865 type = TREE_TYPE (args[0]);
1866 bitsize = TYPE_PRECISION (type);
1867 utype = unsigned_type_for (type);
1868 stype = TREE_TYPE (args[2]);
1869
1870 arg1 = gfc_evaluate_now (args[0], &se->pre);
1871 arg2 = gfc_evaluate_now (args[1], &se->pre);
1872 shift = gfc_evaluate_now (args[2], &se->pre);
1873
1874 /* The generic case. */
1875 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
1876 build_int_cst (stype, bitsize), shift);
1877 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
1878 arg1, dshiftl ? shift : tmp);
1879
1880 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
1881 fold_convert (utype, arg2), dshiftl ? tmp : shift);
1882 right = fold_convert (type, right);
1883
1884 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
1885
1886 /* Special cases. */
1887 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
1888 build_int_cst (stype, 0));
1889 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
1890 dshiftl ? arg1 : arg2, res);
1891
1892 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, shift,
1893 build_int_cst (stype, bitsize));
1894 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
1895 dshiftl ? arg2 : arg1, res);
1896
1897 se->expr = res;
1898}
1899
1900
4ee9c684 1901/* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
1902
1903static void
1904gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
1905{
4ee9c684 1906 tree val;
1907 tree tmp;
1908 tree type;
1909 tree zero;
5ddb0172 1910 tree args[2];
4ee9c684 1911
5ddb0172 1912 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1913 type = TREE_TYPE (args[0]);
4ee9c684 1914
6f5c9335 1915 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
4ee9c684 1916 val = gfc_evaluate_now (val, &se->pre);
1917
1918 zero = gfc_build_const (type, integer_zero_node);
6f5c9335 1919 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, val, zero);
1920 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
4ee9c684 1921}
1922
1923
1924/* SIGN(A, B) is absolute value of A times sign of B.
1925 The real value versions use library functions to ensure the correct
1926 handling of negative zero. Integer case implemented as:
5687724f 1927 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
4ee9c684 1928 */
1929
1930static void
1931gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
1932{
1933 tree tmp;
4ee9c684 1934 tree type;
5ddb0172 1935 tree args[2];
4ee9c684 1936
5ddb0172 1937 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4ee9c684 1938 if (expr->ts.type == BT_REAL)
1939 {
af9e821d 1940 tree abs;
1941
808656b4 1942 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
1943 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
af9e821d 1944
1945 /* We explicitly have to ignore the minus sign. We do so by using
1946 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
1947 if (!gfc_option.flag_sign_zero
1948 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
1949 {
1950 tree cond, zero;
1951 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
6f5c9335 1952 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
1953 args[1], zero);
1954 se->expr = fold_build3_loc (input_location, COND_EXPR,
1955 TREE_TYPE (args[0]), cond,
1516b2fb 1956 build_call_expr_loc (input_location, abs, 1,
1957 args[0]),
1958 build_call_expr_loc (input_location, tmp, 2,
1959 args[0], args[1]));
af9e821d 1960 }
1961 else
a80ae91c 1962 se->expr = build_call_expr_loc (input_location, tmp, 2,
1963 args[0], args[1]);
4ee9c684 1964 return;
1965 }
1966
5687724f 1967 /* Having excluded floating point types, we know we are now dealing
1968 with signed integer types. */
5ddb0172 1969 type = TREE_TYPE (args[0]);
4ee9c684 1970
5ddb0172 1971 /* Args[0] is used multiple times below. */
1972 args[0] = gfc_evaluate_now (args[0], &se->pre);
5687724f 1973
1974 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
1975 the signs of A and B are the same, and of all ones if they differ. */
6f5c9335 1976 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
1977 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
1978 build_int_cst (type, TYPE_PRECISION (type) - 1));
5687724f 1979 tmp = gfc_evaluate_now (tmp, &se->pre);
1980
1981 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
1982 is all ones (i.e. -1). */
6f5c9335 1983 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
1984 fold_build2_loc (input_location, PLUS_EXPR,
1985 type, args[0], tmp), tmp);
4ee9c684 1986}
1987
1988
1989/* Test for the presence of an optional argument. */
1990
1991static void
1992gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
1993{
1994 gfc_expr *arg;
1995
1996 arg = expr->value.function.actual->expr;
22d678e8 1997 gcc_assert (arg->expr_type == EXPR_VARIABLE);
4ee9c684 1998 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
1999 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
2000}
2001
2002
2003/* Calculate the double precision product of two single precision values. */
2004
2005static void
2006gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
2007{
4ee9c684 2008 tree type;
5ddb0172 2009 tree args[2];
4ee9c684 2010
5ddb0172 2011 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4ee9c684 2012
2013 /* Convert the args to double precision before multiplying. */
2014 type = gfc_typenode_for_spec (&expr->ts);
5ddb0172 2015 args[0] = convert (type, args[0]);
2016 args[1] = convert (type, args[1]);
6f5c9335 2017 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
2018 args[1]);
4ee9c684 2019}
2020
2021
2022/* Return a length one character string containing an ascii character. */
2023
2024static void
2025gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
2026{
6bd88715 2027 tree arg[2];
4ee9c684 2028 tree var;
2029 tree type;
6bd88715 2030 unsigned int num_args;
4ee9c684 2031
6bd88715 2032 num_args = gfc_intrinsic_argument_list_length (expr);
2033 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
4ee9c684 2034
b44437b9 2035 type = gfc_get_char_type (expr->ts.kind);
4ee9c684 2036 var = gfc_create_var (type, "char");
2037
6f5c9335 2038 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
75a70cf9 2039 gfc_add_modify (&se->pre, var, arg[0]);
4ee9c684 2040 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
1557756e 2041 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
4ee9c684 2042}
2043
2044
b902b078 2045static void
2046gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
2047{
2048 tree var;
2049 tree len;
2050 tree tmp;
b902b078 2051 tree cond;
5ddb0172 2052 tree fndecl;
2053 tree *args;
2054 unsigned int num_args;
2055
2056 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
86b32f71 2057 args = XALLOCAVEC (tree, num_args);
b902b078 2058
329f13ad 2059 var = gfc_create_var (pchar_type_node, "pstr");
4f16309a 2060 len = gfc_create_var (gfc_charlen_type_node, "len");
b902b078 2061
5ddb0172 2062 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
86f2ad37 2063 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2064 args[1] = gfc_build_addr_expr (NULL_TREE, len);
b902b078 2065
5ddb0172 2066 fndecl = build_addr (gfor_fndecl_ctime, current_function_decl);
389dd41b 2067 tmp = build_call_array_loc (input_location,
2068 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
5ddb0172 2069 fndecl, num_args, args);
b902b078 2070 gfc_add_expr_to_block (&se->pre, tmp);
2071
2072 /* Free the temporary afterwards, if necessary. */
6f5c9335 2073 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2074 len, build_int_cst (TREE_TYPE (len), 0));
9915365e 2075 tmp = gfc_call_free (var);
e60a6f7b 2076 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
b902b078 2077 gfc_add_expr_to_block (&se->post, tmp);
2078
2079 se->expr = var;
2080 se->string_length = len;
2081}
2082
2083
2084static void
2085gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
2086{
2087 tree var;
2088 tree len;
2089 tree tmp;
b902b078 2090 tree cond;
5ddb0172 2091 tree fndecl;
2092 tree *args;
2093 unsigned int num_args;
2094
2095 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
86b32f71 2096 args = XALLOCAVEC (tree, num_args);
b902b078 2097
329f13ad 2098 var = gfc_create_var (pchar_type_node, "pstr");
185bc3c7 2099 len = gfc_create_var (gfc_charlen_type_node, "len");
b902b078 2100
5ddb0172 2101 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
86f2ad37 2102 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2103 args[1] = gfc_build_addr_expr (NULL_TREE, len);
b902b078 2104
5ddb0172 2105 fndecl = build_addr (gfor_fndecl_fdate, current_function_decl);
389dd41b 2106 tmp = build_call_array_loc (input_location,
2107 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
5ddb0172 2108 fndecl, num_args, args);
b902b078 2109 gfc_add_expr_to_block (&se->pre, tmp);
2110
2111 /* Free the temporary afterwards, if necessary. */
6f5c9335 2112 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2113 len, build_int_cst (TREE_TYPE (len), 0));
9915365e 2114 tmp = gfc_call_free (var);
e60a6f7b 2115 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
b902b078 2116 gfc_add_expr_to_block (&se->post, tmp);
2117
2118 se->expr = var;
2119 se->string_length = len;
2120}
2121
2122
dbc97b88 2123/* Return a character string containing the tty name. */
2124
2125static void
2126gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
2127{
2128 tree var;
2129 tree len;
2130 tree tmp;
dbc97b88 2131 tree cond;
5ddb0172 2132 tree fndecl;
5ddb0172 2133 tree *args;
2134 unsigned int num_args;
2135
2136 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
86b32f71 2137 args = XALLOCAVEC (tree, num_args);
dbc97b88 2138
329f13ad 2139 var = gfc_create_var (pchar_type_node, "pstr");
185bc3c7 2140 len = gfc_create_var (gfc_charlen_type_node, "len");
dbc97b88 2141
5ddb0172 2142 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
86f2ad37 2143 args[0] = gfc_build_addr_expr (NULL_TREE, var);
2144 args[1] = gfc_build_addr_expr (NULL_TREE, len);
dbc97b88 2145
5ddb0172 2146 fndecl = build_addr (gfor_fndecl_ttynam, current_function_decl);
389dd41b 2147 tmp = build_call_array_loc (input_location,
2148 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
5ddb0172 2149 fndecl, num_args, args);
dbc97b88 2150 gfc_add_expr_to_block (&se->pre, tmp);
2151
2152 /* Free the temporary afterwards, if necessary. */
6f5c9335 2153 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2154 len, build_int_cst (TREE_TYPE (len), 0));
9915365e 2155 tmp = gfc_call_free (var);
e60a6f7b 2156 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
dbc97b88 2157 gfc_add_expr_to_block (&se->post, tmp);
2158
2159 se->expr = var;
2160 se->string_length = len;
2161}
2162
2163
4ee9c684 2164/* Get the minimum/maximum value of all the parameters.
2165 minmax (a1, a2, a3, ...)
2166 {
0cc4742f 2167 mvar = a1;
2168 if (a2 .op. mvar || isnan(mvar))
4ee9c684 2169 mvar = a2;
34203d28 2170 if (a3 .op. mvar || isnan(mvar))
4ee9c684 2171 mvar = a3;
2172 ...
2173 return mvar
2174 }
2175 */
2176
2177/* TODO: Mismatching types can occur when specific names are used.
2178 These should be handled during resolution. */
2179static void
d62fb8de 2180gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
4ee9c684 2181{
4ee9c684 2182 tree tmp;
2183 tree mvar;
2184 tree val;
2185 tree thencase;
5ddb0172 2186 tree *args;
4ee9c684 2187 tree type;
edf97ddf 2188 gfc_actual_arglist *argexpr;
0cc4742f 2189 unsigned int i, nargs;
4ee9c684 2190
5ddb0172 2191 nargs = gfc_intrinsic_argument_list_length (expr);
86b32f71 2192 args = XALLOCAVEC (tree, nargs);
5ddb0172 2193
2194 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
4ee9c684 2195 type = gfc_typenode_for_spec (&expr->ts);
2196
edf97ddf 2197 argexpr = expr->value.function.actual;
0cc4742f 2198 if (TREE_TYPE (args[0]) != type)
2199 args[0] = convert (type, args[0]);
4ee9c684 2200 /* Only evaluate the argument once. */
0cc4742f 2201 if (TREE_CODE (args[0]) != VAR_DECL && !TREE_CONSTANT (args[0]))
2202 args[0] = gfc_evaluate_now (args[0], &se->pre);
4ee9c684 2203
2204 mvar = gfc_create_var (type, "M");
75a70cf9 2205 gfc_add_modify (&se->pre, mvar, args[0]);
5ddb0172 2206 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
4ee9c684 2207 {
34203d28 2208 tree cond, isnan;
edf97ddf 2209
5ddb0172 2210 val = args[i];
4ee9c684 2211
edf97ddf 2212 /* Handle absent optional arguments by ignoring the comparison. */
0cc4742f 2213 if (argexpr->expr->expr_type == EXPR_VARIABLE
edf97ddf 2214 && argexpr->expr->symtree->n.sym->attr.optional
2215 && TREE_CODE (val) == INDIRECT_REF)
389dd41b 2216 cond = fold_build2_loc (input_location,
2217 NE_EXPR, boolean_type_node,
2218 TREE_OPERAND (val, 0),
2219 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
edf97ddf 2220 else
2221 {
2222 cond = NULL_TREE;
2223
2224 /* Only evaluate the argument once. */
2225 if (TREE_CODE (val) != VAR_DECL && !TREE_CONSTANT (val))
2226 val = gfc_evaluate_now (val, &se->pre);
2227 }
4ee9c684 2228
ed52ef8b 2229 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
4ee9c684 2230
6f5c9335 2231 tmp = fold_build2_loc (input_location, op, boolean_type_node,
2232 convert (type, val), mvar);
34203d28 2233
2234 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
2235 __builtin_isnan might be made dependent on that module being loaded,
2236 to help performance of programs that don't rely on IEEE semantics. */
0cc4742f 2237 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
34203d28 2238 {
389dd41b 2239 isnan = build_call_expr_loc (input_location,
b9a16870 2240 builtin_decl_explicit (BUILT_IN_ISNAN),
2241 1, mvar);
6f5c9335 2242 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
2243 boolean_type_node, tmp,
2244 fold_convert (boolean_type_node, isnan));
34203d28 2245 }
e60a6f7b 2246 tmp = build3_v (COND_EXPR, tmp, thencase,
2247 build_empty_stmt (input_location));
edf97ddf 2248
2249 if (cond != NULL_TREE)
e60a6f7b 2250 tmp = build3_v (COND_EXPR, cond, tmp,
2251 build_empty_stmt (input_location));
edf97ddf 2252
4ee9c684 2253 gfc_add_expr_to_block (&se->pre, tmp);
edf97ddf 2254 argexpr = argexpr->next;
4ee9c684 2255 }
2256 se->expr = mvar;
2257}
2258
2259
5fcc6ec2 2260/* Generate library calls for MIN and MAX intrinsics for character
2261 variables. */
2262static void
2263gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
2264{
2265 tree *args;
40b806de 2266 tree var, len, fndecl, tmp, cond, function;
5fcc6ec2 2267 unsigned int nargs;
2268
2269 nargs = gfc_intrinsic_argument_list_length (expr);
86b32f71 2270 args = XALLOCAVEC (tree, nargs + 4);
5fcc6ec2 2271 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
2272
2273 /* Create the result variables. */
2274 len = gfc_create_var (gfc_charlen_type_node, "len");
86f2ad37 2275 args[0] = gfc_build_addr_expr (NULL_TREE, len);
329f13ad 2276 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
5fcc6ec2 2277 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
35bf1214 2278 args[2] = build_int_cst (integer_type_node, op);
2279 args[3] = build_int_cst (integer_type_node, nargs / 2);
5fcc6ec2 2280
40b806de 2281 if (expr->ts.kind == 1)
2282 function = gfor_fndecl_string_minmax;
2283 else if (expr->ts.kind == 4)
2284 function = gfor_fndecl_string_minmax_char4;
2285 else
2286 gcc_unreachable ();
2287
5fcc6ec2 2288 /* Make the function call. */
40b806de 2289 fndecl = build_addr (function, current_function_decl);
389dd41b 2290 tmp = build_call_array_loc (input_location,
2291 TREE_TYPE (TREE_TYPE (function)), fndecl,
40b806de 2292 nargs + 4, args);
5fcc6ec2 2293 gfc_add_expr_to_block (&se->pre, tmp);
2294
2295 /* Free the temporary afterwards, if necessary. */
6f5c9335 2296 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2297 len, build_int_cst (TREE_TYPE (len), 0));
5fcc6ec2 2298 tmp = gfc_call_free (var);
e60a6f7b 2299 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
5fcc6ec2 2300 gfc_add_expr_to_block (&se->post, tmp);
2301
2302 se->expr = var;
2303 se->string_length = len;
2304}
2305
2306
6f0539a0 2307/* Create a symbol node for this intrinsic. The symbol from the frontend
2308 has the generic name. */
4ee9c684 2309
2310static gfc_symbol *
2311gfc_get_symbol_for_expr (gfc_expr * expr)
2312{
2313 gfc_symbol *sym;
2314
2315 /* TODO: Add symbols for intrinsic function to the global namespace. */
22d678e8 2316 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
4ee9c684 2317 sym = gfc_new_symbol (expr->value.function.name, NULL);
2318
2319 sym->ts = expr->ts;
2320 sym->attr.external = 1;
2321 sym->attr.function = 1;
2322 sym->attr.always_explicit = 1;
2323 sym->attr.proc = PROC_INTRINSIC;
2324 sym->attr.flavor = FL_PROCEDURE;
2325 sym->result = sym;
2326 if (expr->rank > 0)
2327 {
2328 sym->attr.dimension = 1;
2329 sym->as = gfc_get_array_spec ();
2330 sym->as->type = AS_ASSUMED_SHAPE;
2331 sym->as->rank = expr->rank;
2332 }
2333
faa9fea4 2334 gfc_copy_formal_args_intr (sym, expr->value.function.isym);
2335
4ee9c684 2336 return sym;
2337}
2338
2339/* Generate a call to an external intrinsic function. */
2340static void
2341gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
2342{
2343 gfc_symbol *sym;
f1f41a6c 2344 vec<tree, va_gc> *append_args;
4ee9c684 2345
bfa43780 2346 gcc_assert (!se->ss || se->ss->info->expr == expr);
4ee9c684 2347
2348 if (se->ss)
22d678e8 2349 gcc_assert (expr->rank > 0);
4ee9c684 2350 else
22d678e8 2351 gcc_assert (expr->rank == 0);
4ee9c684 2352
2353 sym = gfc_get_symbol_for_expr (expr);
4e8e57b0 2354
2355 /* Calls to libgfortran_matmul need to be appended special arguments,
2356 to be able to call the BLAS ?gemm functions if required and possible. */
008f96d8 2357 append_args = NULL;
55cb4417 2358 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
4e8e57b0 2359 && sym->ts.type != BT_LOGICAL)
2360 {
2361 tree cint = gfc_get_int_type (gfc_c_int_kind);
2362
2363 if (gfc_option.flag_external_blas
2364 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
19bbb6e7 2365 && (sym->ts.kind == 4 || sym->ts.kind == 8))
4e8e57b0 2366 {
2367 tree gemm_fndecl;
2368
2369 if (sym->ts.type == BT_REAL)
2370 {
19bbb6e7 2371 if (sym->ts.kind == 4)
4e8e57b0 2372 gemm_fndecl = gfor_fndecl_sgemm;
2373 else
2374 gemm_fndecl = gfor_fndecl_dgemm;
2375 }
2376 else
2377 {
19bbb6e7 2378 if (sym->ts.kind == 4)
4e8e57b0 2379 gemm_fndecl = gfor_fndecl_cgemm;
2380 else
2381 gemm_fndecl = gfor_fndecl_zgemm;
2382 }
2383
f1f41a6c 2384 vec_alloc (append_args, 3);
2385 append_args->quick_push (build_int_cst (cint, 1));
2386 append_args->quick_push (build_int_cst (cint,
2387 gfc_option.blas_matmul_limit));
2388 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
2389 gemm_fndecl));
4e8e57b0 2390 }
2391 else
2392 {
f1f41a6c 2393 vec_alloc (append_args, 3);
2394 append_args->quick_push (build_int_cst (cint, 0));
2395 append_args->quick_push (build_int_cst (cint, 0));
2396 append_args->quick_push (null_pointer_node);
4e8e57b0 2397 }
2398 }
2399
64e93293 2400 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
2401 append_args);
16760fe7 2402 gfc_free_symbol (sym);
4ee9c684 2403}
2404
2405/* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
2406 Implemented as
2407 any(a)
2408 {
2409 forall (i=...)
2410 if (a[i] != 0)
2411 return 1
2412 end forall
2413 return 0
2414 }
2415 all(a)
2416 {
2417 forall (i=...)
2418 if (a[i] == 0)
2419 return 0
2420 end forall
2421 return 1
2422 }
2423 */
2424static void
d62fb8de 2425gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
4ee9c684 2426{
2427 tree resvar;
2428 stmtblock_t block;
2429 stmtblock_t body;
2430 tree type;
2431 tree tmp;
2432 tree found;
2433 gfc_loopinfo loop;
2434 gfc_actual_arglist *actual;
2435 gfc_ss *arrayss;
2436 gfc_se arrayse;
2437 tree exit_label;
2438
2439 if (se->ss)
2440 {
2441 gfc_conv_intrinsic_funcall (se, expr);
2442 return;
2443 }
2444
2445 actual = expr->value.function.actual;
2446 type = gfc_typenode_for_spec (&expr->ts);
2447 /* Initialize the result. */
2448 resvar = gfc_create_var (type, "test");
2449 if (op == EQ_EXPR)
2450 tmp = convert (type, boolean_true_node);
2451 else
2452 tmp = convert (type, boolean_false_node);
75a70cf9 2453 gfc_add_modify (&se->pre, resvar, tmp);
4ee9c684 2454
2455 /* Walk the arguments. */
2456 arrayss = gfc_walk_expr (actual->expr);
22d678e8 2457 gcc_assert (arrayss != gfc_ss_terminator);
4ee9c684 2458
2459 /* Initialize the scalarizer. */
2460 gfc_init_loopinfo (&loop);
2461 exit_label = gfc_build_label_decl (NULL_TREE);
2462 TREE_USED (exit_label) = 1;
2463 gfc_add_ss_to_loop (&loop, arrayss);
2464
2465 /* Initialize the loop. */
2466 gfc_conv_ss_startstride (&loop);
92f4d1c4 2467 gfc_conv_loop_setup (&loop, &expr->where);
4ee9c684 2468
2469 gfc_mark_ss_chain_used (arrayss, 1);
2470 /* Generate the loop body. */
2471 gfc_start_scalarized_body (&loop, &body);
2472
2473 /* If the condition matches then set the return value. */
2474 gfc_start_block (&block);
2475 if (op == EQ_EXPR)
2476 tmp = convert (type, boolean_false_node);
2477 else
2478 tmp = convert (type, boolean_true_node);
75a70cf9 2479 gfc_add_modify (&block, resvar, tmp);
4ee9c684 2480
2481 /* And break out of the loop. */
2482 tmp = build1_v (GOTO_EXPR, exit_label);
2483 gfc_add_expr_to_block (&block, tmp);
2484
2485 found = gfc_finish_block (&block);
2486
2487 /* Check this element. */
2488 gfc_init_se (&arrayse, NULL);
2489 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2490 arrayse.ss = arrayss;
2491 gfc_conv_expr_val (&arrayse, actual->expr);
2492
2493 gfc_add_block_to_block (&body, &arrayse.pre);
6f5c9335 2494 tmp = fold_build2_loc (input_location, op, boolean_type_node, arrayse.expr,
2495 build_int_cst (TREE_TYPE (arrayse.expr), 0));
e60a6f7b 2496 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
4ee9c684 2497 gfc_add_expr_to_block (&body, tmp);
2498 gfc_add_block_to_block (&body, &arrayse.post);
2499
2500 gfc_trans_scalarizing_loops (&loop, &body);
2501
2502 /* Add the exit label. */
2503 tmp = build1_v (LABEL_EXPR, exit_label);
2504 gfc_add_expr_to_block (&loop.pre, tmp);
2505
2506 gfc_add_block_to_block (&se->pre, &loop.pre);
2507 gfc_add_block_to_block (&se->pre, &loop.post);
2508 gfc_cleanup_loop (&loop);
2509
2510 se->expr = resvar;
2511}
2512
2513/* COUNT(A) = Number of true elements in A. */
2514static void
2515gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
2516{
2517 tree resvar;
2518 tree type;
2519 stmtblock_t body;
2520 tree tmp;
2521 gfc_loopinfo loop;
2522 gfc_actual_arglist *actual;
2523 gfc_ss *arrayss;
2524 gfc_se arrayse;
2525
2526 if (se->ss)
2527 {
2528 gfc_conv_intrinsic_funcall (se, expr);
2529 return;
2530 }
2531
2532 actual = expr->value.function.actual;
2533
2534 type = gfc_typenode_for_spec (&expr->ts);
2535 /* Initialize the result. */
2536 resvar = gfc_create_var (type, "count");
75a70cf9 2537 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
4ee9c684 2538
2539 /* Walk the arguments. */
2540 arrayss = gfc_walk_expr (actual->expr);
22d678e8 2541 gcc_assert (arrayss != gfc_ss_terminator);
4ee9c684 2542
2543 /* Initialize the scalarizer. */
2544 gfc_init_loopinfo (&loop);
2545 gfc_add_ss_to_loop (&loop, arrayss);
2546
2547 /* Initialize the loop. */
2548 gfc_conv_ss_startstride (&loop);
92f4d1c4 2549 gfc_conv_loop_setup (&loop, &expr->where);
4ee9c684 2550
2551 gfc_mark_ss_chain_used (arrayss, 1);
2552 /* Generate the loop body. */
2553 gfc_start_scalarized_body (&loop, &body);
2554
6f5c9335 2555 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
2556 resvar, build_int_cst (TREE_TYPE (resvar), 1));
ed52ef8b 2557 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
4ee9c684 2558
2559 gfc_init_se (&arrayse, NULL);
2560 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2561 arrayse.ss = arrayss;
2562 gfc_conv_expr_val (&arrayse, actual->expr);
e60a6f7b 2563 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
2564 build_empty_stmt (input_location));
4ee9c684 2565
2566 gfc_add_block_to_block (&body, &arrayse.pre);
2567 gfc_add_expr_to_block (&body, tmp);
2568 gfc_add_block_to_block (&body, &arrayse.post);
2569
2570 gfc_trans_scalarizing_loops (&loop, &body);
2571
2572 gfc_add_block_to_block (&se->pre, &loop.pre);
2573 gfc_add_block_to_block (&se->pre, &loop.post);
2574 gfc_cleanup_loop (&loop);
2575
2576 se->expr = resvar;
2577}
2578
88df5e2f 2579
2580/* Update given gfc_se to have ss component pointing to the nested gfc_ss
2581 struct and return the corresponding loopinfo. */
2582
2583static gfc_loopinfo *
2584enter_nested_loop (gfc_se *se)
2585{
2586 se->ss = se->ss->nested_ss;
2587 gcc_assert (se->ss == se->ss->loop->ss);
2588
2589 return se->ss->loop;
2590}
2591
2592
4ee9c684 2593/* Inline implementation of the sum and product intrinsics. */
2594static void
b4ba8232 2595gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
2596 bool norm2)
4ee9c684 2597{
2598 tree resvar;
b4ba8232 2599 tree scale = NULL_TREE;
4ee9c684 2600 tree type;
2601 stmtblock_t body;
2602 stmtblock_t block;
2603 tree tmp;
cae7ff32 2604 gfc_loopinfo loop, *ploop;
dbef2853 2605 gfc_actual_arglist *arg_array, *arg_mask;
88df5e2f 2606 gfc_ss *arrayss = NULL;
2607 gfc_ss *maskss = NULL;
4ee9c684 2608 gfc_se arrayse;
2609 gfc_se maskse;
85b3b7b7 2610 gfc_se *parent_se;
4ee9c684 2611 gfc_expr *arrayexpr;
2612 gfc_expr *maskexpr;
2613
88df5e2f 2614 if (expr->rank > 0)
4ee9c684 2615 {
88df5e2f 2616 gcc_assert (gfc_inline_intrinsic_function_p (expr));
2617 parent_se = se;
4ee9c684 2618 }
85b3b7b7 2619 else
2620 parent_se = NULL;
4ee9c684 2621
2622 type = gfc_typenode_for_spec (&expr->ts);
2623 /* Initialize the result. */
2624 resvar = gfc_create_var (type, "val");
b4ba8232 2625 if (norm2)
2626 {
2627 /* result = 0.0;
2628 scale = 1.0. */
2629 scale = gfc_create_var (type, "scale");
2630 gfc_add_modify (&se->pre, scale,
2631 gfc_build_const (type, integer_one_node));
2632 tmp = gfc_build_const (type, integer_zero_node);
2633 }
9028d57d 2634 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
4ee9c684 2635 tmp = gfc_build_const (type, integer_zero_node);
b4ba8232 2636 else if (op == NE_EXPR)
2637 /* PARITY. */
2638 tmp = convert (type, boolean_false_node);
9028d57d 2639 else if (op == BIT_AND_EXPR)
2640 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
2641 type, integer_one_node));
4ee9c684 2642 else
2643 tmp = gfc_build_const (type, integer_one_node);
2644
75a70cf9 2645 gfc_add_modify (&se->pre, resvar, tmp);
4ee9c684 2646
dbef2853 2647 arg_array = expr->value.function.actual;
2648
dbef2853 2649 arrayexpr = arg_array->expr;
4ee9c684 2650
b4ba8232 2651 if (op == NE_EXPR || norm2)
2652 /* PARITY and NORM2. */
2653 maskexpr = NULL;
2654 else
2655 {
dbef2853 2656 arg_mask = arg_array->next->next;
2657 gcc_assert (arg_mask != NULL);
2658 maskexpr = arg_mask->expr;
b4ba8232 2659 }
2660
88df5e2f 2661 if (expr->rank == 0)
4ee9c684 2662 {
88df5e2f 2663 /* Walk the arguments. */
2664 arrayss = gfc_walk_expr (arrayexpr);
2665 gcc_assert (arrayss != gfc_ss_terminator);
4ee9c684 2666
88df5e2f 2667 if (maskexpr && maskexpr->rank > 0)
2668 {
2669 maskss = gfc_walk_expr (maskexpr);
2670 gcc_assert (maskss != gfc_ss_terminator);
2671 }
2672 else
2673 maskss = NULL;
4ee9c684 2674
88df5e2f 2675 /* Initialize the scalarizer. */
2676 gfc_init_loopinfo (&loop);
2677 gfc_add_ss_to_loop (&loop, arrayss);
2678 if (maskexpr && maskexpr->rank > 0)
2679 gfc_add_ss_to_loop (&loop, maskss);
4ee9c684 2680
88df5e2f 2681 /* Initialize the loop. */
2682 gfc_conv_ss_startstride (&loop);
2683 gfc_conv_loop_setup (&loop, &expr->where);
2684
2685 gfc_mark_ss_chain_used (arrayss, 1);
2686 if (maskexpr && maskexpr->rank > 0)
2687 gfc_mark_ss_chain_used (maskss, 1);
2688
2689 ploop = &loop;
2690 }
2691 else
2692 /* All the work has been done in the parent loops. */
2693 ploop = enter_nested_loop (se);
2694
2695 gcc_assert (ploop);
cae7ff32 2696
4ee9c684 2697 /* Generate the loop body. */
cae7ff32 2698 gfc_start_scalarized_body (ploop, &body);
4ee9c684 2699
2700 /* If we have a mask, only add this element if the mask is set. */
190c9d73 2701 if (maskexpr && maskexpr->rank > 0)
4ee9c684 2702 {
85b3b7b7 2703 gfc_init_se (&maskse, parent_se);
cae7ff32 2704 gfc_copy_loopinfo_to_se (&maskse, ploop);
88df5e2f 2705 if (expr->rank == 0)
2706 maskse.ss = maskss;
4ee9c684 2707 gfc_conv_expr_val (&maskse, maskexpr);
2708 gfc_add_block_to_block (&body, &maskse.pre);
2709
2710 gfc_start_block (&block);
2711 }
2712 else
2713 gfc_init_block (&block);
2714
2715 /* Do the actual summation/product. */
85b3b7b7 2716 gfc_init_se (&arrayse, parent_se);
cae7ff32 2717 gfc_copy_loopinfo_to_se (&arrayse, ploop);
88df5e2f 2718 if (expr->rank == 0)
2719 arrayse.ss = arrayss;
4ee9c684 2720 gfc_conv_expr_val (&arrayse, arrayexpr);
2721 gfc_add_block_to_block (&block, &arrayse.pre);
2722
b4ba8232 2723 if (norm2)
2724 {
2725 /* if (x(i) != 0.0)
2726 {
2727 absX = abs(x(i))
2728 if (absX > scale)
2729 {
2730 val = scale/absX;
2731 result = 1.0 + result * val * val;
2732 scale = absX;
2733 }
2734 else
2735 {
2736 val = absX/scale;
2737 result += val * val;
2738 }
2739 } */
2740 tree res1, res2, cond, absX, val;
2741 stmtblock_t ifblock1, ifblock2, ifblock3;
2742
2743 gfc_init_block (&ifblock1);
2744
2745 absX = gfc_create_var (type, "absX");
2746 gfc_add_modify (&ifblock1, absX,
6f5c9335 2747 fold_build1_loc (input_location, ABS_EXPR, type,
2748 arrayse.expr));
b4ba8232 2749 val = gfc_create_var (type, "val");
2750 gfc_add_expr_to_block (&ifblock1, val);
2751
2752 gfc_init_block (&ifblock2);
2753 gfc_add_modify (&ifblock2, val,
6f5c9335 2754 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
2755 absX));
2756 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
2757 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
2758 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
2759 gfc_build_const (type, integer_one_node));
b4ba8232 2760 gfc_add_modify (&ifblock2, resvar, res1);
2761 gfc_add_modify (&ifblock2, scale, absX);
2762 res1 = gfc_finish_block (&ifblock2);
2763
2764 gfc_init_block (&ifblock3);
2765 gfc_add_modify (&ifblock3, val,
6f5c9335 2766 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
2767 scale));
2768 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
2769 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
b4ba8232 2770 gfc_add_modify (&ifblock3, resvar, res2);
2771 res2 = gfc_finish_block (&ifblock3);
2772
6f5c9335 2773 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2774 absX, scale);
b4ba8232 2775 tmp = build3_v (COND_EXPR, cond, res1, res2);
2776 gfc_add_expr_to_block (&ifblock1, tmp);
2777 tmp = gfc_finish_block (&ifblock1);
2778
6f5c9335 2779 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
2780 arrayse.expr,
2781 gfc_build_const (type, integer_zero_node));
b4ba8232 2782
2783 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2784 gfc_add_expr_to_block (&block, tmp);
2785 }
2786 else
2787 {
6f5c9335 2788 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
b4ba8232 2789 gfc_add_modify (&block, resvar, tmp);
2790 }
2791
4ee9c684 2792 gfc_add_block_to_block (&block, &arrayse.post);
2793
190c9d73 2794 if (maskexpr && maskexpr->rank > 0)
4ee9c684 2795 {
2796 /* We enclose the above in if (mask) {...} . */
4ee9c684 2797
b4ba8232 2798 tmp = gfc_finish_block (&block);
e60a6f7b 2799 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2800 build_empty_stmt (input_location));
4ee9c684 2801 }
2802 else
2803 tmp = gfc_finish_block (&block);
2804 gfc_add_expr_to_block (&body, tmp);
2805
cae7ff32 2806 gfc_trans_scalarizing_loops (ploop, &body);
91b2f40f 2807
2808 /* For a scalar mask, enclose the loop in an if statement. */
190c9d73 2809 if (maskexpr && maskexpr->rank == 0)
91b2f40f 2810 {
91b2f40f 2811 gfc_init_block (&block);
cae7ff32 2812 gfc_add_block_to_block (&block, &ploop->pre);
2813 gfc_add_block_to_block (&block, &ploop->post);
91b2f40f 2814 tmp = gfc_finish_block (&block);
2815
88df5e2f 2816 if (expr->rank > 0)
2817 {
2818 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
2819 build_empty_stmt (input_location));
2820 gfc_advance_se_ss_chain (se);
2821 }
2822 else
2823 {
2824 gcc_assert (expr->rank == 0);
2825 gfc_init_se (&maskse, NULL);
2826 gfc_conv_expr_val (&maskse, maskexpr);
2827 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2828 build_empty_stmt (input_location));
2829 }
2830
91b2f40f 2831 gfc_add_expr_to_block (&block, tmp);
2832 gfc_add_block_to_block (&se->pre, &block);
88df5e2f 2833 gcc_assert (se->post.head == NULL);
91b2f40f 2834 }
2835 else
2836 {
cae7ff32 2837 gfc_add_block_to_block (&se->pre, &ploop->pre);
2838 gfc_add_block_to_block (&se->pre, &ploop->post);
91b2f40f 2839 }
2840
88df5e2f 2841 if (expr->rank == 0)
2842 gfc_cleanup_loop (ploop);
4ee9c684 2843
b4ba8232 2844 if (norm2)
2845 {
2846 /* result = scale * sqrt(result). */
2847 tree sqrt;
808656b4 2848 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
b4ba8232 2849 resvar = build_call_expr_loc (input_location,
2850 sqrt, 1, resvar);
6f5c9335 2851 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
b4ba8232 2852 }
2853
4ee9c684 2854 se->expr = resvar;
2855}
2856
0b5dc8b5 2857
2858/* Inline implementation of the dot_product intrinsic. This function
2859 is based on gfc_conv_intrinsic_arith (the previous function). */
2860static void
2861gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
2862{
2863 tree resvar;
2864 tree type;
2865 stmtblock_t body;
2866 stmtblock_t block;
2867 tree tmp;
2868 gfc_loopinfo loop;
2869 gfc_actual_arglist *actual;
2870 gfc_ss *arrayss1, *arrayss2;
2871 gfc_se arrayse1, arrayse2;
2872 gfc_expr *arrayexpr1, *arrayexpr2;
2873
2874 type = gfc_typenode_for_spec (&expr->ts);
2875
2876 /* Initialize the result. */
2877 resvar = gfc_create_var (type, "val");
2878 if (expr->ts.type == BT_LOGICAL)
a69b6929 2879 tmp = build_int_cst (type, 0);
0b5dc8b5 2880 else
2881 tmp = gfc_build_const (type, integer_zero_node);
2882
75a70cf9 2883 gfc_add_modify (&se->pre, resvar, tmp);
0b5dc8b5 2884
2885 /* Walk argument #1. */
2886 actual = expr->value.function.actual;
2887 arrayexpr1 = actual->expr;
2888 arrayss1 = gfc_walk_expr (arrayexpr1);
2889 gcc_assert (arrayss1 != gfc_ss_terminator);
2890
2891 /* Walk argument #2. */
2892 actual = actual->next;
2893 arrayexpr2 = actual->expr;
2894 arrayss2 = gfc_walk_expr (arrayexpr2);
2895 gcc_assert (arrayss2 != gfc_ss_terminator);
2896
2897 /* Initialize the scalarizer. */
2898 gfc_init_loopinfo (&loop);
2899 gfc_add_ss_to_loop (&loop, arrayss1);
2900 gfc_add_ss_to_loop (&loop, arrayss2);
2901
2902 /* Initialize the loop. */
2903 gfc_conv_ss_startstride (&loop);
92f4d1c4 2904 gfc_conv_loop_setup (&loop, &expr->where);
0b5dc8b5 2905
2906 gfc_mark_ss_chain_used (arrayss1, 1);
2907 gfc_mark_ss_chain_used (arrayss2, 1);
2908
2909 /* Generate the loop body. */
2910 gfc_start_scalarized_body (&loop, &body);
2911 gfc_init_block (&block);
2912
2913 /* Make the tree expression for [conjg(]array1[)]. */
2914 gfc_init_se (&arrayse1, NULL);
2915 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
2916 arrayse1.ss = arrayss1;
2917 gfc_conv_expr_val (&arrayse1, arrayexpr1);
2918 if (expr->ts.type == BT_COMPLEX)
6f5c9335 2919 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
2920 arrayse1.expr);
0b5dc8b5 2921 gfc_add_block_to_block (&block, &arrayse1.pre);
2922
2923 /* Make the tree expression for array2. */
2924 gfc_init_se (&arrayse2, NULL);
2925 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
2926 arrayse2.ss = arrayss2;
2927 gfc_conv_expr_val (&arrayse2, arrayexpr2);
2928 gfc_add_block_to_block (&block, &arrayse2.pre);
2929
2930 /* Do the actual product and sum. */
2931 if (expr->ts.type == BT_LOGICAL)
2932 {
6f5c9335 2933 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
2934 arrayse1.expr, arrayse2.expr);
2935 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
0b5dc8b5 2936 }
2937 else
2938 {
6f5c9335 2939 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
2940 arrayse2.expr);
2941 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
0b5dc8b5 2942 }
75a70cf9 2943 gfc_add_modify (&block, resvar, tmp);
0b5dc8b5 2944
2945 /* Finish up the loop block and the loop. */
2946 tmp = gfc_finish_block (&block);
2947 gfc_add_expr_to_block (&body, tmp);
2948
2949 gfc_trans_scalarizing_loops (&loop, &body);
2950 gfc_add_block_to_block (&se->pre, &loop.pre);
2951 gfc_add_block_to_block (&se->pre, &loop.post);
2952 gfc_cleanup_loop (&loop);
2953
2954 se->expr = resvar;
2955}
2956
2957
7ebee933 2958/* Emit code for minloc or maxloc intrinsic. There are many different cases
2959 we need to handle. For performance reasons we sometimes create two
2960 loops instead of one, where the second one is much simpler.
2961 Examples for minloc intrinsic:
2962 1) Result is an array, a call is generated
2963 2) Array mask is used and NaNs need to be supported:
2964 limit = Infinity;
2965 pos = 0;
2966 S = from;
2967 while (S <= to) {
2968 if (mask[S]) {
2969 if (pos == 0) pos = S + (1 - from);
2970 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
2971 }
2972 S++;
2973 }
2974 goto lab2;
2975 lab1:;
2976 while (S <= to) {
2977 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
2978 S++;
2979 }
2980 lab2:;
2981 3) NaNs need to be supported, but it is known at compile time or cheaply
2982 at runtime whether array is nonempty or not:
2983 limit = Infinity;
2984 pos = 0;
2985 S = from;
2986 while (S <= to) {
2987 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
2988 S++;
2989 }
2990 if (from <= to) pos = 1;
2991 goto lab2;
2992 lab1:;
2993 while (S <= to) {
2994 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
2995 S++;
2996 }
2997 lab2:;
2998 4) NaNs aren't supported, array mask is used:
2999 limit = infinities_supported ? Infinity : huge (limit);
3000 pos = 0;
3001 S = from;
3002 while (S <= to) {
3003 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3004 S++;
3005 }
3006 goto lab2;
3007 lab1:;
3008 while (S <= to) {
3009 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3010 S++;
3011 }
3012 lab2:;
3013 5) Same without array mask:
3014 limit = infinities_supported ? Infinity : huge (limit);
3015 pos = (from <= to) ? 1 : 0;
3016 S = from;
3017 while (S <= to) {
3018 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3019 S++;
3020 }
3021 For 3) and 5), if mask is scalar, this all goes into a conditional,
3022 setting pos = 0; in the else branch. */
3023
4ee9c684 3024static void
d62fb8de 3025gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
4ee9c684 3026{
3027 stmtblock_t body;
3028 stmtblock_t block;
3029 stmtblock_t ifblock;
622183f4 3030 stmtblock_t elseblock;
4ee9c684 3031 tree limit;
3032 tree type;
3033 tree tmp;
7ebee933 3034 tree cond;
622183f4 3035 tree elsetmp;
4ee9c684 3036 tree ifbody;
30dc020c 3037 tree offset;
7ebee933 3038 tree nonempty;
3039 tree lab1, lab2;
4ee9c684 3040 gfc_loopinfo loop;
3041 gfc_actual_arglist *actual;
3042 gfc_ss *arrayss;
3043 gfc_ss *maskss;
3044 gfc_se arrayse;
3045 gfc_se maskse;
3046 gfc_expr *arrayexpr;
3047 gfc_expr *maskexpr;
3048 tree pos;
3049 int n;
3050
3051 if (se->ss)
3052 {
3053 gfc_conv_intrinsic_funcall (se, expr);
3054 return;
3055 }
3056
3057 /* Initialize the result. */
3058 pos = gfc_create_var (gfc_array_index_type, "pos");
30dc020c 3059 offset = gfc_create_var (gfc_array_index_type, "offset");
4ee9c684 3060 type = gfc_typenode_for_spec (&expr->ts);
3061
3062 /* Walk the arguments. */
3063 actual = expr->value.function.actual;
3064 arrayexpr = actual->expr;
3065 arrayss = gfc_walk_expr (arrayexpr);
22d678e8 3066 gcc_assert (arrayss != gfc_ss_terminator);
4ee9c684 3067
3068 actual = actual->next->next;
22d678e8 3069 gcc_assert (actual);
4ee9c684 3070 maskexpr = actual->expr;
7ebee933 3071 nonempty = NULL;
622183f4 3072 if (maskexpr && maskexpr->rank != 0)
4ee9c684 3073 {
3074 maskss = gfc_walk_expr (maskexpr);
22d678e8 3075 gcc_assert (maskss != gfc_ss_terminator);
4ee9c684 3076 }
3077 else
7ebee933 3078 {
3079 mpz_t asize;
3080 if (gfc_array_size (arrayexpr, &asize) == SUCCESS)
3081 {
3082 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
3083 mpz_clear (asize);
6f5c9335 3084 nonempty = fold_build2_loc (input_location, GT_EXPR,
3085 boolean_type_node, nonempty,
3086 gfc_index_zero_node);
7ebee933 3087 }
3088 maskss = NULL;
3089 }
4ee9c684 3090
3091 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
4ee9c684 3092 switch (arrayexpr->ts.type)
3093 {
3094 case BT_REAL:
729e6db2 3095 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
4ee9c684 3096 break;
3097
3098 case BT_INTEGER:
729e6db2 3099 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
4ee9c684 3100 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
3101 arrayexpr->ts.kind);
3102 break;
3103
3104 default:
22d678e8 3105 gcc_unreachable ();
4ee9c684 3106 }
3107
1706268d 3108 /* We start with the most negative possible value for MAXLOC, and the most
3109 positive possible value for MINLOC. The most negative possible value is
3110 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
f6d0e37a 3111 possible value is HUGE in both cases. */
4ee9c684 3112 if (op == GT_EXPR)
6f5c9335 3113 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
1706268d 3114 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
6f5c9335 3115 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
3116 build_int_cst (type, 1));
1706268d 3117
19a12e8d 3118 gfc_add_modify (&se->pre, limit, tmp);
3119
4ee9c684 3120 /* Initialize the scalarizer. */
3121 gfc_init_loopinfo (&loop);
3122 gfc_add_ss_to_loop (&loop, arrayss);
3123 if (maskss)
3124 gfc_add_ss_to_loop (&loop, maskss);
3125
3126 /* Initialize the loop. */
3127 gfc_conv_ss_startstride (&loop);
30eabb0d 3128
3129 /* The code generated can have more than one loop in sequence (see the
3130 comment at the function header). This doesn't work well with the
3131 scalarizer, which changes arrays' offset when the scalarization loops
3132 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
3133 are currently inlined in the scalar case only (for which loop is of rank
3134 one). As there is no dependency to care about in that case, there is no
3135 temporary, so that we can use the scalarizer temporary code to handle
3136 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
3137 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
3138 to restore offset.
3139 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
3140 should eventually go away. We could either create two loops properly,
3141 or find another way to save/restore the array offsets between the two
3142 loops (without conflicting with temporary management), or use a single
3143 loop minmaxloc implementation. See PR 31067. */
3144 loop.temp_dim = loop.dimen;
92f4d1c4 3145 gfc_conv_loop_setup (&loop, &expr->where);
4ee9c684 3146
22d678e8 3147 gcc_assert (loop.dimen == 1);
7ebee933 3148 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
6f5c9335 3149 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3150 loop.from[0], loop.to[0]);
4ee9c684 3151
7ebee933 3152 lab1 = NULL;
3153 lab2 = NULL;
b1660f25 3154 /* Initialize the position to zero, following Fortran 2003. We are free
3155 to do this because Fortran 95 allows the result of an entirely false
7ebee933 3156 mask to be processor dependent. If we know at compile time the array
3157 is non-empty and no MASK is used, we can initialize to 1 to simplify
3158 the inner loop. */
3159 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
3160 gfc_add_modify (&loop.pre, pos,
6f5c9335 3161 fold_build3_loc (input_location, COND_EXPR,
3162 gfc_array_index_type,
3163 nonempty, gfc_index_one_node,
3164 gfc_index_zero_node));
7ebee933 3165 else
3166 {
3167 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
3168 lab1 = gfc_build_label_decl (NULL_TREE);
3169 TREE_USED (lab1) = 1;
3170 lab2 = gfc_build_label_decl (NULL_TREE);
3171 TREE_USED (lab2) = 1;
3172 }
6bcf802b 3173
e816ed35 3174 /* An offset must be added to the loop
3175 counter to obtain the required position. */
3176 gcc_assert (loop.from[0]);
3177
3178 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3179 gfc_index_one_node, loop.from[0]);
3180 gfc_add_modify (&loop.pre, offset, tmp);
3181
30eabb0d 3182 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
4ee9c684 3183 if (maskss)
30eabb0d 3184 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
4ee9c684 3185 /* Generate the loop body. */
3186 gfc_start_scalarized_body (&loop, &body);
3187
3188 /* If we have a mask, only check this element if the mask is set. */
3189 if (maskss)
3190 {
3191 gfc_init_se (&maskse, NULL);
3192 gfc_copy_loopinfo_to_se (&maskse, &loop);
3193 maskse.ss = maskss;
3194 gfc_conv_expr_val (&maskse, maskexpr);
3195 gfc_add_block_to_block (&body, &maskse.pre);
3196
3197 gfc_start_block (&block);
3198 }
3199 else
3200 gfc_init_block (&block);
3201
3202 /* Compare with the current limit. */
3203 gfc_init_se (&arrayse, NULL);
3204 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3205 arrayse.ss = arrayss;
3206 gfc_conv_expr_val (&arrayse, arrayexpr);
3207 gfc_add_block_to_block (&block, &arrayse.pre);
3208
3209 /* We do the following if this is a more extreme value. */
3210 gfc_start_block (&ifblock);
3211
3212 /* Assign the value to the limit... */
75a70cf9 3213 gfc_add_modify (&ifblock, limit, arrayse.expr);
4ee9c684 3214
7ebee933 3215 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
3216 {
3217 stmtblock_t ifblock2;
3218 tree ifbody2;
3219
3220 gfc_start_block (&ifblock2);
6f5c9335 3221 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3222 loop.loopvar[0], offset);
7ebee933 3223 gfc_add_modify (&ifblock2, pos, tmp);
3224 ifbody2 = gfc_finish_block (&ifblock2);
6f5c9335 3225 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, pos,
3226 gfc_index_zero_node);
7ebee933 3227 tmp = build3_v (COND_EXPR, cond, ifbody2,
3228 build_empty_stmt (input_location));
3229 gfc_add_expr_to_block (&block, tmp);
3230 }
3231
6f5c9335 3232 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3233 loop.loopvar[0], offset);
75a70cf9 3234 gfc_add_modify (&ifblock, pos, tmp);
4ee9c684 3235
7ebee933 3236 if (lab1)
3237 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
3238
4ee9c684 3239 ifbody = gfc_finish_block (&ifblock);
3240
7ebee933 3241 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
3242 {
3243 if (lab1)
6f5c9335 3244 cond = fold_build2_loc (input_location,
3245 op == GT_EXPR ? GE_EXPR : LE_EXPR,
3246 boolean_type_node, arrayse.expr, limit);
7ebee933 3247 else
6f5c9335 3248 cond = fold_build2_loc (input_location, op, boolean_type_node,
3249 arrayse.expr, limit);
7ebee933 3250
3251 ifbody = build3_v (COND_EXPR, cond, ifbody,
3252 build_empty_stmt (input_location));
3253 }
3254 gfc_add_expr_to_block (&block, ifbody);
4ee9c684 3255
3256 if (maskss)
3257 {
3258 /* We enclose the above in if (mask) {...}. */
3259 tmp = gfc_finish_block (&block);
3260
e60a6f7b 3261 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3262 build_empty_stmt (input_location));
4ee9c684 3263 }
3264 else
3265 tmp = gfc_finish_block (&block);
3266 gfc_add_expr_to_block (&body, tmp);
3267
7ebee933 3268 if (lab1)
3269 {
30eabb0d 3270 gfc_trans_scalarized_loop_boundary (&loop, &body);
7ebee933 3271
3272 if (HONOR_NANS (DECL_MODE (limit)))
3273 {
3274 if (nonempty != NULL)
3275 {
3276 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
3277 tmp = build3_v (COND_EXPR, nonempty, ifbody,
3278 build_empty_stmt (input_location));
3279 gfc_add_expr_to_block (&loop.code[0], tmp);
3280 }
3281 }
3282
3283 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
3284 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
7ebee933 3285
3286 /* If we have a mask, only check this element if the mask is set. */
3287 if (maskss)
3288 {
3289 gfc_init_se (&maskse, NULL);
3290 gfc_copy_loopinfo_to_se (&maskse, &loop);
3291 maskse.ss = maskss;
3292 gfc_conv_expr_val (&maskse, maskexpr);
3293 gfc_add_block_to_block (&body, &maskse.pre);
3294
3295 gfc_start_block (&block);
3296 }
3297 else
3298 gfc_init_block (&block);
3299
3300 /* Compare with the current limit. */
3301 gfc_init_se (&arrayse, NULL);
3302 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3303 arrayse.ss = arrayss;
3304 gfc_conv_expr_val (&arrayse, arrayexpr);
3305 gfc_add_block_to_block (&block, &arrayse.pre);
3306
3307 /* We do the following if this is a more extreme value. */
3308 gfc_start_block (&ifblock);
3309
3310 /* Assign the value to the limit... */
3311 gfc_add_modify (&ifblock, limit, arrayse.expr);
3312
6f5c9335 3313 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
3314 loop.loopvar[0], offset);
7ebee933 3315 gfc_add_modify (&ifblock, pos, tmp);
3316
3317 ifbody = gfc_finish_block (&ifblock);
3318
6f5c9335 3319 cond = fold_build2_loc (input_location, op, boolean_type_node,
3320 arrayse.expr, limit);
7ebee933 3321
3322 tmp = build3_v (COND_EXPR, cond, ifbody,
3323 build_empty_stmt (input_location));
3324 gfc_add_expr_to_block (&block, tmp);
3325
3326 if (maskss)
3327 {
3328 /* We enclose the above in if (mask) {...}. */
3329 tmp = gfc_finish_block (&block);
3330
3331 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3332 build_empty_stmt (input_location));
3333 }
3334 else
3335 tmp = gfc_finish_block (&block);
3336 gfc_add_expr_to_block (&body, tmp);
3337 /* Avoid initializing loopvar[0] again, it should be left where
3338 it finished by the first loop. */
3339 loop.from[0] = loop.loopvar[0];
3340 }
3341
4ee9c684 3342 gfc_trans_scalarizing_loops (&loop, &body);
3343
7ebee933 3344 if (lab2)
3345 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
3346
622183f4 3347 /* For a scalar mask, enclose the loop in an if statement. */
3348 if (maskexpr && maskss == NULL)
3349 {
3350 gfc_init_se (&maskse, NULL);
3351 gfc_conv_expr_val (&maskse, maskexpr);
3352 gfc_init_block (&block);
3353 gfc_add_block_to_block (&block, &loop.pre);
3354 gfc_add_block_to_block (&block, &loop.post);
3355 tmp = gfc_finish_block (&block);
3356
3357 /* For the else part of the scalar mask, just initialize
3358 the pos variable the same way as above. */
3359
3360 gfc_init_block (&elseblock);
75a70cf9 3361 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
622183f4 3362 elsetmp = gfc_finish_block (&elseblock);
3363
3364 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
3365 gfc_add_expr_to_block (&block, tmp);
3366 gfc_add_block_to_block (&se->pre, &block);
3367 }
3368 else
3369 {
3370 gfc_add_block_to_block (&se->pre, &loop.pre);
3371 gfc_add_block_to_block (&se->pre, &loop.post);
3372 }
4ee9c684 3373 gfc_cleanup_loop (&loop);
3374
30dc020c 3375 se->expr = convert (type, pos);
4ee9c684 3376}
3377
7ebee933 3378/* Emit code for minval or maxval intrinsic. There are many different cases
3379 we need to handle. For performance reasons we sometimes create two
3380 loops instead of one, where the second one is much simpler.
3381 Examples for minval intrinsic:
3382 1) Result is an array, a call is generated
3383 2) Array mask is used and NaNs need to be supported, rank 1:
3384 limit = Infinity;
3385 nonempty = false;
3386 S = from;
3387 while (S <= to) {
3388 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
3389 S++;
3390 }
3391 limit = nonempty ? NaN : huge (limit);
3392 lab:
3393 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
3394 3) NaNs need to be supported, but it is known at compile time or cheaply
3395 at runtime whether array is nonempty or not, rank 1:
3396 limit = Infinity;
3397 S = from;
3398 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
3399 limit = (from <= to) ? NaN : huge (limit);
3400 lab:
3401 while (S <= to) { limit = min (a[S], limit); S++; }
3402 4) Array mask is used and NaNs need to be supported, rank > 1:
3403 limit = Infinity;
3404 nonempty = false;
3405 fast = false;
3406 S1 = from1;
3407 while (S1 <= to1) {
3408 S2 = from2;
3409 while (S2 <= to2) {
3410 if (mask[S1][S2]) {
3411 if (fast) limit = min (a[S1][S2], limit);
3412 else {
3413 nonempty = true;
3414 if (a[S1][S2] <= limit) {
3415 limit = a[S1][S2];
3416 fast = true;
3417 }
3418 }
3419 }
3420 S2++;
3421 }
3422 S1++;
3423 }
3424 if (!fast)
3425 limit = nonempty ? NaN : huge (limit);
3426 5) NaNs need to be supported, but it is known at compile time or cheaply
3427 at runtime whether array is nonempty or not, rank > 1:
3428 limit = Infinity;
3429 fast = false;
3430 S1 = from1;
3431 while (S1 <= to1) {
3432 S2 = from2;
3433 while (S2 <= to2) {
3434 if (fast) limit = min (a[S1][S2], limit);
3435 else {
3436 if (a[S1][S2] <= limit) {
3437 limit = a[S1][S2];
3438 fast = true;
3439 }
3440 }
3441 S2++;
3442 }
3443 S1++;
3444 }
3445 if (!fast)
3446 limit = (nonempty_array) ? NaN : huge (limit);
3447 6) NaNs aren't supported, but infinities are. Array mask is used:
3448 limit = Infinity;
3449 nonempty = false;
3450 S = from;
3451 while (S <= to) {
3452 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
3453 S++;
3454 }
3455 limit = nonempty ? limit : huge (limit);
3456 7) Same without array mask:
3457 limit = Infinity;
3458 S = from;
3459 while (S <= to) { limit = min (a[S], limit); S++; }
3460 limit = (from <= to) ? limit : huge (limit);
3461 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
3462 limit = huge (limit);
3463 S = from;
3464 while (S <= to) { limit = min (a[S], limit); S++); }
3465 (or
3466 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
3467 with array mask instead).
3468 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
3469 setting limit = huge (limit); in the else branch. */
3470
4ee9c684 3471static void
d62fb8de 3472gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
4ee9c684 3473{
3474 tree limit;
3475 tree type;
3476 tree tmp;
3477 tree ifbody;
7ebee933 3478 tree nonempty;
3479 tree nonempty_var;
3480 tree lab;
3481 tree fast;
3482 tree huge_cst = NULL, nan_cst = NULL;
4ee9c684 3483 stmtblock_t body;
7ebee933 3484 stmtblock_t block, block2;
4ee9c684 3485 gfc_loopinfo loop;
3486 gfc_actual_arglist *actual;
3487 gfc_ss *arrayss;
3488 gfc_ss *maskss;
3489 gfc_se arrayse;
3490 gfc_se maskse;
3491 gfc_expr *arrayexpr;
3492 gfc_expr *maskexpr;
3493 int n;
3494
3495 if (se->ss)
3496 {
3497 gfc_conv_intrinsic_funcall (se, expr);
3498 return;
3499 }
3500
3501 type = gfc_typenode_for_spec (&expr->ts);
3502 /* Initialize the result. */
3503 limit = gfc_create_var (type, "limit");
f2d4ef3b 3504 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
4ee9c684 3505 switch (expr->ts.type)
3506 {
3507 case BT_REAL:
7ebee933 3508 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
3509 expr->ts.kind, 0);
3510 if (HONOR_INFINITIES (DECL_MODE (limit)))
3511 {
3512 REAL_VALUE_TYPE real;
3513 real_inf (&real);
3514 tmp = build_real (type, real);
3515 }
3516 else
3517 tmp = huge_cst;
3518 if (HONOR_NANS (DECL_MODE (limit)))
3519 {
3520 REAL_VALUE_TYPE real;
3521 real_nan (&real, "", 1, DECL_MODE (limit));
3522 nan_cst = build_real (type, real);
3523 }
4ee9c684 3524 break;
3525
3526 case BT_INTEGER:
3527 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
3528 break;
3529
3530 default:
22d678e8 3531 gcc_unreachable ();
4ee9c684 3532 }
3533
1706268d 3534 /* We start with the most negative possible value for MAXVAL, and the most
3535 positive possible value for MINVAL. The most negative possible value is
3536 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
f6d0e37a 3537 possible value is HUGE in both cases. */
4ee9c684 3538 if (op == GT_EXPR)
7ebee933 3539 {
6f5c9335 3540 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
7ebee933 3541 if (huge_cst)
6f5c9335 3542 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
3543 TREE_TYPE (huge_cst), huge_cst);
7ebee933 3544 }
1706268d 3545
3546 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
6f5c9335 3547 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
3548 tmp, build_int_cst (type, 1));
1706268d 3549
75a70cf9 3550 gfc_add_modify (&se->pre, limit, tmp);
4ee9c684 3551
3552 /* Walk the arguments. */
3553 actual = expr->value.function.actual;
3554 arrayexpr = actual->expr;
3555 arrayss = gfc_walk_expr (arrayexpr);
22d678e8 3556 gcc_assert (arrayss != gfc_ss_terminator);
4ee9c684 3557
3558 actual = actual->next->next;
22d678e8 3559 gcc_assert (actual);
4ee9c684 3560 maskexpr = actual->expr;
7ebee933 3561 nonempty = NULL;
91b2f40f 3562 if (maskexpr && maskexpr->rank != 0)
4ee9c684 3563 {
3564 maskss = gfc_walk_expr (maskexpr);
22d678e8 3565 gcc_assert (maskss != gfc_ss_terminator);
4ee9c684 3566 }
3567 else
7ebee933 3568 {
3569 mpz_t asize;
3570 if (gfc_array_size (arrayexpr, &asize) == SUCCESS)
3571 {
3572 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
3573 mpz_clear (asize);
6f5c9335 3574 nonempty = fold_build2_loc (input_location, GT_EXPR,
3575 boolean_type_node, nonempty,
3576 gfc_index_zero_node);
7ebee933 3577 }
3578 maskss = NULL;
3579 }
4ee9c684 3580
3581 /* Initialize the scalarizer. */
3582 gfc_init_loopinfo (&loop);
3583 gfc_add_ss_to_loop (&loop, arrayss);
3584 if (maskss)
3585 gfc_add_ss_to_loop (&loop, maskss);
3586
3587 /* Initialize the loop. */
3588 gfc_conv_ss_startstride (&loop);
469bafde 3589
3590 /* The code generated can have more than one loop in sequence (see the
3591 comment at the function header). This doesn't work well with the
3592 scalarizer, which changes arrays' offset when the scalarization loops
3593 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
3594 are currently inlined in the scalar case only. As there is no dependency
3595 to care about in that case, there is no temporary, so that we can use the
3596 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
3597 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
3598 gfc_trans_scalarized_loop_boundary even later to restore offset.
3599 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
3600 should eventually go away. We could either create two loops properly,
3601 or find another way to save/restore the array offsets between the two
3602 loops (without conflicting with temporary management), or use a single
3603 loop minmaxval implementation. See PR 31067. */
3604 loop.temp_dim = loop.dimen;
92f4d1c4 3605 gfc_conv_loop_setup (&loop, &expr->where);
4ee9c684 3606
7ebee933 3607 if (nonempty == NULL && maskss == NULL
3608 && loop.dimen == 1 && loop.from[0] && loop.to[0])
6f5c9335 3609 nonempty = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3610 loop.from[0], loop.to[0]);
7ebee933 3611 nonempty_var = NULL;
3612 if (nonempty == NULL
3613 && (HONOR_INFINITIES (DECL_MODE (limit))
3614 || HONOR_NANS (DECL_MODE (limit))))
3615 {
3616 nonempty_var = gfc_create_var (boolean_type_node, "nonempty");
3617 gfc_add_modify (&se->pre, nonempty_var, boolean_false_node);
3618 nonempty = nonempty_var;
3619 }
3620 lab = NULL;
3621 fast = NULL;
3622 if (HONOR_NANS (DECL_MODE (limit)))
3623 {
3624 if (loop.dimen == 1)
3625 {
3626 lab = gfc_build_label_decl (NULL_TREE);
3627 TREE_USED (lab) = 1;
3628 }
3629 else
3630 {
3631 fast = gfc_create_var (boolean_type_node, "fast");
3632 gfc_add_modify (&se->pre, fast, boolean_false_node);
3633 }
3634 }
3635
469bafde 3636 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
4ee9c684 3637 if (maskss)
469bafde 3638 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
4ee9c684 3639 /* Generate the loop body. */
3640 gfc_start_scalarized_body (&loop, &body);
3641
3642 /* If we have a mask, only add this element if the mask is set. */
3643 if (maskss)
3644 {
3645 gfc_init_se (&maskse, NULL);
3646 gfc_copy_loopinfo_to_se (&maskse, &loop);
3647 maskse.ss = maskss;
3648 gfc_conv_expr_val (&maskse, maskexpr);
3649 gfc_add_block_to_block (&body, &maskse.pre);
3650
3651 gfc_start_block (&block);
3652 }
3653 else
3654 gfc_init_block (&block);
3655
3656 /* Compare with the current limit. */
3657 gfc_init_se (&arrayse, NULL);
3658 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3659 arrayse.ss = arrayss;
3660 gfc_conv_expr_val (&arrayse, arrayexpr);
3661 gfc_add_block_to_block (&block, &arrayse.pre);
3662
7ebee933 3663 gfc_init_block (&block2);
3664
3665 if (nonempty_var)
3666 gfc_add_modify (&block2, nonempty_var, boolean_true_node);
3667
3668 if (HONOR_NANS (DECL_MODE (limit)))
3669 {
6f5c9335 3670 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
3671 boolean_type_node, arrayse.expr, limit);
7ebee933 3672 if (lab)
3673 ifbody = build1_v (GOTO_EXPR, lab);
3674 else
3675 {
3676 stmtblock_t ifblock;
3677
3678 gfc_init_block (&ifblock);
3679 gfc_add_modify (&ifblock, limit, arrayse.expr);
3680 gfc_add_modify (&ifblock, fast, boolean_true_node);
3681 ifbody = gfc_finish_block (&ifblock);
3682 }
3683 tmp = build3_v (COND_EXPR, tmp, ifbody,
3684 build_empty_stmt (input_location));
3685 gfc_add_expr_to_block (&block2, tmp);
3686 }
3687 else
3688 {
3689 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3690 signed zeros. */
3691 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3692 {
6f5c9335 3693 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3694 arrayse.expr, limit);
7ebee933 3695 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3696 tmp = build3_v (COND_EXPR, tmp, ifbody,
3697 build_empty_stmt (input_location));
3698 gfc_add_expr_to_block (&block2, tmp);
3699 }
3700 else
3701 {
6f5c9335 3702 tmp = fold_build2_loc (input_location,
3703 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3704 type, arrayse.expr, limit);
7ebee933 3705 gfc_add_modify (&block2, limit, tmp);
3706 }
3707 }
3708
3709 if (fast)
3710 {
3711 tree elsebody = gfc_finish_block (&block2);
3712
3713 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3714 signed zeros. */
3715 if (HONOR_NANS (DECL_MODE (limit))
3716 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3717 {
6f5c9335 3718 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3719 arrayse.expr, limit);
7ebee933 3720 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3721 ifbody = build3_v (COND_EXPR, tmp, ifbody,
3722 build_empty_stmt (input_location));
3723 }
3724 else
3725 {
6f5c9335 3726 tmp = fold_build2_loc (input_location,
3727 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3728 type, arrayse.expr, limit);
7ebee933 3729 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
3730 }
3731 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
3732 gfc_add_expr_to_block (&block, tmp);
3733 }
3734 else
3735 gfc_add_block_to_block (&block, &block2);
4ee9c684 3736
4ee9c684 3737 gfc_add_block_to_block (&block, &arrayse.post);
3738
3739 tmp = gfc_finish_block (&block);
3740 if (maskss)
ed52ef8b 3741 /* We enclose the above in if (mask) {...}. */
e60a6f7b 3742 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3743 build_empty_stmt (input_location));
4ee9c684 3744 gfc_add_expr_to_block (&body, tmp);
3745
7ebee933 3746 if (lab)
3747 {
469bafde 3748 gfc_trans_scalarized_loop_boundary (&loop, &body);
7ebee933 3749
6f5c9335 3750 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
3751 nan_cst, huge_cst);
7ebee933 3752 gfc_add_modify (&loop.code[0], limit, tmp);
3753 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
3754
7ebee933 3755 /* If we have a mask, only add this element if the mask is set. */
3756 if (maskss)
3757 {
3758 gfc_init_se (&maskse, NULL);
3759 gfc_copy_loopinfo_to_se (&maskse, &loop);
3760 maskse.ss = maskss;
3761 gfc_conv_expr_val (&maskse, maskexpr);
3762 gfc_add_block_to_block (&body, &maskse.pre);
3763
3764 gfc_start_block (&block);
3765 }
3766 else
3767 gfc_init_block (&block);
3768
3769 /* Compare with the current limit. */
3770 gfc_init_se (&arrayse, NULL);
3771 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3772 arrayse.ss = arrayss;
3773 gfc_conv_expr_val (&arrayse, arrayexpr);
3774 gfc_add_block_to_block (&block, &arrayse.pre);
3775
3776 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3777 signed zeros. */
3778 if (HONOR_NANS (DECL_MODE (limit))
3779 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3780 {
6f5c9335 3781 tmp = fold_build2_loc (input_location, op, boolean_type_node,
3782 arrayse.expr, limit);
7ebee933 3783 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3784 tmp = build3_v (COND_EXPR, tmp, ifbody,
3785 build_empty_stmt (input_location));
3786 gfc_add_expr_to_block (&block, tmp);
3787 }
3788 else
3789 {
6f5c9335 3790 tmp = fold_build2_loc (input_location,
3791 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3792 type, arrayse.expr, limit);
7ebee933 3793 gfc_add_modify (&block, limit, tmp);
3794 }
3795
3796 gfc_add_block_to_block (&block, &arrayse.post);
3797
3798 tmp = gfc_finish_block (&block);
3799 if (maskss)
3800 /* We enclose the above in if (mask) {...}. */
3801 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3802 build_empty_stmt (input_location));
3803 gfc_add_expr_to_block (&body, tmp);
3804 /* Avoid initializing loopvar[0] again, it should be left where
3805 it finished by the first loop. */
3806 loop.from[0] = loop.loopvar[0];
3807 }
4ee9c684 3808 gfc_trans_scalarizing_loops (&loop, &body);
3809
7ebee933 3810 if (fast)
3811 {
6f5c9335 3812 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
3813 nan_cst, huge_cst);
7ebee933 3814 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
3815 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
3816 ifbody);
3817 gfc_add_expr_to_block (&loop.pre, tmp);
3818 }
3819 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
3820 {
6f5c9335 3821 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
3822 huge_cst);
7ebee933 3823 gfc_add_modify (&loop.pre, limit, tmp);
3824 }
3825
91b2f40f 3826 /* For a scalar mask, enclose the loop in an if statement. */
3827 if (maskexpr && maskss == NULL)
3828 {
7ebee933 3829 tree else_stmt;
3830
91b2f40f 3831 gfc_init_se (&maskse, NULL);
3832 gfc_conv_expr_val (&maskse, maskexpr);
3833 gfc_init_block (&block);
3834 gfc_add_block_to_block (&block, &loop.pre);
3835 gfc_add_block_to_block (&block, &loop.post);
3836 tmp = gfc_finish_block (&block);
3837
7ebee933 3838 if (HONOR_INFINITIES (DECL_MODE (limit)))
3839 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
3840 else
3841 else_stmt = build_empty_stmt (input_location);
3842 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
91b2f40f 3843 gfc_add_expr_to_block (&block, tmp);
3844 gfc_add_block_to_block (&se->pre, &block);
3845 }
3846 else
3847 {
3848 gfc_add_block_to_block (&se->pre, &loop.pre);
3849 gfc_add_block_to_block (&se->pre, &loop.post);
3850 }
3851
4ee9c684 3852 gfc_cleanup_loop (&loop);
3853
3854 se->expr = limit;
3855}
3856
3857/* BTEST (i, pos) = (i & (1 << pos)) != 0. */
3858static void
3859gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
3860{
5ddb0172 3861 tree args[2];
4ee9c684 3862 tree type;
3863 tree tmp;
3864
5ddb0172 3865 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3866 type = TREE_TYPE (args[0]);
4ee9c684 3867
6f5c9335 3868 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3869 build_int_cst (type, 1), args[1]);
3870 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
3871 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
3872 build_int_cst (type, 0));
4ee9c684 3873 type = gfc_typenode_for_spec (&expr->ts);
3874 se->expr = convert (type, tmp);
3875}
3876
f004c7aa 3877
3878/* Generate code for BGE, BGT, BLE and BLT intrinsics. */
3879static void
3880gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
3881{
3882 tree args[2];
3883
3884 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3885
3886 /* Convert both arguments to the unsigned type of the same size. */
3887 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
3888 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
3889
3890 /* If they have unequal type size, convert to the larger one. */
3891 if (TYPE_PRECISION (TREE_TYPE (args[0]))
3892 > TYPE_PRECISION (TREE_TYPE (args[1])))
3893 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
3894 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
3895 > TYPE_PRECISION (TREE_TYPE (args[0])))
3896 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
3897
3898 /* Now, we compare them. */
3899 se->expr = fold_build2_loc (input_location, op, boolean_type_node,
3900 args[0], args[1]);
3901}
3902
3903
4ee9c684 3904/* Generate code to perform the specified operation. */
3905static void
d62fb8de 3906gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
4ee9c684 3907{
5ddb0172 3908 tree args[2];
4ee9c684 3909
5ddb0172 3910 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6f5c9335 3911 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
3912 args[0], args[1]);
4ee9c684 3913}
3914
3915/* Bitwise not. */
3916static void
3917gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
3918{
3919 tree arg;
3920
5ddb0172 3921 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6f5c9335 3922 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
3923 TREE_TYPE (arg), arg);
4ee9c684 3924}
3925
3926/* Set or clear a single bit. */
3927static void
3928gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
3929{
5ddb0172 3930 tree args[2];
4ee9c684 3931 tree type;
3932 tree tmp;
d62fb8de 3933 enum tree_code op;
4ee9c684 3934
5ddb0172 3935 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3936 type = TREE_TYPE (args[0]);
4ee9c684 3937
6f5c9335 3938 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3939 build_int_cst (type, 1), args[1]);
4ee9c684 3940 if (set)
3941 op = BIT_IOR_EXPR;
3942 else
3943 {
3944 op = BIT_AND_EXPR;
6f5c9335 3945 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
4ee9c684 3946 }
6f5c9335 3947 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
4ee9c684 3948}
3949
3950/* Extract a sequence of bits.
3951 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
3952static void
3953gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
3954{
5ddb0172 3955 tree args[3];
4ee9c684 3956 tree type;
3957 tree tmp;
3958 tree mask;
3959
5ddb0172 3960 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3961 type = TREE_TYPE (args[0]);
4ee9c684 3962
33130b1d 3963 mask = build_int_cst (type, -1);
6f5c9335 3964 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
3965 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
4ee9c684 3966
6f5c9335 3967 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
4ee9c684 3968
6f5c9335 3969 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
4ee9c684 3970}
3971
d2fc5bb1 3972static void
f004c7aa 3973gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
3974 bool arithmetic)
d2fc5bb1 3975{
f004c7aa 3976 tree args[2], type, num_bits, cond;
d2fc5bb1 3977
5ddb0172 3978 gfc_conv_intrinsic_function_args (se, expr, args, 2);
d2fc5bb1 3979
f004c7aa 3980 args[0] = gfc_evaluate_now (args[0], &se->pre);
3981 args[1] = gfc_evaluate_now (args[1], &se->pre);
3982 type = TREE_TYPE (args[0]);
3983
3984 if (!arithmetic)
3985 args[0] = fold_convert (unsigned_type_for (type), args[0]);
3986 else
3987 gcc_assert (right_shift);
3988
6f5c9335 3989 se->expr = fold_build2_loc (input_location,
3990 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
3991 TREE_TYPE (args[0]), args[0], args[1]);
f004c7aa 3992
3993 if (!arithmetic)
3994 se->expr = fold_convert (type, se->expr);
3995
3996 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
3997 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
3998 special case. */
3999 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
4000 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
4001 args[1], num_bits);
4002
4003 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
4004 build_int_cst (type, 0), se->expr);
d2fc5bb1 4005}
4006
4d66f715 4007/* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
4008 ? 0
4009 : ((shift >= 0) ? i << shift : i >> -shift)
4010 where all shifts are logical shifts. */
4ee9c684 4011static void
4012gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
4013{
5ddb0172 4014 tree args[2];
4ee9c684 4015 tree type;
4d66f715 4016 tree utype;
4ee9c684 4017 tree tmp;
4d66f715 4018 tree width;
4019 tree num_bits;
4020 tree cond;
4ee9c684 4021 tree lshift;
4022 tree rshift;
4023
5ddb0172 4024 gfc_conv_intrinsic_function_args (se, expr, args, 2);
15da0ca7 4025
4026 args[0] = gfc_evaluate_now (args[0], &se->pre);
4027 args[1] = gfc_evaluate_now (args[1], &se->pre);
4028
5ddb0172 4029 type = TREE_TYPE (args[0]);
71eea85c 4030 utype = unsigned_type_for (type);
4ee9c684 4031
6f5c9335 4032 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
4033 args[1]);
4ee9c684 4034
4d66f715 4035 /* Left shift if positive. */
6f5c9335 4036 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
4d66f715 4037
f50c9c11 4038 /* Right shift if negative.
4039 We convert to an unsigned type because we want a logical shift.
4040 The standard doesn't define the case of shifting negative
4041 numbers, and we try to be compatible with other compilers, most
4042 notably g77, here. */
6f5c9335 4043 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
4044 utype, convert (utype, args[0]), width));
4d66f715 4045
6f5c9335 4046 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, args[1],
4047 build_int_cst (TREE_TYPE (args[1]), 0));
4048 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
4d66f715 4049
4050 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4051 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4052 special case. */
bdb4cd30 4053 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6f5c9335 4054 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, width,
4055 num_bits);
4056 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
4057 build_int_cst (type, 0), tmp);
4ee9c684 4058}
4059
9dd6c589 4060
4ee9c684 4061/* Circular shift. AKA rotate or barrel shift. */
9dd6c589 4062
4ee9c684 4063static void
4064gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
4065{
5ddb0172 4066 tree *args;
4ee9c684 4067 tree type;
4068 tree tmp;
4069 tree lrot;
4070 tree rrot;
6dbb04e3 4071 tree zero;
5ddb0172 4072 unsigned int num_args;
4ee9c684 4073
5ddb0172 4074 num_args = gfc_intrinsic_argument_list_length (expr);
86b32f71 4075 args = XALLOCAVEC (tree, num_args);
5ddb0172 4076
4077 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4078
4079 if (num_args == 3)
4ee9c684 4080 {
4081 /* Use a library function for the 3 parameter version. */
4d66f715 4082 tree int4type = gfc_get_int_type (4);
4083
5ddb0172 4084 type = TREE_TYPE (args[0]);
4d66f715 4085 /* We convert the first argument to at least 4 bytes, and
4086 convert back afterwards. This removes the need for library
4087 functions for all argument sizes, and function will be
4088 aligned to at least 32 bits, so there's no loss. */
4089 if (expr->ts.kind < 4)
5ddb0172 4090 args[0] = convert (int4type, args[0]);
4091
4d66f715 4092 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
4093 need loads of library functions. They cannot have values >
4094 BIT_SIZE (I) so the conversion is safe. */
5ddb0172 4095 args[1] = convert (int4type, args[1]);
4096 args[2] = convert (int4type, args[2]);
4ee9c684 4097
4098 switch (expr->ts.kind)
4099 {
4d66f715 4100 case 1:
4101 case 2:
4ee9c684 4102 case 4:
4103 tmp = gfor_fndecl_math_ishftc4;
4104 break;
4105 case 8:
4106 tmp = gfor_fndecl_math_ishftc8;
4107 break;
920e54ef 4108 case 16:
4109 tmp = gfor_fndecl_math_ishftc16;
4110 break;
4ee9c684 4111 default:
22d678e8 4112 gcc_unreachable ();
4ee9c684 4113 }
389dd41b 4114 se->expr = build_call_expr_loc (input_location,
15da0ca7 4115 tmp, 3, args[0], args[1], args[2]);
4d66f715 4116 /* Convert the result back to the original type, if we extended
4117 the first argument's width above. */
4118 if (expr->ts.kind < 4)
4119 se->expr = convert (type, se->expr);
4120
4ee9c684 4121 return;
4122 }
5ddb0172 4123 type = TREE_TYPE (args[0]);
4ee9c684 4124
15da0ca7 4125 /* Evaluate arguments only once. */
4126 args[0] = gfc_evaluate_now (args[0], &se->pre);
4127 args[1] = gfc_evaluate_now (args[1], &se->pre);
4128
4ee9c684 4129 /* Rotate left if positive. */
6f5c9335 4130 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
4ee9c684 4131
4132 /* Rotate right if negative. */
6f5c9335 4133 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
4134 args[1]);
4135 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
4ee9c684 4136
5ddb0172 4137 zero = build_int_cst (TREE_TYPE (args[1]), 0);
6f5c9335 4138 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, args[1],
4139 zero);
4140 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
4ee9c684 4141
4142 /* Do nothing if shift == 0. */
6f5c9335 4143 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, args[1],
4144 zero);
4145 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
4146 rrot);
4ee9c684 4147}
4148
4bfb5282 4149
0b820f43 4150/* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
4151 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
4152
4153 The conditional expression is necessary because the result of LEADZ(0)
4154 is defined, but the result of __builtin_clz(0) is undefined for most
4155 targets.
4156
4157 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
4158 difference in bit size between the argument of LEADZ and the C int. */
4159
4160static void
4161gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
4162{
4163 tree arg;
4164 tree arg_type;
4165 tree cond;
4166 tree result_type;
4167 tree leadz;
4168 tree bit_size;
4169 tree tmp;
70eb4f1a 4170 tree func;
4171 int s, argsize;
0b820f43 4172
4173 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
70eb4f1a 4174 argsize = TYPE_PRECISION (TREE_TYPE (arg));
0b820f43 4175
4176 /* Which variant of __builtin_clz* should we call? */
70eb4f1a 4177 if (argsize <= INT_TYPE_SIZE)
4178 {
4179 arg_type = unsigned_type_node;
b9a16870 4180 func = builtin_decl_explicit (BUILT_IN_CLZ);
70eb4f1a 4181 }
4182 else if (argsize <= LONG_TYPE_SIZE)
4183 {
4184 arg_type = long_unsigned_type_node;
b9a16870 4185 func = builtin_decl_explicit (BUILT_IN_CLZL);
70eb4f1a 4186 }
4187 else if (argsize <= LONG_LONG_TYPE_SIZE)
4188 {
4189 arg_type = long_long_unsigned_type_node;
b9a16870 4190 func = builtin_decl_explicit (BUILT_IN_CLZLL);
70eb4f1a 4191 }
4192 else
4193 {
4bfb5282 4194 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
70eb4f1a 4195 arg_type = gfc_build_uint_type (argsize);
4bfb5282 4196 func = NULL_TREE;
0b820f43 4197 }
4198
70eb4f1a 4199 /* Convert the actual argument twice: first, to the unsigned type of the
4200 same size; then, to the proper argument type for the built-in
0b820f43 4201 function. But the return type is of the default INTEGER kind. */
70eb4f1a 4202 arg = fold_convert (gfc_build_uint_type (argsize), arg);
0b820f43 4203 arg = fold_convert (arg_type, arg);
4bfb5282 4204 arg = gfc_evaluate_now (arg, &se->pre);
0b820f43 4205 result_type = gfc_get_int_type (gfc_default_integer_kind);
4206
4207 /* Compute LEADZ for the case i .ne. 0. */
4bfb5282 4208 if (func)
4209 {
4210 s = TYPE_PRECISION (arg_type) - argsize;
4211 tmp = fold_convert (result_type,
4212 build_call_expr_loc (input_location, func,
4213 1, arg));
4214 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
4215 tmp, build_int_cst (result_type, s));
4216 }
4217 else
4218 {
4219 /* We end up here if the argument type is larger than 'long long'.
4220 We generate this code:
4221
4222 if (x & (ULL_MAX << ULL_SIZE) != 0)
4223 return clzll ((unsigned long long) (x >> ULLSIZE));
4224 else
4225 return ULL_SIZE + clzll ((unsigned long long) x);
4bfb5282 4226 where ULL_MAX is the largest value that a ULL_MAX can hold
4227 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
4228 is the bit-size of the long long type (64 in this example). */
b9a16870 4229 tree ullsize, ullmax, tmp1, tmp2, btmp;
4bfb5282 4230
4231 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
4232 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
4233 long_long_unsigned_type_node,
4234 build_int_cst (long_long_unsigned_type_node,
4235 0));
4236
4237 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
4238 fold_convert (arg_type, ullmax), ullsize);
4239 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
4240 arg, cond);
4241 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
4242 cond, build_int_cst (arg_type, 0));
4243
4244 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
4245 arg, ullsize);
4246 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
b9a16870 4247 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4bfb5282 4248 tmp1 = fold_convert (result_type,
b9a16870 4249 build_call_expr_loc (input_location, btmp, 1, tmp1));
4bfb5282 4250
4251 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
b9a16870 4252 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
4bfb5282 4253 tmp2 = fold_convert (result_type,
b9a16870 4254 build_call_expr_loc (input_location, btmp, 1, tmp2));
4bfb5282 4255 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4256 tmp2, ullsize);
4257
4258 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
4259 cond, tmp1, tmp2);
4260 }
0b820f43 4261
4262 /* Build BIT_SIZE. */
70eb4f1a 4263 bit_size = build_int_cst (result_type, argsize);
0b820f43 4264
6f5c9335 4265 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4266 arg, build_int_cst (arg_type, 0));
4267 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
4268 bit_size, leadz);
0b820f43 4269}
4270
4bfb5282 4271
0b820f43 4272/* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
4273
4274 The conditional expression is necessary because the result of TRAILZ(0)
4275 is defined, but the result of __builtin_ctz(0) is undefined for most
4276 targets. */
4277
4278static void
4279gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
4280{
4281 tree arg;
4282 tree arg_type;
4283 tree cond;
4284 tree result_type;
4285 tree trailz;
4286 tree bit_size;
70eb4f1a 4287 tree func;
4288 int argsize;
0b820f43 4289
4290 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
70eb4f1a 4291 argsize = TYPE_PRECISION (TREE_TYPE (arg));
0b820f43 4292
70eb4f1a 4293 /* Which variant of __builtin_ctz* should we call? */
4294 if (argsize <= INT_TYPE_SIZE)
4295 {
4296 arg_type = unsigned_type_node;
b9a16870 4297 func = builtin_decl_explicit (BUILT_IN_CTZ);
70eb4f1a 4298 }
4299 else if (argsize <= LONG_TYPE_SIZE)
4300 {
4301 arg_type = long_unsigned_type_node;
b9a16870 4302 func = builtin_decl_explicit (BUILT_IN_CTZL);
70eb4f1a 4303 }
4304 else if (argsize <= LONG_LONG_TYPE_SIZE)
4305 {
4306 arg_type = long_long_unsigned_type_node;
b9a16870 4307 func = builtin_decl_explicit (BUILT_IN_CTZLL);
70eb4f1a 4308 }
4309 else
4310 {
4bfb5282 4311 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
70eb4f1a 4312 arg_type = gfc_build_uint_type (argsize);
4bfb5282 4313 func = NULL_TREE;
0b820f43 4314 }
4315
70eb4f1a 4316 /* Convert the actual argument twice: first, to the unsigned type of the
4317 same size; then, to the proper argument type for the built-in
0b820f43 4318 function. But the return type is of the default INTEGER kind. */
70eb4f1a 4319 arg = fold_convert (gfc_build_uint_type (argsize), arg);
0b820f43 4320 arg = fold_convert (arg_type, arg);
4bfb5282 4321 arg = gfc_evaluate_now (arg, &se->pre);
0b820f43 4322 result_type = gfc_get_int_type (gfc_default_integer_kind);
4323
4324 /* Compute TRAILZ for the case i .ne. 0. */
4bfb5282 4325 if (func)
4326 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
4327 func, 1, arg));
4328 else
4329 {
4330 /* We end up here if the argument type is larger than 'long long'.
4331 We generate this code:
4332
4333 if ((x & ULL_MAX) == 0)
4334 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
4335 else
4336 return ctzll ((unsigned long long) x);
4337
4338 where ULL_MAX is the largest value that a ULL_MAX can hold
4339 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
4340 is the bit-size of the long long type (64 in this example). */
b9a16870 4341 tree ullsize, ullmax, tmp1, tmp2, btmp;
4bfb5282 4342
4343 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
4344 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
4345 long_long_unsigned_type_node,
4346 build_int_cst (long_long_unsigned_type_node, 0));
4347
4348 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
4349 fold_convert (arg_type, ullmax));
4350 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, cond,
4351 build_int_cst (arg_type, 0));
4352
4353 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
4354 arg, ullsize);
4355 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
b9a16870 4356 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
4bfb5282 4357 tmp1 = fold_convert (result_type,
b9a16870 4358 build_call_expr_loc (input_location, btmp, 1, tmp1));
4bfb5282 4359 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4360 tmp1, ullsize);
4361
4362 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
b9a16870 4363 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
4bfb5282 4364 tmp2 = fold_convert (result_type,
b9a16870 4365 build_call_expr_loc (input_location, btmp, 1, tmp2));
4bfb5282 4366
4367 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
4368 cond, tmp1, tmp2);
4369 }
0b820f43 4370
4371 /* Build BIT_SIZE. */
70eb4f1a 4372 bit_size = build_int_cst (result_type, argsize);
0b820f43 4373
6f5c9335 4374 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4375 arg, build_int_cst (arg_type, 0));
4376 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
4377 bit_size, trailz);
0b820f43 4378}
8572fdb4 4379
41cbc93c 4380/* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
4381 for types larger than "long long", we call the long long built-in for
4382 the lower and higher bits and combine the result. */
4383
4384static void
4385gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
4386{
4387 tree arg;
4388 tree arg_type;
4389 tree result_type;
4390 tree func;
4391 int argsize;
4392
4393 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4394 argsize = TYPE_PRECISION (TREE_TYPE (arg));
4395 result_type = gfc_get_int_type (gfc_default_integer_kind);
4396
4397 /* Which variant of the builtin should we call? */
4398 if (argsize <= INT_TYPE_SIZE)
4399 {
4400 arg_type = unsigned_type_node;
b9a16870 4401 func = builtin_decl_explicit (parity
4402 ? BUILT_IN_PARITY
4403 : BUILT_IN_POPCOUNT);
41cbc93c 4404 }
4405 else if (argsize <= LONG_TYPE_SIZE)
4406 {
4407 arg_type = long_unsigned_type_node;
b9a16870 4408 func = builtin_decl_explicit (parity
4409 ? BUILT_IN_PARITYL
4410 : BUILT_IN_POPCOUNTL);
41cbc93c 4411 }
4412 else if (argsize <= LONG_LONG_TYPE_SIZE)
4413 {
4414 arg_type = long_long_unsigned_type_node;
b9a16870 4415 func = builtin_decl_explicit (parity
4416 ? BUILT_IN_PARITYLL
4417 : BUILT_IN_POPCOUNTLL);
41cbc93c 4418 }
4419 else
4420 {
4421 /* Our argument type is larger than 'long long', which mean none
4422 of the POPCOUNT builtins covers it. We thus call the 'long long'
4423 variant multiple times, and add the results. */
4424 tree utype, arg2, call1, call2;
4425
4426 /* For now, we only cover the case where argsize is twice as large
4427 as 'long long'. */
4428 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
4429
b9a16870 4430 func = builtin_decl_explicit (parity
4431 ? BUILT_IN_PARITYLL
4432 : BUILT_IN_POPCOUNTLL);
41cbc93c 4433
4434 /* Convert it to an integer, and store into a variable. */
4435 utype = gfc_build_uint_type (argsize);
4436 arg = fold_convert (utype, arg);
4437 arg = gfc_evaluate_now (arg, &se->pre);
4438
4439 /* Call the builtin twice. */
4440 call1 = build_call_expr_loc (input_location, func, 1,
4441 fold_convert (long_long_unsigned_type_node,
4442 arg));
4443
6f5c9335 4444 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
4445 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
41cbc93c 4446 call2 = build_call_expr_loc (input_location, func, 1,
4447 fold_convert (long_long_unsigned_type_node,
4448 arg2));
4449
4450 /* Combine the results. */
4451 if (parity)
6f5c9335 4452 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type,
4453 call1, call2);
41cbc93c 4454 else
6f5c9335 4455 se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type,
4456 call1, call2);
41cbc93c 4457
4458 return;
4459 }
4460
4461 /* Convert the actual argument twice: first, to the unsigned type of the
4462 same size; then, to the proper argument type for the built-in
4463 function. */
4464 arg = fold_convert (gfc_build_uint_type (argsize), arg);
4465 arg = fold_convert (arg_type, arg);
4466
4467 se->expr = fold_convert (result_type,
4468 build_call_expr_loc (input_location, func, 1, arg));
4469}
4470
4471
8572fdb4 4472/* Process an intrinsic with unspecified argument-types that has an optional
4473 argument (which could be of type character), e.g. EOSHIFT. For those, we
4474 need to append the string length of the optional argument if it is not
4475 present and the type is really character.
4476 primary specifies the position (starting at 1) of the non-optional argument
4477 specifying the type and optional gives the position of the optional
4478 argument in the arglist. */
4479
4480static void
4481conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
4482 unsigned primary, unsigned optional)
4483{
4484 gfc_actual_arglist* prim_arg;
4485 gfc_actual_arglist* opt_arg;
4486 unsigned cur_pos;
4487 gfc_actual_arglist* arg;
4488 gfc_symbol* sym;
f1f41a6c 4489 vec<tree, va_gc> *append_args;
8572fdb4 4490
4491 /* Find the two arguments given as position. */
4492 cur_pos = 0;
4493 prim_arg = NULL;
4494 opt_arg = NULL;
4495 for (arg = expr->value.function.actual; arg; arg = arg->next)
4496 {
4497 ++cur_pos;
4498
4499 if (cur_pos == primary)
4500 prim_arg = arg;
4501 if (cur_pos == optional)
4502 opt_arg = arg;
4503
4504 if (cur_pos >= primary && cur_pos >= optional)
4505 break;
4506 }
4507 gcc_assert (prim_arg);
4508 gcc_assert (prim_arg->expr);
4509 gcc_assert (opt_arg);
4510
4511 /* If we do have type CHARACTER and the optional argument is really absent,
4512 append a dummy 0 as string length. */
008f96d8 4513 append_args = NULL;
8572fdb4 4514 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
4515 {
4516 tree dummy;
4517
4518 dummy = build_int_cst (gfc_charlen_type_node, 0);
f1f41a6c 4519 vec_alloc (append_args, 1);
4520 append_args->quick_push (dummy);
8572fdb4 4521 }
4522
4523 /* Build the call itself. */
4524 sym = gfc_get_symbol_for_expr (expr);
64e93293 4525 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4526 append_args);
a89260f1 4527 gfc_free_symbol (sym);
8572fdb4 4528}
4529
4530
4ee9c684 4531/* The length of a character string. */
4532static void
4533gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
4534{
4535 tree len;
4536 tree type;
4537 tree decl;
4538 gfc_symbol *sym;
4539 gfc_se argse;
4540 gfc_expr *arg;
4541
22d678e8 4542 gcc_assert (!se->ss);
4ee9c684 4543
4544 arg = expr->value.function.actual->expr;
4545
4546 type = gfc_typenode_for_spec (&expr->ts);
4547 switch (arg->expr_type)
4548 {
4549 case EXPR_CONSTANT:
35bf1214 4550 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
4ee9c684 4551 break;
4552
bcb27a87 4553 case EXPR_ARRAY:
4554 /* Obtain the string length from the function used by
4555 trans-array.c(gfc_trans_array_constructor). */
4556 len = NULL_TREE;
151af988 4557 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
bcb27a87 4558 break;
4559
926b9532 4560 case EXPR_VARIABLE:
4561 if (arg->ref == NULL
4562 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
4563 {
4564 /* This doesn't catch all cases.
4565 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
4566 and the surrounding thread. */
4567 sym = arg->symtree->n.sym;
4568 decl = gfc_get_symbol_decl (sym);
4569 if (decl == current_function_decl && sym->attr.function
4ee9c684 4570 && (sym->result == sym))
926b9532 4571 decl = gfc_get_fake_result_decl (sym, 0);
4572
eeebe20b 4573 len = sym->ts.u.cl->backend_decl;
926b9532 4574 gcc_assert (len);
4575 break;
4ee9c684 4576 }
926b9532 4577
4578 /* Otherwise fall through. */
4579
4580 default:
4581 /* Anybody stupid enough to do this deserves inefficient code. */
926b9532 4582 gfc_init_se (&argse, se);
5d34a30f 4583 if (arg->rank == 0)
926b9532 4584 gfc_conv_expr (&argse, arg);
4585 else
5d34a30f 4586 gfc_conv_expr_descriptor (&argse, arg);
926b9532 4587 gfc_add_block_to_block (&se->pre, &argse.pre);
4588 gfc_add_block_to_block (&se->post, &argse.post);
4589 len = argse.string_length;
4ee9c684 4590 break;
4591 }
4592 se->expr = convert (type, len);
4593}
4594
4595/* The length of a character string not including trailing blanks. */
4596static void
4597gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
4598{
40b806de 4599 int kind = expr->value.function.actual->expr->ts.kind;
4600 tree args[2], type, fndecl;
4ee9c684 4601
5ddb0172 4602 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4ee9c684 4603 type = gfc_typenode_for_spec (&expr->ts);
40b806de 4604
4605 if (kind == 1)
4606 fndecl = gfor_fndecl_string_len_trim;
4607 else if (kind == 4)
4608 fndecl = gfor_fndecl_string_len_trim_char4;
4609 else
4610 gcc_unreachable ();
4611
389dd41b 4612 se->expr = build_call_expr_loc (input_location,
4613 fndecl, 2, args[0], args[1]);
4ee9c684 4614 se->expr = convert (type, se->expr);
4615}
4616
4617
4618/* Returns the starting position of a substring within a string. */
4619
4620static void
7fe55cc9 4621gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
4622 tree function)
4ee9c684 4623{
2eb4481b 4624 tree logical4_type_node = gfc_get_logical_type (4);
4ee9c684 4625 tree type;
5ddb0172 4626 tree fndecl;
4627 tree *args;
4628 unsigned int num_args;
4ee9c684 4629
86b32f71 4630 args = XALLOCAVEC (tree, 5);
5ddb0172 4631
24f1d2c4 4632 /* Get number of arguments; characters count double due to the
69b1505f 4633 string length argument. Kind= is not passed to the library
24f1d2c4 4634 and thus ignored. */
4635 if (expr->value.function.actual->next->next->expr == NULL)
4636 num_args = 4;
4637 else
4638 num_args = 5;
4639
4640 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
4ee9c684 4641 type = gfc_typenode_for_spec (&expr->ts);
5ddb0172 4642
4643 if (num_args == 4)
4644 args[4] = build_int_cst (logical4_type_node, 0);
4ee9c684 4645 else
7fe55cc9 4646 args[4] = convert (logical4_type_node, args[4]);
4ee9c684 4647
7fe55cc9 4648 fndecl = build_addr (function, current_function_decl);
389dd41b 4649 se->expr = build_call_array_loc (input_location,
4650 TREE_TYPE (TREE_TYPE (function)), fndecl,
7fe55cc9 4651 5, args);
4ee9c684 4652 se->expr = convert (type, se->expr);
5ddb0172 4653
4ee9c684 4654}
4655
4656/* The ascii value for a single character. */
4657static void
4658gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
4659{
40b806de 4660 tree args[2], type, pchartype;
4ee9c684 4661
5ddb0172 4662 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4663 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
40b806de 4664 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
6f5c9335 4665 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
4ee9c684 4666 type = gfc_typenode_for_spec (&expr->ts);
4667
389dd41b 4668 se->expr = build_fold_indirect_ref_loc (input_location,
4669 args[1]);
4ee9c684 4670 se->expr = convert (type, se->expr);
4671}
4672
4673
4e549567 4674/* Intrinsic ISNAN calls __builtin_isnan. */
4675
4676static void
4677gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
4678{
4679 tree arg;
4680
4681 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
389dd41b 4682 se->expr = build_call_expr_loc (input_location,
b9a16870 4683 builtin_decl_explicit (BUILT_IN_ISNAN),
4684 1, arg);
0a8db768 4685 STRIP_TYPE_NOPS (se->expr);
4e549567 4686 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
4687}
4688
52ed1096 4689
4690/* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
4691 their argument against a constant integer value. */
4692
4693static void
4694gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
4695{
4696 tree arg;
4697
4698 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6f5c9335 4699 se->expr = fold_build2_loc (input_location, EQ_EXPR,
4700 gfc_typenode_for_spec (&expr->ts),
4701 arg, build_int_cst (TREE_TYPE (arg), value));
52ed1096 4702}
4703
4704
4705
4ee9c684 4706/* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
4707
4708static void
4709gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
4710{
4ee9c684 4711 tree tsource;
4712 tree fsource;
4713 tree mask;
4714 tree type;
f24d382c 4715 tree len, len2;
5ddb0172 4716 tree *args;
4717 unsigned int num_args;
4718
4719 num_args = gfc_intrinsic_argument_list_length (expr);
86b32f71 4720 args = XALLOCAVEC (tree, num_args);
4ee9c684 4721
5ddb0172 4722 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
1e812509 4723 if (expr->ts.type != BT_CHARACTER)
4724 {
5ddb0172 4725 tsource = args[0];
4726 fsource = args[1];
4727 mask = args[2];
1e812509 4728 }
4729 else
4730 {
4731 /* We do the same as in the non-character case, but the argument
4732 list is different because of the string length arguments. We
4733 also have to set the string length for the result. */
5ddb0172 4734 len = args[0];
4735 tsource = args[1];
f24d382c 4736 len2 = args[2];
5ddb0172 4737 fsource = args[3];
4738 mask = args[4];
1e812509 4739
9c5786bd 4740 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
4741 &se->pre);
1e812509 4742 se->string_length = len;
4743 }
4ee9c684 4744 type = TREE_TYPE (tsource);
6f5c9335 4745 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
4746 fold_convert (type, fsource));
4ee9c684 4747}
4748
4749
f004c7aa 4750/* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
4751
4752static void
4753gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
4754{
4755 tree args[3], mask, type;
4756
4757 gfc_conv_intrinsic_function_args (se, expr, args, 3);
4758 mask = gfc_evaluate_now (args[2], &se->pre);
4759
4760 type = TREE_TYPE (args[0]);
4761 gcc_assert (TREE_TYPE (args[1]) == type);
4762 gcc_assert (TREE_TYPE (mask) == type);
4763
4764 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
4765 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
4766 fold_build1_loc (input_location, BIT_NOT_EXPR,
4767 type, mask));
4768 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
4769 args[0], args[1]);
4770}
4771
4772
4773/* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
4774 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
4775
4776static void
4777gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
4778{
4779 tree arg, allones, type, utype, res, cond, bitsize;
4780 int i;
4781
4782 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4783 arg = gfc_evaluate_now (arg, &se->pre);
4784
4785 type = gfc_get_int_type (expr->ts.kind);
4786 utype = unsigned_type_for (type);
4787
4788 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
4789 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
4790
4791 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
4792 build_int_cst (utype, 0));
4793
4794 if (left)
4795 {
4796 /* Left-justified mask. */
4797 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
4798 bitsize, arg);
4799 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
4800 fold_convert (utype, res));
4801
4802 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
4803 smaller than type width. */
4804 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
4805 build_int_cst (TREE_TYPE (arg), 0));
4806 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
4807 build_int_cst (utype, 0), res);
4808 }
4809 else
4810 {
4811 /* Right-justified mask. */
4812 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
4813 fold_convert (utype, arg));
4814 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
4815
4816 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
4817 strictly smaller than type width. */
4818 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4819 arg, bitsize);
4820 res = fold_build3_loc (input_location, COND_EXPR, utype,
4821 cond, allones, res);
4822 }
4823
4824 se->expr = fold_convert (type, res);
4825}
4826
4827
34e106da 4828/* FRACTION (s) is translated into frexp (s, &dummy_int). */
4829static void
4830gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
4831{
a80ae91c 4832 tree arg, type, tmp, frexp;
34e106da 4833
808656b4 4834 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
34e106da 4835
4836 type = gfc_typenode_for_spec (&expr->ts);
4837 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4838 tmp = gfc_create_var (integer_type_node, NULL);
a80ae91c 4839 se->expr = build_call_expr_loc (input_location, frexp, 2,
4840 fold_convert (type, arg),
4841 gfc_build_addr_expr (NULL_TREE, tmp));
34e106da 4842 se->expr = fold_convert (type, se->expr);
4843}
4844
4845
4846/* NEAREST (s, dir) is translated into
4792ff6e 4847 tmp = copysign (HUGE_VAL, dir);
34e106da 4848 return nextafter (s, tmp);
4849 */
4850static void
4851gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
4852{
a80ae91c 4853 tree args[2], type, tmp, nextafter, copysign, huge_val;
34e106da 4854
808656b4 4855 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
4856 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
34e106da 4857
4858 type = gfc_typenode_for_spec (&expr->ts);
4859 gfc_conv_intrinsic_function_args (se, expr, args, 2);
729e6db2 4860
4861 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
4862 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
a80ae91c 4863 fold_convert (type, args[1]));
4864 se->expr = build_call_expr_loc (input_location, nextafter, 2,
4865 fold_convert (type, args[0]), tmp);
34e106da 4866 se->expr = fold_convert (type, se->expr);
4867}
4868
4869
4870/* SPACING (s) is translated into
4871 int e;
4872 if (s == 0)
4873 res = tiny;
4874 else
4875 {
4876 frexp (s, &e);
4877 e = e - prec;
4878 e = MAX_EXPR (e, emin);
4879 res = scalbn (1., e);
4880 }
4881 return res;
4882
4883 where prec is the precision of s, gfc_real_kinds[k].digits,
4884 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
4885 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
4886
4887static void
4888gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
4889{
4890 tree arg, type, prec, emin, tiny, res, e;
a80ae91c 4891 tree cond, tmp, frexp, scalbn;
4892 int k;
34e106da 4893 stmtblock_t block;
4894
4895 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
35bf1214 4896 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
4897 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
2b6bc4f2 4898 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
34e106da 4899
808656b4 4900 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4901 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
34e106da 4902
4903 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4904 arg = gfc_evaluate_now (arg, &se->pre);
4905
4906 type = gfc_typenode_for_spec (&expr->ts);
4907 e = gfc_create_var (integer_type_node, NULL);
4908 res = gfc_create_var (type, NULL);
4909
4910
4911 /* Build the block for s /= 0. */
4912 gfc_start_block (&block);
a80ae91c 4913 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
4914 gfc_build_addr_expr (NULL_TREE, e));
34e106da 4915 gfc_add_expr_to_block (&block, tmp);
4916
6f5c9335 4917 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
4918 prec);
4919 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
4920 integer_type_node, tmp, emin));
34e106da 4921
a80ae91c 4922 tmp = build_call_expr_loc (input_location, scalbn, 2,
34e106da 4923 build_real_from_int_cst (type, integer_one_node), e);
75a70cf9 4924 gfc_add_modify (&block, res, tmp);
34e106da 4925
4926 /* Finish by building the IF statement. */
6f5c9335 4927 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, arg,
4928 build_real_from_int_cst (type, integer_zero_node));
34e106da 4929 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
4930 gfc_finish_block (&block));
4931
4932 gfc_add_expr_to_block (&se->pre, tmp);
4933 se->expr = res;
4934}
4935
4936
4937/* RRSPACING (s) is translated into
4938 int e;
4939 real x;
4940 x = fabs (s);
4941 if (x != 0)
4942 {
4943 frexp (s, &e);
4944 x = scalbn (x, precision - e);
4945 }
4946 return x;
4947
4948 where precision is gfc_real_kinds[k].digits. */
4949
4950static void
4951gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
4952{
a80ae91c 4953 tree arg, type, e, x, cond, stmt, tmp, frexp, scalbn, fabs;
4954 int prec, k;
34e106da 4955 stmtblock_t block;
4956
4957 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
4958 prec = gfc_real_kinds[k].digits;
a80ae91c 4959
808656b4 4960 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4961 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
4962 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
34e106da 4963
4964 type = gfc_typenode_for_spec (&expr->ts);
4965 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4966 arg = gfc_evaluate_now (arg, &se->pre);
4967
4968 e = gfc_create_var (integer_type_node, NULL);
4969 x = gfc_create_var (type, NULL);
75a70cf9 4970 gfc_add_modify (&se->pre, x,
a80ae91c 4971 build_call_expr_loc (input_location, fabs, 1, arg));
34e106da 4972
4973
4974 gfc_start_block (&block);
a80ae91c 4975 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
4976 gfc_build_addr_expr (NULL_TREE, e));
34e106da 4977 gfc_add_expr_to_block (&block, tmp);
4978
6f5c9335 4979 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
35bf1214 4980 build_int_cst (integer_type_node, prec), e);
a80ae91c 4981 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
75a70cf9 4982 gfc_add_modify (&block, x, tmp);
34e106da 4983 stmt = gfc_finish_block (&block);
4984
6f5c9335 4985 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, x,
4986 build_real_from_int_cst (type, integer_zero_node));
e60a6f7b 4987 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
34e106da 4988 gfc_add_expr_to_block (&se->pre, tmp);
4989
4990 se->expr = fold_convert (type, x);
4991}
4992
4993
4994/* SCALE (s, i) is translated into scalbn (s, i). */
4995static void
4996gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
4997{
a80ae91c 4998 tree args[2], type, scalbn;
34e106da 4999
808656b4 5000 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
34e106da 5001
5002 type = gfc_typenode_for_spec (&expr->ts);
5003 gfc_conv_intrinsic_function_args (se, expr, args, 2);
a80ae91c 5004 se->expr = build_call_expr_loc (input_location, scalbn, 2,
5005 fold_convert (type, args[0]),
5006 fold_convert (integer_type_node, args[1]));
34e106da 5007 se->expr = fold_convert (type, se->expr);
5008}
5009
5010
5011/* SET_EXPONENT (s, i) is translated into
5012 scalbn (frexp (s, &dummy_int), i). */
5013static void
5014gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
5015{
a80ae91c 5016 tree args[2], type, tmp, frexp, scalbn;
34e106da 5017
808656b4 5018 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
5019 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
34e106da 5020
5021 type = gfc_typenode_for_spec (&expr->ts);
5022 gfc_conv_intrinsic_function_args (se, expr, args, 2);
5023
5024 tmp = gfc_create_var (integer_type_node, NULL);
a80ae91c 5025 tmp = build_call_expr_loc (input_location, frexp, 2,
5026 fold_convert (type, args[0]),
5027 gfc_build_addr_expr (NULL_TREE, tmp));
5028 se->expr = build_call_expr_loc (input_location, scalbn, 2, tmp,
5029 fold_convert (integer_type_node, args[1]));
34e106da 5030 se->expr = fold_convert (type, se->expr);
5031}
5032
5033
4ee9c684 5034static void
5035gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
5036{
5037 gfc_actual_arglist *actual;
dd145961 5038 tree arg1;
4ee9c684 5039 tree type;
dd145961 5040 tree fncall0;
5041 tree fncall1;
4ee9c684 5042 gfc_se argse;
4ee9c684 5043
5044 gfc_init_se (&argse, NULL);
5045 actual = expr->value.function.actual;
5046
fd23cc08 5047 if (actual->expr->ts.type == BT_CLASS)
5048 gfc_add_class_array_ref (actual->expr);
5049
4ee9c684 5050 argse.want_pointer = 1;
e6a3cabf 5051 argse.data_not_needed = 1;
5d34a30f 5052 gfc_conv_expr_descriptor (&argse, actual->expr);
4ee9c684 5053 gfc_add_block_to_block (&se->pre, &argse.pre);
5054 gfc_add_block_to_block (&se->post, &argse.post);
dd145961 5055 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
5056
5057 /* Build the call to size0. */
389dd41b 5058 fncall0 = build_call_expr_loc (input_location,
5059 gfor_fndecl_size0, 1, arg1);
4ee9c684 5060
5061 actual = actual->next;
dd145961 5062
4ee9c684 5063 if (actual->expr)
5064 {
5065 gfc_init_se (&argse, NULL);
dd145961 5066 gfc_conv_expr_type (&argse, actual->expr,
5067 gfc_array_index_type);
4ee9c684 5068 gfc_add_block_to_block (&se->pre, &argse.pre);
dd145961 5069
dd145961 5070 /* Unusually, for an intrinsic, size does not exclude
5071 an optional arg2, so we must test for it. */
5072 if (actual->expr->expr_type == EXPR_VARIABLE
5073 && actual->expr->symtree->n.sym->attr.dummy
5074 && actual->expr->symtree->n.sym->attr.optional)
5075 {
5076 tree tmp;
43021eb9 5077 /* Build the call to size1. */
389dd41b 5078 fncall1 = build_call_expr_loc (input_location,
5079 gfor_fndecl_size1, 2,
43021eb9 5080 arg1, argse.expr);
5081
75367391 5082 gfc_init_se (&argse, NULL);
5083 argse.want_pointer = 1;
5084 argse.data_not_needed = 1;
5085 gfc_conv_expr (&argse, actual->expr);
5086 gfc_add_block_to_block (&se->pre, &argse.pre);
6f5c9335 5087 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5088 argse.expr, null_pointer_node);
dd145961 5089 tmp = gfc_evaluate_now (tmp, &se->pre);
6f5c9335 5090 se->expr = fold_build3_loc (input_location, COND_EXPR,
5091 pvoid_type_node, tmp, fncall1, fncall0);
dd145961 5092 }
5093 else
43021eb9 5094 {
5095 se->expr = NULL_TREE;
6f5c9335 5096 argse.expr = fold_build2_loc (input_location, MINUS_EXPR,
5097 gfc_array_index_type,
5098 argse.expr, gfc_index_one_node);
43021eb9 5099 }
5100 }
5101 else if (expr->value.function.actual->expr->rank == 1)
5102 {
4b6af10a 5103 argse.expr = gfc_index_zero_node;
43021eb9 5104 se->expr = NULL_TREE;
4ee9c684 5105 }
5106 else
dd145961 5107 se->expr = fncall0;
4ee9c684 5108
43021eb9 5109 if (se->expr == NULL_TREE)
5110 {
5111 tree ubound, lbound;
5112
389dd41b 5113 arg1 = build_fold_indirect_ref_loc (input_location,
5114 arg1);
6b1a9af3 5115 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
5116 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
6f5c9335 5117 se->expr = fold_build2_loc (input_location, MINUS_EXPR,
5118 gfc_array_index_type, ubound, lbound);
5119 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
5120 gfc_array_index_type,
5121 se->expr, gfc_index_one_node);
5122 se->expr = fold_build2_loc (input_location, MAX_EXPR,
5123 gfc_array_index_type, se->expr,
5124 gfc_index_zero_node);
43021eb9 5125 }
5126
4ee9c684 5127 type = gfc_typenode_for_spec (&expr->ts);
5128 se->expr = convert (type, se->expr);
5129}
5130
5131
329f13ad 5132/* Helper function to compute the size of a character variable,
5133 excluding the terminating null characters. The result has
5134 gfc_array_index_type type. */
5135
5136static tree
5137size_of_string_in_bytes (int kind, tree string_length)
5138{
5139 tree bytesize;
5140 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
5141
5142 bytesize = build_int_cst (gfc_array_index_type,
5143 gfc_character_kinds[i].bit_size / 8);
5144
6f5c9335 5145 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5146 bytesize,
5147 fold_convert (gfc_array_index_type, string_length));
329f13ad 5148}
5149
5150
1318f16c 5151static void
5152gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
5153{
5154 gfc_expr *arg;
1318f16c 5155 gfc_se argse;
1318f16c 5156 tree source_bytes;
5157 tree type;
5158 tree tmp;
5159 tree lower;
5160 tree upper;
1318f16c 5161 int n;
5162
5163 arg = expr->value.function.actual->expr;
5164
5165 gfc_init_se (&argse, NULL);
1318f16c 5166
5d34a30f 5167 if (arg->rank == 0)
1318f16c 5168 {
95bf00d5 5169 if (arg->ts.type == BT_CLASS)
607ae689 5170 gfc_add_data_component (arg);
95bf00d5 5171
1318f16c 5172 gfc_conv_expr_reference (&argse, arg);
1318f16c 5173
389dd41b 5174 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5175 argse.expr));
1318f16c 5176
5177 /* Obtain the source word length. */
5178 if (arg->ts.type == BT_CHARACTER)
189ffda5 5179 se->expr = size_of_string_in_bytes (arg->ts.kind,
5180 argse.string_length);
1318f16c 5181 else
189ffda5 5182 se->expr = fold_convert (gfc_array_index_type, size_in_bytes (type));
1318f16c 5183 }
5184 else
5185 {
189ffda5 5186 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
1318f16c 5187 argse.want_pointer = 0;
5d34a30f 5188 gfc_conv_expr_descriptor (&argse, arg);
1318f16c 5189 type = gfc_get_element_type (TREE_TYPE (argse.expr));
5190
5191 /* Obtain the argument's word length. */
5192 if (arg->ts.type == BT_CHARACTER)
329f13ad 5193 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
1318f16c 5194 else
5195 tmp = fold_convert (gfc_array_index_type,
5196 size_in_bytes (type));
75a70cf9 5197 gfc_add_modify (&argse.pre, source_bytes, tmp);
1318f16c 5198
5199 /* Obtain the size of the array in bytes. */
5200 for (n = 0; n < arg->rank; n++)
5201 {
5202 tree idx;
5203 idx = gfc_rank_cst[n];
6b1a9af3 5204 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
5205 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
6f5c9335 5206 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5207 gfc_array_index_type, upper, lower);
5208 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5209 gfc_array_index_type, tmp, gfc_index_one_node);
5210 tmp = fold_build2_loc (input_location, MULT_EXPR,
5211 gfc_array_index_type, tmp, source_bytes);
75a70cf9 5212 gfc_add_modify (&argse.pre, source_bytes, tmp);
1318f16c 5213 }
189ffda5 5214 se->expr = source_bytes;
1318f16c 5215 }
5216
5217 gfc_add_block_to_block (&se->pre, &argse.pre);
1318f16c 5218}
5219
5220
95bf00d5 5221static void
5222gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
5223{
5224 gfc_expr *arg;
95bf00d5 5225 gfc_se argse,eight;
5226 tree type, result_type, tmp;
5227
5228 arg = expr->value.function.actual->expr;
5229 gfc_init_se (&eight, NULL);
5230 gfc_conv_expr (&eight, gfc_get_int_expr (expr->ts.kind, NULL, 8));
5231
5232 gfc_init_se (&argse, NULL);
95bf00d5 5233 result_type = gfc_get_int_type (expr->ts.kind);
5234
5d34a30f 5235 if (arg->rank == 0)
95bf00d5 5236 {
5237 if (arg->ts.type == BT_CLASS)
5238 {
607ae689 5239 gfc_add_vptr_component (arg);
5240 gfc_add_size_component (arg);
95bf00d5 5241 gfc_conv_expr (&argse, arg);
5242 tmp = fold_convert (result_type, argse.expr);
5243 goto done;
5244 }
5245
5246 gfc_conv_expr_reference (&argse, arg);
5247 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5248 argse.expr));
5249 }
5250 else
5251 {
5252 argse.want_pointer = 0;
5d34a30f 5253 gfc_conv_expr_descriptor (&argse, arg);
95bf00d5 5254 type = gfc_get_element_type (TREE_TYPE (argse.expr));
5255 }
5256
5257 /* Obtain the argument's word length. */
5258 if (arg->ts.type == BT_CHARACTER)
5259 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
5260 else
5261 tmp = fold_convert (result_type, size_in_bytes (type));
5262
5263done:
6f5c9335 5264 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
5265 eight.expr);
95bf00d5 5266 gfc_add_block_to_block (&se->pre, &argse.pre);
5267}
5268
5269
4ee9c684 5270/* Intrinsic string comparison functions. */
5271
1318f16c 5272static void
d62fb8de 5273gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
4ee9c684 5274{
5ddb0172 5275 tree args[4];
27781b86 5276
5ddb0172 5277 gfc_conv_intrinsic_function_args (se, expr, args, 4);
4ee9c684 5278
40b806de 5279 se->expr
5280 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
a313dc3a 5281 expr->value.function.actual->expr->ts.kind,
5282 op);
6f5c9335 5283 se->expr = fold_build2_loc (input_location, op,
5284 gfc_typenode_for_spec (&expr->ts), se->expr,
5285 build_int_cst (TREE_TYPE (se->expr), 0));
4ee9c684 5286}
5287
5288/* Generate a call to the adjustl/adjustr library function. */
5289static void
5290gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
5291{
5ddb0172 5292 tree args[3];
4ee9c684 5293 tree len;
5294 tree type;
5295 tree var;
5296 tree tmp;
5297
5ddb0172 5298 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
5299 len = args[1];
4ee9c684 5300
5ddb0172 5301 type = TREE_TYPE (args[2]);
4ee9c684 5302 var = gfc_conv_string_tmp (se, type, len);
5ddb0172 5303 args[0] = var;
4ee9c684 5304
389dd41b 5305 tmp = build_call_expr_loc (input_location,
5306 fndecl, 3, args[0], args[1], args[2]);
4ee9c684 5307 gfc_add_expr_to_block (&se->pre, tmp);
5308 se->expr = var;
5309 se->string_length = len;
5310}
5311
5312
891756c7 5313/* Generate code for the TRANSFER intrinsic:
5314 For scalar results:
5315 DEST = TRANSFER (SOURCE, MOLD)
5316 where:
5317 typeof<DEST> = typeof<MOLD>
5318 and:
5319 MOLD is scalar.
5320
5321 For array results:
5322 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
5323 where:
5324 typeof<DEST> = typeof<MOLD>
5325 and:
5326 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
4eaa93a5 5327 sizeof (DEST(0) * SIZE). */
4eaa93a5 5328static void
891756c7 5329gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
4eaa93a5 5330{
5331 tree tmp;
891756c7 5332 tree tmpdecl;
5333 tree ptr;
4eaa93a5 5334 tree extent;
5335 tree source;
8957d6ed 5336 tree source_type;
4eaa93a5 5337 tree source_bytes;
8957d6ed 5338 tree mold_type;
4eaa93a5 5339 tree dest_word_len;
5340 tree size_words;
5341 tree size_bytes;
5342 tree upper;
5343 tree lower;
4eaa93a5 5344 tree stmt;
5345 gfc_actual_arglist *arg;
5346 gfc_se argse;
ea686fef 5347 gfc_array_info *info;
4eaa93a5 5348 stmtblock_t block;
5349 int n;
891756c7 5350 bool scalar_mold;
50a0a4ff 5351 gfc_expr *source_expr, *mold_expr;
4eaa93a5 5352
891756c7 5353 info = NULL;
5354 if (se->loop)
b8f38347 5355 info = &se->ss->info->data.array;
4eaa93a5 5356
5357 /* Convert SOURCE. The output from this stage is:-
5358 source_bytes = length of the source in bytes
5359 source = pointer to the source data. */
5360 arg = expr->value.function.actual;
50a0a4ff 5361 source_expr = arg->expr;
891756c7 5362
5363 /* Ensure double transfer through LOGICAL preserves all
5364 the needed bits. */
5365 if (arg->expr->expr_type == EXPR_FUNCTION
5366 && arg->expr->value.function.esym == NULL
5367 && arg->expr->value.function.isym != NULL
5368 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
5369 && arg->expr->ts.type == BT_LOGICAL
5370 && expr->ts.type != arg->expr->ts.type)
5371 arg->expr->value.function.name = "__transfer_in_transfer";
5372
4eaa93a5 5373 gfc_init_se (&argse, NULL);
4eaa93a5 5374
5375 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
5376
5377 /* Obtain the pointer to source and the length of source in bytes. */
5d34a30f 5378 if (arg->expr->rank == 0)
4eaa93a5 5379 {
5380 gfc_conv_expr_reference (&argse, arg->expr);
50a0a4ff 5381 if (arg->expr->ts.type == BT_CLASS)
5382 source = gfc_class_data_get (argse.expr);
5383 else
5384 source = argse.expr;
8957d6ed 5385
4eaa93a5 5386 /* Obtain the source word length. */
50a0a4ff 5387 switch (arg->expr->ts.type)
5388 {
5389 case BT_CHARACTER:
5390 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
5391 argse.string_length);
5392 break;
5393 case BT_CLASS:
5394 tmp = gfc_vtable_size_get (argse.expr);
5395 break;
5396 default:
5397 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
5398 source));
5399 tmp = fold_convert (gfc_array_index_type,
5400 size_in_bytes (source_type));
5401 break;
5402 }
4eaa93a5 5403 }
5404 else
5405 {
4eaa93a5 5406 argse.want_pointer = 0;
5d34a30f 5407 gfc_conv_expr_descriptor (&argse, arg->expr);
4eaa93a5 5408 source = gfc_conv_descriptor_data_get (argse.expr);
8957d6ed 5409 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
4eaa93a5 5410
5411 /* Repack the source if not a full variable array. */
891756c7 5412 if (arg->expr->expr_type == EXPR_VARIABLE
5413 && arg->expr->ref->u.ar.type != AR_FULL)
4eaa93a5 5414 {
86f2ad37 5415 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
92f4d1c4 5416
5417 if (gfc_option.warn_array_temp)
5418 gfc_warning ("Creating array temporary at %L", &expr->where);
5419
389dd41b 5420 source = build_call_expr_loc (input_location,
5421 gfor_fndecl_in_pack, 1, tmp);
4eaa93a5 5422 source = gfc_evaluate_now (source, &argse.pre);
5423
5424 /* Free the temporary. */
5425 gfc_start_block (&block);
9915365e 5426 tmp = gfc_call_free (convert (pvoid_type_node, source));
4eaa93a5 5427 gfc_add_expr_to_block (&block, tmp);
5428 stmt = gfc_finish_block (&block);
5429
5430 /* Clean up if it was repacked. */
5431 gfc_init_block (&block);
5432 tmp = gfc_conv_array_data (argse.expr);
6f5c9335 5433 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5434 source, tmp);
e60a6f7b 5435 tmp = build3_v (COND_EXPR, tmp, stmt,
5436 build_empty_stmt (input_location));
4eaa93a5 5437 gfc_add_expr_to_block (&block, tmp);
5438 gfc_add_block_to_block (&block, &se->post);
5439 gfc_init_block (&se->post);
5440 gfc_add_block_to_block (&se->post, &block);
5441 }
5442
5443 /* Obtain the source word length. */
8957d6ed 5444 if (arg->expr->ts.type == BT_CHARACTER)
329f13ad 5445 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
5446 argse.string_length);
8957d6ed 5447 else
5448 tmp = fold_convert (gfc_array_index_type,
5449 size_in_bytes (source_type));
4eaa93a5 5450
5451 /* Obtain the size of the array in bytes. */
5452 extent = gfc_create_var (gfc_array_index_type, NULL);
5453 for (n = 0; n < arg->expr->rank; n++)
5454 {
5455 tree idx;
5456 idx = gfc_rank_cst[n];
75a70cf9 5457 gfc_add_modify (&argse.pre, source_bytes, tmp);
6b1a9af3 5458 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
5459 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
6f5c9335 5460 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5461 gfc_array_index_type, upper, lower);
75a70cf9 5462 gfc_add_modify (&argse.pre, extent, tmp);
6f5c9335 5463 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5464 gfc_array_index_type, extent,
5465 gfc_index_one_node);
5466 tmp = fold_build2_loc (input_location, MULT_EXPR,
5467 gfc_array_index_type, tmp, source_bytes);
4eaa93a5 5468 }
5469 }
5470
75a70cf9 5471 gfc_add_modify (&argse.pre, source_bytes, tmp);
4eaa93a5 5472 gfc_add_block_to_block (&se->pre, &argse.pre);
5473 gfc_add_block_to_block (&se->post, &argse.post);
5474
8957d6ed 5475 /* Now convert MOLD. The outputs are:
5476 mold_type = the TREE type of MOLD
4eaa93a5 5477 dest_word_len = destination word length in bytes. */
5478 arg = arg->next;
50a0a4ff 5479 mold_expr = arg->expr;
4eaa93a5 5480
5481 gfc_init_se (&argse, NULL);
4eaa93a5 5482
891756c7 5483 scalar_mold = arg->expr->rank == 0;
5484
5d34a30f 5485 if (arg->expr->rank == 0)
4eaa93a5 5486 {
5487 gfc_conv_expr_reference (&argse, arg->expr);
389dd41b 5488 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
50a0a4ff 5489 argse.expr));
4eaa93a5 5490 }
5491 else
5492 {
5493 gfc_init_se (&argse, NULL);
5494 argse.want_pointer = 0;
5d34a30f 5495 gfc_conv_expr_descriptor (&argse, arg->expr);
8957d6ed 5496 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
4eaa93a5 5497 }
5498
891756c7 5499 gfc_add_block_to_block (&se->pre, &argse.pre);
5500 gfc_add_block_to_block (&se->post, &argse.post);
5501
95b7221a 5502 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
5503 {
5504 /* If this TRANSFER is nested in another TRANSFER, use a type
5505 that preserves all bits. */
5506 if (arg->expr->ts.type == BT_LOGICAL)
5507 mold_type = gfc_get_int_type (arg->expr->ts.kind);
5508 }
5509
50a0a4ff 5510 /* Obtain the destination word length. */
5511 switch (arg->expr->ts.type)
8957d6ed 5512 {
50a0a4ff 5513 case BT_CHARACTER:
329f13ad 5514 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
8957d6ed 5515 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
50a0a4ff 5516 break;
5517 case BT_CLASS:
5518 tmp = gfc_vtable_size_get (argse.expr);
5519 break;
5520 default:
5521 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
5522 break;
8957d6ed 5523 }
4eaa93a5 5524 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
75a70cf9 5525 gfc_add_modify (&se->pre, dest_word_len, tmp);
4eaa93a5 5526
5527 /* Finally convert SIZE, if it is present. */
5528 arg = arg->next;
5529 size_words = gfc_create_var (gfc_array_index_type, NULL);
5530
5531 if (arg->expr)
5532 {
5533 gfc_init_se (&argse, NULL);
5534 gfc_conv_expr_reference (&argse, arg->expr);
5535 tmp = convert (gfc_array_index_type,
389dd41b 5536 build_fold_indirect_ref_loc (input_location,
5537 argse.expr));
4eaa93a5 5538 gfc_add_block_to_block (&se->pre, &argse.pre);
5539 gfc_add_block_to_block (&se->post, &argse.post);
5540 }
5541 else
5542 tmp = NULL_TREE;
5543
891756c7 5544 /* Separate array and scalar results. */
5545 if (scalar_mold && tmp == NULL_TREE)
5546 goto scalar_transfer;
5547
4eaa93a5 5548 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
5549 if (tmp != NULL_TREE)
6f5c9335 5550 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5551 tmp, dest_word_len);
4eaa93a5 5552 else
5553 tmp = source_bytes;
5554
75a70cf9 5555 gfc_add_modify (&se->pre, size_bytes, tmp);
5556 gfc_add_modify (&se->pre, size_words,
6f5c9335 5557 fold_build2_loc (input_location, CEIL_DIV_EXPR,
5558 gfc_array_index_type,
5559 size_bytes, dest_word_len));
4eaa93a5 5560
5561 /* Evaluate the bounds of the result. If the loop range exists, we have
5562 to check if it is too large. If so, we modify loop->to be consistent
5563 with min(size, size(source)). Otherwise, size is made consistent with
5564 the loop range, so that the right number of bytes is transferred.*/
5565 n = se->loop->order[0];
5566 if (se->loop->to[n] != NULL_TREE)
5567 {
6f5c9335 5568 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5569 se->loop->to[n], se->loop->from[n]);
5570 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5571 tmp, gfc_index_one_node);
5572 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
1318f16c 5573 tmp, size_words);
75a70cf9 5574 gfc_add_modify (&se->pre, size_words, tmp);
5575 gfc_add_modify (&se->pre, size_bytes,
6f5c9335 5576 fold_build2_loc (input_location, MULT_EXPR,
5577 gfc_array_index_type,
5578 size_words, dest_word_len));
5579 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5580 size_words, se->loop->from[n]);
5581 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5582 upper, gfc_index_one_node);
4eaa93a5 5583 }
5584 else
5585 {
6f5c9335 5586 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5587 size_words, gfc_index_one_node);
4eaa93a5 5588 se->loop->from[n] = gfc_index_zero_node;
5589 }
5590
5591 se->loop->to[n] = upper;
5592
5593 /* Build a destination descriptor, using the pointer, source, as the
891756c7 5594 data field. */
fc09773a 5595 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
5596 NULL_TREE, false, true, false, &expr->where);
8957d6ed 5597
5598 /* Cast the pointer to the result. */
5599 tmp = gfc_conv_descriptor_data_get (info->descriptor);
5600 tmp = fold_convert (pvoid_type_node, tmp);
4eaa93a5 5601
7544787a 5602 /* Use memcpy to do the transfer. */
e740e6a6 5603 tmp
5604 = build_call_expr_loc (input_location,
5605 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
5606 fold_convert (pvoid_type_node, source),
5607 fold_convert (size_type_node,
5608 fold_build2_loc (input_location,
5609 MIN_EXPR,
5610 gfc_array_index_type,
5611 size_bytes,
5612 source_bytes)));
7544787a 5613 gfc_add_expr_to_block (&se->pre, tmp);
5614
4eaa93a5 5615 se->expr = info->descriptor;
5616 if (expr->ts.type == BT_CHARACTER)
1557756e 5617 se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
4eaa93a5 5618
891756c7 5619 return;
4eaa93a5 5620
891756c7 5621/* Deal with scalar results. */
5622scalar_transfer:
6f5c9335 5623 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
5624 dest_word_len, source_bytes);
5625 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
5626 extent, gfc_index_zero_node);
4ee9c684 5627
891756c7 5628 if (expr->ts.type == BT_CHARACTER)
5629 {
5630 tree direct;
5631 tree indirect;
4ee9c684 5632
891756c7 5633 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
5634 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
5635 "transfer");
4ee9c684 5636
891756c7 5637 /* If source is longer than the destination, use a pointer to
5638 the source directly. */
5639 gfc_init_block (&block);
5640 gfc_add_modify (&block, tmpdecl, ptr);
5641 direct = gfc_finish_block (&block);
3b51aab9 5642
891756c7 5643 /* Otherwise, allocate a string with the length of the destination
5644 and copy the source into it. */
5645 gfc_init_block (&block);
5646 tmp = gfc_get_pchar_type (expr->ts.kind);
5647 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
5648 gfc_add_modify (&block, tmpdecl,
5649 fold_convert (TREE_TYPE (ptr), tmp));
389dd41b 5650 tmp = build_call_expr_loc (input_location,
b9a16870 5651 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
891756c7 5652 fold_convert (pvoid_type_node, tmpdecl),
5653 fold_convert (pvoid_type_node, ptr),
e740e6a6 5654 fold_convert (size_type_node, extent));
891756c7 5655 gfc_add_expr_to_block (&block, tmp);
5656 indirect = gfc_finish_block (&block);
5657
5658 /* Wrap it up with the condition. */
6f5c9335 5659 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
5660 dest_word_len, source_bytes);
891756c7 5661 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
5662 gfc_add_expr_to_block (&se->pre, tmp);
5663
5664 se->expr = tmpdecl;
5665 se->string_length = dest_word_len;
4ee9c684 5666 }
5667 else
5668 {
891756c7 5669 tmpdecl = gfc_create_var (mold_type, "transfer");
5670
5671 ptr = convert (build_pointer_type (mold_type), source);
3b51aab9 5672
50a0a4ff 5673 /* For CLASS results, allocate the needed memory first. */
5674 if (mold_expr->ts.type == BT_CLASS)
5675 {
5676 tree cdata;
5677 cdata = gfc_class_data_get (tmpdecl);
5678 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
5679 gfc_add_modify (&se->pre, cdata, tmp);
5680 }
5681
3b51aab9 5682 /* Use memcpy to do the transfer. */
50a0a4ff 5683 if (mold_expr->ts.type == BT_CLASS)
5684 tmp = gfc_class_data_get (tmpdecl);
5685 else
5686 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
5687
389dd41b 5688 tmp = build_call_expr_loc (input_location,
b9a16870 5689 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
c2f47e15 5690 fold_convert (pvoid_type_node, tmp),
5691 fold_convert (pvoid_type_node, ptr),
e740e6a6 5692 fold_convert (size_type_node, extent));
3b51aab9 5693 gfc_add_expr_to_block (&se->pre, tmp);
5694
50a0a4ff 5695 /* For CLASS results, set the _vptr. */
5696 if (mold_expr->ts.type == BT_CLASS)
5697 {
5698 tree vptr;
5699 gfc_symbol *vtab;
5700 vptr = gfc_class_vptr_get (tmpdecl);
5701 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
5702 gcc_assert (vtab);
5703 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
5704 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
5705 }
5706
3b51aab9 5707 se->expr = tmpdecl;
4ee9c684 5708 }
5709}
5710
5711
5712/* Generate code for the ALLOCATED intrinsic.
5713 Generate inline code that directly check the address of the argument. */
5714
5715static void
5716gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
5717{
5718 gfc_actual_arglist *arg1;
5719 gfc_se arg1se;
4ee9c684 5720 tree tmp;
5721
5722 gfc_init_se (&arg1se, NULL);
5723 arg1 = expr->value.function.actual;
fd23cc08 5724
5725 if (arg1->expr->ts.type == BT_CLASS)
5726 {
5727 /* Make sure that class array expressions have both a _data
5728 component reference and an array reference.... */
5729 if (CLASS_DATA (arg1->expr)->attr.dimension)
5730 gfc_add_class_array_ref (arg1->expr);
5731 /* .... whilst scalars only need the _data component. */
5732 else
5733 gfc_add_data_component (arg1->expr);
5734 }
5735
5d34a30f 5736 if (arg1->expr->rank == 0)
eb67c215 5737 {
5738 /* Allocatable scalar. */
5739 arg1se.want_pointer = 1;
5740 gfc_conv_expr (&arg1se, arg1->expr);
5741 tmp = arg1se.expr;
5742 }
5743 else
5744 {
5745 /* Allocatable array. */
5746 arg1se.descriptor_only = 1;
5d34a30f 5747 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
eb67c215 5748 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
5749 }
5750
6f5c9335 5751 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
5752 fold_convert (TREE_TYPE (tmp), null_pointer_node));
4ee9c684 5753 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
5754}
5755
5756
5757/* Generate code for the ASSOCIATED intrinsic.
5758 If both POINTER and TARGET are arrays, generate a call to library function
5759 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
5760 In other cases, generate inline code that directly compare the address of
5761 POINTER with the address of TARGET. */
5762
5763static void
5764gfc_conv_associated (gfc_se *se, gfc_expr *expr)
5765{
5766 gfc_actual_arglist *arg1;
5767 gfc_actual_arglist *arg2;
5768 gfc_se arg1se;
5769 gfc_se arg2se;
5770 tree tmp2;
5771 tree tmp;
d9963cc2 5772 tree nonzero_charlen;
5773 tree nonzero_arraylen;
5d34a30f 5774 gfc_ss *ss;
5775 bool scalar;
4ee9c684 5776
5777 gfc_init_se (&arg1se, NULL);
5778 gfc_init_se (&arg2se, NULL);
5779 arg1 = expr->value.function.actual;
8337b324 5780 if (arg1->expr->ts.type == BT_CLASS)
607ae689 5781 gfc_add_data_component (arg1->expr);
4ee9c684 5782 arg2 = arg1->next;
5d34a30f 5783
5784 /* Check whether the expression is a scalar or not; we cannot use
5785 arg1->expr->rank as it can be nonzero for proc pointers. */
5786 ss = gfc_walk_expr (arg1->expr);
5787 scalar = ss == gfc_ss_terminator;
5788 if (!scalar)
5789 gfc_free_ss_chain (ss);
4ee9c684 5790
5791 if (!arg2->expr)
5792 {
5793 /* No optional target. */
5d34a30f 5794 if (scalar)
4ee9c684 5795 {
4b17ee64 5796 /* A pointer to a scalar. */
5797 arg1se.want_pointer = 1;
5798 gfc_conv_expr (&arg1se, arg1->expr);
5799 if (arg1->expr->symtree->n.sym->attr.proc_pointer
5800 && arg1->expr->symtree->n.sym->attr.dummy)
5801 arg1se.expr = build_fold_indirect_ref_loc (input_location,
5802 arg1se.expr);
5803 tmp2 = arg1se.expr;
4ee9c684 5804 }
5805 else
5806 {
5807 /* A pointer to an array. */
5d34a30f 5808 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
94be45c9 5809 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
4ee9c684 5810 }
98ac6651 5811 gfc_add_block_to_block (&se->pre, &arg1se.pre);
5812 gfc_add_block_to_block (&se->post, &arg1se.post);
6f5c9335 5813 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp2,
5814 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
4ee9c684 5815 se->expr = tmp;
5816 }
5817 else
5818 {
5819 /* An optional target. */
db6e5c08 5820 if (arg2->expr->ts.type == BT_CLASS)
607ae689 5821 gfc_add_data_component (arg2->expr);
e815d37d 5822
5823 nonzero_charlen = NULL_TREE;
5824 if (arg1->expr->ts.type == BT_CHARACTER)
6f5c9335 5825 nonzero_charlen = fold_build2_loc (input_location, NE_EXPR,
5826 boolean_type_node,
5827 arg1->expr->ts.u.cl->backend_decl,
5828 integer_zero_node);
5d34a30f 5829 if (scalar)
4ee9c684 5830 {
4b17ee64 5831 /* A pointer to a scalar. */
4b17ee64 5832 arg1se.want_pointer = 1;
5833 gfc_conv_expr (&arg1se, arg1->expr);
5834 if (arg1->expr->symtree->n.sym->attr.proc_pointer
5835 && arg1->expr->symtree->n.sym->attr.dummy)
5836 arg1se.expr = build_fold_indirect_ref_loc (input_location,
5837 arg1se.expr);
5838
5839 arg2se.want_pointer = 1;
5840 gfc_conv_expr (&arg2se, arg2->expr);
5841 if (arg2->expr->symtree->n.sym->attr.proc_pointer
5842 && arg2->expr->symtree->n.sym->attr.dummy)
5843 arg2se.expr = build_fold_indirect_ref_loc (input_location,
5844 arg2se.expr);
98ac6651 5845 gfc_add_block_to_block (&se->pre, &arg1se.pre);
5846 gfc_add_block_to_block (&se->post, &arg1se.post);
6f5c9335 5847 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5848 arg1se.expr, arg2se.expr);
5849 tmp2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5850 arg1se.expr, null_pointer_node);
5851 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5852 boolean_type_node, tmp, tmp2);
4ee9c684 5853 }
5854 else
5855 {
e815d37d 5856 /* An array pointer of zero length is not associated if target is
5857 present. */
5858 arg1se.descriptor_only = 1;
5859 gfc_conv_expr_lhs (&arg1se, arg1->expr);
f00f6dd6 5860 if (arg1->expr->rank == -1)
5861 {
edc4866f 5862 tmp = gfc_conv_descriptor_rank (arg1se.expr);
f00f6dd6 5863 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5864 TREE_TYPE (tmp), tmp, gfc_index_one_node);
5865 }
5866 else
5867 tmp = gfc_rank_cst[arg1->expr->rank - 1];
5868 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
6f5c9335 5869 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
5870 boolean_type_node, tmp,
5871 build_int_cst (TREE_TYPE (tmp), 0));
e815d37d 5872
4ee9c684 5873 /* A pointer to an array, call library function _gfor_associated. */
4ee9c684 5874 arg1se.want_pointer = 1;
5d34a30f 5875 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
e815d37d 5876
4ee9c684 5877 arg2se.want_pointer = 1;
5d34a30f 5878 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
4ee9c684 5879 gfc_add_block_to_block (&se->pre, &arg2se.pre);
5880 gfc_add_block_to_block (&se->post, &arg2se.post);
389dd41b 5881 se->expr = build_call_expr_loc (input_location,
5882 gfor_fndecl_associated, 2,
c1c66d1d 5883 arg1se.expr, arg2se.expr);
5884 se->expr = convert (boolean_type_node, se->expr);
6f5c9335 5885 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5886 boolean_type_node, se->expr,
5887 nonzero_arraylen);
4ee9c684 5888 }
e815d37d 5889
5890 /* If target is present zero character length pointers cannot
5891 be associated. */
5892 if (nonzero_charlen != NULL_TREE)
6f5c9335 5893 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5894 boolean_type_node,
5895 se->expr, nonzero_charlen);
e815d37d 5896 }
5897
4ee9c684 5898 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
5899}
5900
5901
1de1b1a9 5902/* Generate code for the SAME_TYPE_AS intrinsic.
5903 Generate inline code that directly checks the vindices. */
5904
5905static void
5906gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
5907{
5908 gfc_expr *a, *b;
5909 gfc_se se1, se2;
5910 tree tmp;
5911
5912 gfc_init_se (&se1, NULL);
5913 gfc_init_se (&se2, NULL);
5914
5915 a = expr->value.function.actual->expr;
5916 b = expr->value.function.actual->next->expr;
5917
5918 if (a->ts.type == BT_CLASS)
bdfbc762 5919 {
607ae689 5920 gfc_add_vptr_component (a);
5921 gfc_add_hash_component (a);
bdfbc762 5922 }
1de1b1a9 5923 else if (a->ts.type == BT_DERIVED)
126387b5 5924 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
5925 a->ts.u.derived->hash_value);
1de1b1a9 5926
5927 if (b->ts.type == BT_CLASS)
bdfbc762 5928 {
607ae689 5929 gfc_add_vptr_component (b);
5930 gfc_add_hash_component (b);
bdfbc762 5931 }
1de1b1a9 5932 else if (b->ts.type == BT_DERIVED)
126387b5 5933 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
5934 b->ts.u.derived->hash_value);
1de1b1a9 5935
5936 gfc_conv_expr (&se1, a);
5937 gfc_conv_expr (&se2, b);
5938
6f5c9335 5939 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5940 se1.expr, fold_convert (TREE_TYPE (se1.expr), se2.expr));
1de1b1a9 5941 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
5942}
5943
5944
59e2a584 5945/* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
5946
5947static void
5948gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
5949{
5950 tree args[2];
5951
5952 gfc_conv_intrinsic_function_args (se, expr, args, 2);
389dd41b 5953 se->expr = build_call_expr_loc (input_location,
5954 gfor_fndecl_sc_kind, 2, args[0], args[1]);
59e2a584 5955 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
5956}
5957
5958
4ee9c684 5959/* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
5960
5961static void
e2d2dbf9 5962gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
4ee9c684 5963{
e2d2dbf9 5964 tree arg, type;
4ee9c684 5965
5ddb0172 5966 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
e2d2dbf9 5967
5968 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
5969 type = gfc_get_int_type (4);
86f2ad37 5970 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
e2d2dbf9 5971
5972 /* Convert it to the required type. */
5973 type = gfc_typenode_for_spec (&expr->ts);
389dd41b 5974 se->expr = build_call_expr_loc (input_location,
5975 gfor_fndecl_si_kind, 1, arg);
e2d2dbf9 5976 se->expr = fold_convert (type, se->expr);
4ee9c684 5977}
5978
e2d2dbf9 5979
5ce6c67e 5980/* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
4ee9c684 5981
5982static void
e2d2dbf9 5983gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
4ee9c684 5984{
5985 gfc_actual_arglist *actual;
414c3a2c 5986 tree type;
4ee9c684 5987 gfc_se argse;
f1f41a6c 5988 vec<tree, va_gc> *args = NULL;
4ee9c684 5989
4ee9c684 5990 for (actual = expr->value.function.actual; actual; actual = actual->next)
5991 {
5992 gfc_init_se (&argse, se);
5993
5994 /* Pass a NULL pointer for an absent arg. */
5995 if (actual->expr == NULL)
5996 argse.expr = null_pointer_node;
5997 else
e2d2dbf9 5998 {
5999 gfc_typespec ts;
52179f31 6000 gfc_clear_ts (&ts);
6001
e2d2dbf9 6002 if (actual->expr->ts.kind != gfc_c_int_kind)
6003 {
6004 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
6005 ts.type = BT_INTEGER;
6006 ts.kind = gfc_c_int_kind;
6007 gfc_convert_type (actual->expr, &ts, 2);
6008 }
6009 gfc_conv_expr_reference (&argse, actual->expr);
6010 }
4ee9c684 6011
6012 gfc_add_block_to_block (&se->pre, &argse.pre);
6013 gfc_add_block_to_block (&se->post, &argse.post);
f1f41a6c 6014 vec_safe_push (args, argse.expr);
4ee9c684 6015 }
e2d2dbf9 6016
6017 /* Convert it to the required type. */
6018 type = gfc_typenode_for_spec (&expr->ts);
414c3a2c 6019 se->expr = build_call_expr_loc_vec (input_location,
6020 gfor_fndecl_sr_kind, args);
e2d2dbf9 6021 se->expr = fold_convert (type, se->expr);
4ee9c684 6022}
6023
6024
6025/* Generate code for TRIM (A) intrinsic function. */
6026
6027static void
6028gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
6029{
6030 tree var;
6031 tree len;
6032 tree addr;
6033 tree tmp;
4ee9c684 6034 tree cond;
5ddb0172 6035 tree fndecl;
40b806de 6036 tree function;
5ddb0172 6037 tree *args;
6038 unsigned int num_args;
4ee9c684 6039
5ddb0172 6040 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
86b32f71 6041 args = XALLOCAVEC (tree, num_args);
4ee9c684 6042
329f13ad 6043 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
4ee9c684 6044 addr = gfc_build_addr_expr (ppvoid_type_node, var);
185bc3c7 6045 len = gfc_create_var (gfc_charlen_type_node, "len");
4ee9c684 6046
5ddb0172 6047 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
86f2ad37 6048 args[0] = gfc_build_addr_expr (NULL_TREE, len);
5ddb0172 6049 args[1] = addr;
6bcf802b 6050
40b806de 6051 if (expr->ts.kind == 1)
6052 function = gfor_fndecl_string_trim;
6053 else if (expr->ts.kind == 4)
6054 function = gfor_fndecl_string_trim_char4;
6055 else
6056 gcc_unreachable ();
6057
6058 fndecl = build_addr (function, current_function_decl);
389dd41b 6059 tmp = build_call_array_loc (input_location,
6060 TREE_TYPE (TREE_TYPE (function)), fndecl,
40b806de 6061 num_args, args);
4ee9c684 6062 gfc_add_expr_to_block (&se->pre, tmp);
6063
6064 /* Free the temporary afterwards, if necessary. */
6f5c9335 6065 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6066 len, build_int_cst (TREE_TYPE (len), 0));
9915365e 6067 tmp = gfc_call_free (var);
e60a6f7b 6068 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4ee9c684 6069 gfc_add_expr_to_block (&se->post, tmp);
6070
6071 se->expr = var;
6072 se->string_length = len;
6073}
6074
6075
6076/* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
6077
6078static void
6079gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
6080{
5ddb0172 6081 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
f62816ef 6082 tree type, cond, tmp, count, exit_label, n, max, largest;
b44437b9 6083 tree size;
f62816ef 6084 stmtblock_t block, body;
6085 int i;
4ee9c684 6086
329f13ad 6087 /* We store in charsize the size of a character. */
b44437b9 6088 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
6089 size = build_int_cst (size_type_node, gfc_character_kinds[i].bit_size / 8);
6090
f62816ef 6091 /* Get the arguments. */
5ddb0172 6092 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6093 slen = fold_convert (size_type_node, gfc_evaluate_now (args[0], &se->pre));
6094 src = args[1];
6095 ncopies = gfc_evaluate_now (args[2], &se->pre);
f62816ef 6096 ncopies_type = TREE_TYPE (ncopies);
6097
6098 /* Check that NCOPIES is not negative. */
6f5c9335 6099 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, ncopies,
6100 build_int_cst (ncopies_type, 0));
da6ffc6d 6101 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
399aecc1 6102 "Argument NCOPIES of REPEAT intrinsic is negative "
517c89e5 6103 "(its value is %ld)",
399aecc1 6104 fold_convert (long_integer_type_node, ncopies));
bfe7d4b1 6105
f62816ef 6106 /* If the source length is zero, any non negative value of NCOPIES
6107 is valid, and nothing happens. */
6108 n = gfc_create_var (ncopies_type, "ncopies");
6f5c9335 6109 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
6110 build_int_cst (size_type_node, 0));
6111 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
6112 build_int_cst (ncopies_type, 0), ncopies);
75a70cf9 6113 gfc_add_modify (&se->pre, n, tmp);
f62816ef 6114 ncopies = n;
6115
6116 /* Check that ncopies is not too large: ncopies should be less than
6117 (or equal to) MAX / slen, where MAX is the maximal integer of
6118 the gfc_charlen_type_node type. If slen == 0, we need a special
6119 case to avoid the division by zero. */
6120 i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
6121 max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_charlen_int_kind);
6f5c9335 6122 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node,
6123 fold_convert (size_type_node, max), slen);
f62816ef 6124 largest = TYPE_PRECISION (size_type_node) > TYPE_PRECISION (ncopies_type)
6125 ? size_type_node : ncopies_type;
6f5c9335 6126 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
6127 fold_convert (largest, ncopies),
6128 fold_convert (largest, max));
6129 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, slen,
6130 build_int_cst (size_type_node, 0));
6131 cond = fold_build3_loc (input_location, COND_EXPR, boolean_type_node, tmp,
6132 boolean_false_node, cond);
da6ffc6d 6133 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
399aecc1 6134 "Argument NCOPIES of REPEAT intrinsic is too large");
f62816ef 6135
bfe7d4b1 6136 /* Compute the destination length. */
6f5c9335 6137 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6138 fold_convert (gfc_charlen_type_node, slen),
6139 fold_convert (gfc_charlen_type_node, ncopies));
eeebe20b 6140 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
f62816ef 6141 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
6142
6143 /* Generate the code to do the repeat operation:
6144 for (i = 0; i < ncopies; i++)
b44437b9 6145 memmove (dest + (i * slen * size), src, slen*size); */
f62816ef 6146 gfc_start_block (&block);
6147 count = gfc_create_var (ncopies_type, "count");
75a70cf9 6148 gfc_add_modify (&block, count, build_int_cst (ncopies_type, 0));
f62816ef 6149 exit_label = gfc_build_label_decl (NULL_TREE);
6150
6151 /* Start the loop body. */
6152 gfc_start_block (&body);
4ee9c684 6153
f62816ef 6154 /* Exit the loop if count >= ncopies. */
6f5c9335 6155 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, count,
6156 ncopies);
f62816ef 6157 tmp = build1_v (GOTO_EXPR, exit_label);
6158 TREE_USED (exit_label) = 1;
6f5c9335 6159 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
6160 build_empty_stmt (input_location));
f62816ef 6161 gfc_add_expr_to_block (&body, tmp);
6162
b44437b9 6163 /* Call memmove (dest + (i*slen*size), src, slen*size). */
6f5c9335 6164 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6165 fold_convert (gfc_charlen_type_node, slen),
6166 fold_convert (gfc_charlen_type_node, count));
6167 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
6168 tmp, fold_convert (gfc_charlen_type_node, size));
2cc66f2a 6169 tmp = fold_build_pointer_plus_loc (input_location,
6170 fold_convert (pvoid_type_node, dest), tmp);
389dd41b 6171 tmp = build_call_expr_loc (input_location,
b9a16870 6172 builtin_decl_explicit (BUILT_IN_MEMMOVE),
6173 3, tmp, src,
6f5c9335 6174 fold_build2_loc (input_location, MULT_EXPR,
6175 size_type_node, slen,
6176 fold_convert (size_type_node,
6177 size)));
f62816ef 6178 gfc_add_expr_to_block (&body, tmp);
6179
6180 /* Increment count. */
6f5c9335 6181 tmp = fold_build2_loc (input_location, PLUS_EXPR, ncopies_type,
6182 count, build_int_cst (TREE_TYPE (count), 1));
75a70cf9 6183 gfc_add_modify (&body, count, tmp);
f62816ef 6184
6185 /* Build the loop. */
6186 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
6187 gfc_add_expr_to_block (&block, tmp);
6188
6189 /* Add the exit label. */
6190 tmp = build1_v (LABEL_EXPR, exit_label);
6191 gfc_add_expr_to_block (&block, tmp);
6192
6193 /* Finish the block. */
6194 tmp = gfc_finish_block (&block);
4ee9c684 6195 gfc_add_expr_to_block (&se->pre, tmp);
6196
f62816ef 6197 /* Set the result value. */
6198 se->expr = dest;
6199 se->string_length = dlen;
4ee9c684 6200}
6201
6202
f0f2da44 6203/* Generate code for the IARGC intrinsic. */
9b057c29 6204
6205static void
f0f2da44 6206gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
9b057c29 6207{
6208 tree tmp;
6209 tree fndecl;
6210 tree type;
6211
6212 /* Call the library function. This always returns an INTEGER(4). */
6213 fndecl = gfor_fndecl_iargc;
389dd41b 6214 tmp = build_call_expr_loc (input_location,
6215 fndecl, 0);
9b057c29 6216
6217 /* Convert it to the required type. */
6218 type = gfc_typenode_for_spec (&expr->ts);
6219 tmp = fold_convert (type, tmp);
6220
9b057c29 6221 se->expr = tmp;
6222}
6223
b549d2a5 6224
6225/* The loc intrinsic returns the address of its argument as
6226 gfc_index_integer_kind integer. */
6227
6228static void
fe537a55 6229gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
b549d2a5 6230{
6231 tree temp_var;
6232 gfc_expr *arg_expr;
b549d2a5 6233
6234 gcc_assert (!se->ss);
6235
6236 arg_expr = expr->value.function.actual->expr;
5d34a30f 6237 if (arg_expr->rank == 0)
b549d2a5 6238 gfc_conv_expr_reference (se, arg_expr);
6239 else
5d34a30f 6240 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
fe537a55 6241 se->expr= convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
b549d2a5 6242
6243 /* Create a temporary variable for loc return value. Without this,
6244 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
fe537a55 6245 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
75a70cf9 6246 gfc_add_modify (&se->pre, temp_var, se->expr);
b549d2a5 6247 se->expr = temp_var;
6248}
6249
4ee9c684 6250/* Generate code for an intrinsic function. Some map directly to library
6251 calls, others get special handling. In some cases the name of the function
6252 used depends on the type specifiers. */
6253
6254void
6255gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
6256{
c231e334 6257 const char *name;
40b806de 6258 int lib, kind;
6259 tree fndecl;
4ee9c684 6260
4ee9c684 6261 name = &expr->value.function.name[2];
6262
1274527b 6263 if (expr->rank > 0)
4ee9c684 6264 {
6265 lib = gfc_is_intrinsic_libcall (expr);
6266 if (lib != 0)
6267 {
6268 if (lib == 1)
6269 se->ignore_optional = 1;
8572fdb4 6270
6271 switch (expr->value.function.isym->id)
6272 {
6273 case GFC_ISYM_EOSHIFT:
6274 case GFC_ISYM_PACK:
6275 case GFC_ISYM_RESHAPE:
6276 /* For all of those the first argument specifies the type and the
6277 third is optional. */
6278 conv_generic_with_optional_char_arg (se, expr, 1, 3);
6279 break;
6280
6281 default:
6282 gfc_conv_intrinsic_funcall (se, expr);
6283 break;
6284 }
6285
4ee9c684 6286 return;
6287 }
6288 }
6289
55cb4417 6290 switch (expr->value.function.isym->id)
4ee9c684 6291 {
6292 case GFC_ISYM_NONE:
22d678e8 6293 gcc_unreachable ();
4ee9c684 6294
6295 case GFC_ISYM_REPEAT:
6296 gfc_conv_intrinsic_repeat (se, expr);
6297 break;
6298
6299 case GFC_ISYM_TRIM:
6300 gfc_conv_intrinsic_trim (se, expr);
6301 break;
6302
59e2a584 6303 case GFC_ISYM_SC_KIND:
6304 gfc_conv_intrinsic_sc_kind (se, expr);
6305 break;
6306
4ee9c684 6307 case GFC_ISYM_SI_KIND:
6308 gfc_conv_intrinsic_si_kind (se, expr);
6309 break;
6310
6311 case GFC_ISYM_SR_KIND:
6312 gfc_conv_intrinsic_sr_kind (se, expr);
6313 break;
6314
6315 case GFC_ISYM_EXPONENT:
6316 gfc_conv_intrinsic_exponent (se, expr);
6317 break;
6318
4ee9c684 6319 case GFC_ISYM_SCAN:
40b806de 6320 kind = expr->value.function.actual->expr->ts.kind;
6321 if (kind == 1)
6322 fndecl = gfor_fndecl_string_scan;
6323 else if (kind == 4)
6324 fndecl = gfor_fndecl_string_scan_char4;
6325 else
6326 gcc_unreachable ();
6327
6328 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
4ee9c684 6329 break;
6330
6331 case GFC_ISYM_VERIFY:
40b806de 6332 kind = expr->value.function.actual->expr->ts.kind;
6333 if (kind == 1)
6334 fndecl = gfor_fndecl_string_verify;
6335 else if (kind == 4)
6336 fndecl = gfor_fndecl_string_verify_char4;
6337 else
6338 gcc_unreachable ();
6339
6340 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
4ee9c684 6341 break;
6342
6343 case GFC_ISYM_ALLOCATED:
6344 gfc_conv_allocated (se, expr);
6345 break;
6346
6347 case GFC_ISYM_ASSOCIATED:
6348 gfc_conv_associated(se, expr);
6349 break;
6350
1de1b1a9 6351 case GFC_ISYM_SAME_TYPE_AS:
6352 gfc_conv_same_type_as (se, expr);
6353 break;
6354
4ee9c684 6355 case GFC_ISYM_ABS:
6356 gfc_conv_intrinsic_abs (se, expr);
6357 break;
6358
6359 case GFC_ISYM_ADJUSTL:
40b806de 6360 if (expr->ts.kind == 1)
6361 fndecl = gfor_fndecl_adjustl;
6362 else if (expr->ts.kind == 4)
6363 fndecl = gfor_fndecl_adjustl_char4;
6364 else
6365 gcc_unreachable ();
6366
6367 gfc_conv_intrinsic_adjust (se, expr, fndecl);
4ee9c684 6368 break;
6369
6370 case GFC_ISYM_ADJUSTR:
40b806de 6371 if (expr->ts.kind == 1)
6372 fndecl = gfor_fndecl_adjustr;
6373 else if (expr->ts.kind == 4)
6374 fndecl = gfor_fndecl_adjustr_char4;
6375 else
6376 gcc_unreachable ();
6377
6378 gfc_conv_intrinsic_adjust (se, expr, fndecl);
4ee9c684 6379 break;
6380
6381 case GFC_ISYM_AIMAG:
6382 gfc_conv_intrinsic_imagpart (se, expr);
6383 break;
6384
6385 case GFC_ISYM_AINT:
8a1417cb 6386 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
4ee9c684 6387 break;
6388
6389 case GFC_ISYM_ALL:
6390 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
6391 break;
6392
6393 case GFC_ISYM_ANINT:
8a1417cb 6394 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
4ee9c684 6395 break;
6396
16de8065 6397 case GFC_ISYM_AND:
6398 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
6399 break;
6400
4ee9c684 6401 case GFC_ISYM_ANY:
6402 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
6403 break;
6404
6405 case GFC_ISYM_BTEST:
6406 gfc_conv_intrinsic_btest (se, expr);
6407 break;
6408
f004c7aa 6409 case GFC_ISYM_BGE:
6410 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
6411 break;
6412
6413 case GFC_ISYM_BGT:
6414 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
6415 break;
6416
6417 case GFC_ISYM_BLE:
6418 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
6419 break;
6420
6421 case GFC_ISYM_BLT:
6422 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
6423 break;
6424
4ee9c684 6425 case GFC_ISYM_ACHAR:
6426 case GFC_ISYM_CHAR:
6427 gfc_conv_intrinsic_char (se, expr);
6428 break;
6429
6430 case GFC_ISYM_CONVERSION:
6431 case GFC_ISYM_REAL:
6432 case GFC_ISYM_LOGICAL:
6433 case GFC_ISYM_DBLE:
6434 gfc_conv_intrinsic_conversion (se, expr);
6435 break;
6436
7b3423b9 6437 /* Integer conversions are handled separately to make sure we get the
4ee9c684 6438 correct rounding mode. */
6439 case GFC_ISYM_INT:
c7347b39 6440 case GFC_ISYM_INT2:
6441 case GFC_ISYM_INT8:
6442 case GFC_ISYM_LONG:
8a1417cb 6443 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
4ee9c684 6444 break;
6445
6446 case GFC_ISYM_NINT:
8a1417cb 6447 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
4ee9c684 6448 break;
6449
6450 case GFC_ISYM_CEILING:
8a1417cb 6451 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
4ee9c684 6452 break;
6453
6454 case GFC_ISYM_FLOOR:
8a1417cb 6455 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
4ee9c684 6456 break;
6457
6458 case GFC_ISYM_MOD:
6459 gfc_conv_intrinsic_mod (se, expr, 0);
6460 break;
6461
6462 case GFC_ISYM_MODULO:
6463 gfc_conv_intrinsic_mod (se, expr, 1);
6464 break;
6465
6466 case GFC_ISYM_CMPLX:
6467 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
6468 break;
6469
9b057c29 6470 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
f0f2da44 6471 gfc_conv_intrinsic_iargc (se, expr);
9b057c29 6472 break;
6473
16de8065 6474 case GFC_ISYM_COMPLEX:
6475 gfc_conv_intrinsic_cmplx (se, expr, 1);
6476 break;
6477
4ee9c684 6478 case GFC_ISYM_CONJG:
6479 gfc_conv_intrinsic_conjg (se, expr);
6480 break;
6481
6482 case GFC_ISYM_COUNT:
6483 gfc_conv_intrinsic_count (se, expr);
6484 break;
6485
b902b078 6486 case GFC_ISYM_CTIME:
6487 gfc_conv_intrinsic_ctime (se, expr);
6488 break;
6489
4ee9c684 6490 case GFC_ISYM_DIM:
6491 gfc_conv_intrinsic_dim (se, expr);
6492 break;
6493
0b5dc8b5 6494 case GFC_ISYM_DOT_PRODUCT:
6495 gfc_conv_intrinsic_dot_product (se, expr);
6496 break;
6497
4ee9c684 6498 case GFC_ISYM_DPROD:
6499 gfc_conv_intrinsic_dprod (se, expr);
6500 break;
6501
f004c7aa 6502 case GFC_ISYM_DSHIFTL:
6503 gfc_conv_intrinsic_dshift (se, expr, true);
6504 break;
6505
6506 case GFC_ISYM_DSHIFTR:
6507 gfc_conv_intrinsic_dshift (se, expr, false);
6508 break;
6509
b902b078 6510 case GFC_ISYM_FDATE:
6511 gfc_conv_intrinsic_fdate (se, expr);
6512 break;
6513
34e106da 6514 case GFC_ISYM_FRACTION:
6515 gfc_conv_intrinsic_fraction (se, expr);
6516 break;
6517
9028d57d 6518 case GFC_ISYM_IALL:
6519 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
6520 break;
6521
4ee9c684 6522 case GFC_ISYM_IAND:
6523 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
6524 break;
6525
9028d57d 6526 case GFC_ISYM_IANY:
6527 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
6528 break;
6529
4ee9c684 6530 case GFC_ISYM_IBCLR:
6531 gfc_conv_intrinsic_singlebitop (se, expr, 0);
6532 break;
6533
6534 case GFC_ISYM_IBITS:
6535 gfc_conv_intrinsic_ibits (se, expr);
6536 break;
6537
6538 case GFC_ISYM_IBSET:
6539 gfc_conv_intrinsic_singlebitop (se, expr, 1);
6540 break;
6541
6542 case GFC_ISYM_IACHAR:
6543 case GFC_ISYM_ICHAR:
6544 /* We assume ASCII character sequence. */
6545 gfc_conv_intrinsic_ichar (se, expr);
6546 break;
6547
9b057c29 6548 case GFC_ISYM_IARGC:
f0f2da44 6549 gfc_conv_intrinsic_iargc (se, expr);
9b057c29 6550 break;
6551
4ee9c684 6552 case GFC_ISYM_IEOR:
6553 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
6554 break;
6555
6556 case GFC_ISYM_INDEX:
40b806de 6557 kind = expr->value.function.actual->expr->ts.kind;
6558 if (kind == 1)
6559 fndecl = gfor_fndecl_string_index;
6560 else if (kind == 4)
6561 fndecl = gfor_fndecl_string_index_char4;
6562 else
6563 gcc_unreachable ();
6564
6565 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
4ee9c684 6566 break;
6567
6568 case GFC_ISYM_IOR:
6569 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
6570 break;
6571
9028d57d 6572 case GFC_ISYM_IPARITY:
6573 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
6574 break;
6575
52ed1096 6576 case GFC_ISYM_IS_IOSTAT_END:
18f0b7df 6577 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
52ed1096 6578 break;
6579
6580 case GFC_ISYM_IS_IOSTAT_EOR:
18f0b7df 6581 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
52ed1096 6582 break;
6583
4e549567 6584 case GFC_ISYM_ISNAN:
6585 gfc_conv_intrinsic_isnan (se, expr);
6586 break;
6587
d2fc5bb1 6588 case GFC_ISYM_LSHIFT:
f004c7aa 6589 gfc_conv_intrinsic_shift (se, expr, false, false);
d2fc5bb1 6590 break;
6591
6592 case GFC_ISYM_RSHIFT:
f004c7aa 6593 gfc_conv_intrinsic_shift (se, expr, true, true);
6594 break;
6595
6596 case GFC_ISYM_SHIFTA:
6597 gfc_conv_intrinsic_shift (se, expr, true, true);
6598 break;
6599
6600 case GFC_ISYM_SHIFTL:
6601 gfc_conv_intrinsic_shift (se, expr, false, false);
6602 break;
6603
6604 case GFC_ISYM_SHIFTR:
6605 gfc_conv_intrinsic_shift (se, expr, true, false);
d2fc5bb1 6606 break;
6607
4ee9c684 6608 case GFC_ISYM_ISHFT:
6609 gfc_conv_intrinsic_ishft (se, expr);
6610 break;
6611
6612 case GFC_ISYM_ISHFTC:
6613 gfc_conv_intrinsic_ishftc (se, expr);
6614 break;
6615
0b820f43 6616 case GFC_ISYM_LEADZ:
6617 gfc_conv_intrinsic_leadz (se, expr);
6618 break;
6619
6620 case GFC_ISYM_TRAILZ:
6621 gfc_conv_intrinsic_trailz (se, expr);
6622 break;
6623
41cbc93c 6624 case GFC_ISYM_POPCNT:
6625 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
6626 break;
6627
6628 case GFC_ISYM_POPPAR:
6629 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
6630 break;
6631
4ee9c684 6632 case GFC_ISYM_LBOUND:
6633 gfc_conv_intrinsic_bound (se, expr, 0);
6634 break;
6635
076094b7 6636 case GFC_ISYM_LCOBOUND:
6637 conv_intrinsic_cobound (se, expr);
6638 break;
6639
018ef8b8 6640 case GFC_ISYM_TRANSPOSE:
1274527b 6641 /* The scalarizer has already been set up for reversed dimension access
6642 order ; now we just get the argument value normally. */
6643 gfc_conv_expr (se, expr->value.function.actual->expr);
018ef8b8 6644 break;
6645
4ee9c684 6646 case GFC_ISYM_LEN:
6647 gfc_conv_intrinsic_len (se, expr);
6648 break;
6649
6650 case GFC_ISYM_LEN_TRIM:
6651 gfc_conv_intrinsic_len_trim (se, expr);
6652 break;
6653
6654 case GFC_ISYM_LGE:
6655 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
6656 break;
6657
6658 case GFC_ISYM_LGT:
6659 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
6660 break;
6661
6662 case GFC_ISYM_LLE:
6663 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
6664 break;
6665
6666 case GFC_ISYM_LLT:
6667 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
6668 break;
6669
f004c7aa 6670 case GFC_ISYM_MASKL:
6671 gfc_conv_intrinsic_mask (se, expr, 1);
6672 break;
6673
6674 case GFC_ISYM_MASKR:
6675 gfc_conv_intrinsic_mask (se, expr, 0);
6676 break;
6677
4ee9c684 6678 case GFC_ISYM_MAX:
5fcc6ec2 6679 if (expr->ts.type == BT_CHARACTER)
6680 gfc_conv_intrinsic_minmax_char (se, expr, 1);
6681 else
6682 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
4ee9c684 6683 break;
6684
6685 case GFC_ISYM_MAXLOC:
6686 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
6687 break;
6688
6689 case GFC_ISYM_MAXVAL:
6690 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
6691 break;
6692
6693 case GFC_ISYM_MERGE:
6694 gfc_conv_intrinsic_merge (se, expr);
6695 break;
6696
f004c7aa 6697 case GFC_ISYM_MERGE_BITS:
6698 gfc_conv_intrinsic_merge_bits (se, expr);
6699 break;
6700
4ee9c684 6701 case GFC_ISYM_MIN:
5fcc6ec2 6702 if (expr->ts.type == BT_CHARACTER)
6703 gfc_conv_intrinsic_minmax_char (se, expr, -1);
6704 else
6705 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
4ee9c684 6706 break;
6707
6708 case GFC_ISYM_MINLOC:
6709 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
6710 break;
6711
6712 case GFC_ISYM_MINVAL:
6713 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
6714 break;
6715
34e106da 6716 case GFC_ISYM_NEAREST:
6717 gfc_conv_intrinsic_nearest (se, expr);
6718 break;
6719
b4ba8232 6720 case GFC_ISYM_NORM2:
6721 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
6722 break;
6723
4ee9c684 6724 case GFC_ISYM_NOT:
6725 gfc_conv_intrinsic_not (se, expr);
6726 break;
6727
16de8065 6728 case GFC_ISYM_OR:
6729 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
6730 break;
6731
b4ba8232 6732 case GFC_ISYM_PARITY:
6733 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
6734 break;
6735
4ee9c684 6736 case GFC_ISYM_PRESENT:
6737 gfc_conv_intrinsic_present (se, expr);
6738 break;
6739
6740 case GFC_ISYM_PRODUCT:
b4ba8232 6741 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
4ee9c684 6742 break;
90342c73 6743
6744 case GFC_ISYM_RANK:
6745 gfc_conv_intrinsic_rank (se, expr);
6746 break;
4ee9c684 6747
34e106da 6748 case GFC_ISYM_RRSPACING:
6749 gfc_conv_intrinsic_rrspacing (se, expr);
6750 break;
6751
6752 case GFC_ISYM_SET_EXPONENT:
6753 gfc_conv_intrinsic_set_exponent (se, expr);
6754 break;
6755
6756 case GFC_ISYM_SCALE:
6757 gfc_conv_intrinsic_scale (se, expr);
6758 break;
6759
4ee9c684 6760 case GFC_ISYM_SIGN:
6761 gfc_conv_intrinsic_sign (se, expr);
6762 break;
6763
6764 case GFC_ISYM_SIZE:
6765 gfc_conv_intrinsic_size (se, expr);
6766 break;
6767
1318f16c 6768 case GFC_ISYM_SIZEOF:
95bf00d5 6769 case GFC_ISYM_C_SIZEOF:
1318f16c 6770 gfc_conv_intrinsic_sizeof (se, expr);
6771 break;
6772
95bf00d5 6773 case GFC_ISYM_STORAGE_SIZE:
6774 gfc_conv_intrinsic_storage_size (se, expr);
6775 break;
6776
34e106da 6777 case GFC_ISYM_SPACING:
6778 gfc_conv_intrinsic_spacing (se, expr);
6779 break;
6780
4ee9c684 6781 case GFC_ISYM_SUM:
b4ba8232 6782 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
4ee9c684 6783 break;
6784
6785 case GFC_ISYM_TRANSFER:
1b3fff24 6786 if (se->ss && se->ss->info->useflags)
1f2a3eec 6787 /* Access the previously obtained result. */
6788 gfc_conv_tmp_array_ref (se);
4eaa93a5 6789 else
891756c7 6790 gfc_conv_intrinsic_transfer (se, expr);
dbc97b88 6791 break;
6792
6793 case GFC_ISYM_TTYNAM:
6794 gfc_conv_intrinsic_ttynam (se, expr);
4ee9c684 6795 break;
6796
6797 case GFC_ISYM_UBOUND:
6798 gfc_conv_intrinsic_bound (se, expr, 1);
6799 break;
6800
076094b7 6801 case GFC_ISYM_UCOBOUND:
6802 conv_intrinsic_cobound (se, expr);
6803 break;
6804
16de8065 6805 case GFC_ISYM_XOR:
6806 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
6807 break;
6808
b549d2a5 6809 case GFC_ISYM_LOC:
6810 gfc_conv_intrinsic_loc (se, expr);
6811 break;
6812
70b5944a 6813 case GFC_ISYM_THIS_IMAGE:
2e34dcd8 6814 /* For num_images() == 1, handle as LCOBOUND. */
6815 if (expr->value.function.actual->expr
6816 && gfc_option.coarray == GFC_FCOARRAY_SINGLE)
076094b7 6817 conv_intrinsic_cobound (se, expr);
6818 else
6819 trans_this_image (se, expr);
70b5944a 6820 break;
6821
09800dba 6822 case GFC_ISYM_IMAGE_INDEX:
6823 trans_image_index (se, expr);
6824 break;
6825
70b5944a 6826 case GFC_ISYM_NUM_IMAGES:
6827 trans_num_images (se);
6828 break;
6829
d2fc5bb1 6830 case GFC_ISYM_ACCESS:
4dd3972f 6831 case GFC_ISYM_CHDIR:
d2fc5bb1 6832 case GFC_ISYM_CHMOD:
dd6c1457 6833 case GFC_ISYM_DTIME:
041de113 6834 case GFC_ISYM_ETIME:
bdfbc762 6835 case GFC_ISYM_EXTENDS_TYPE_OF:
16de8065 6836 case GFC_ISYM_FGET:
6837 case GFC_ISYM_FGETC:
771c1b50 6838 case GFC_ISYM_FNUM:
16de8065 6839 case GFC_ISYM_FPUT:
6840 case GFC_ISYM_FPUTC:
771c1b50 6841 case GFC_ISYM_FSTAT:
16de8065 6842 case GFC_ISYM_FTELL:
169bb4d1 6843 case GFC_ISYM_GETCWD:
adad6c74 6844 case GFC_ISYM_GETGID:
6845 case GFC_ISYM_GETPID:
6846 case GFC_ISYM_GETUID:
4dd3972f 6847 case GFC_ISYM_HOSTNM:
6848 case GFC_ISYM_KILL:
6849 case GFC_ISYM_IERRNO:
771c1b50 6850 case GFC_ISYM_IRAND:
60d77e0d 6851 case GFC_ISYM_ISATTY:
faa9fea4 6852 case GFC_ISYM_JN2:
4dd3972f 6853 case GFC_ISYM_LINK:
c7347b39 6854 case GFC_ISYM_LSTAT:
b3d3a366 6855 case GFC_ISYM_MALLOC:
771c1b50 6856 case GFC_ISYM_MATMUL:
c7347b39 6857 case GFC_ISYM_MCLOCK:
6858 case GFC_ISYM_MCLOCK8:
771c1b50 6859 case GFC_ISYM_RAND:
4dd3972f 6860 case GFC_ISYM_RENAME:
771c1b50 6861 case GFC_ISYM_SECOND:
10387833 6862 case GFC_ISYM_SECNDS:
247981ce 6863 case GFC_ISYM_SIGNAL:
771c1b50 6864 case GFC_ISYM_STAT:
4dd3972f 6865 case GFC_ISYM_SYMLNK:
82bbe4ec 6866 case GFC_ISYM_SYSTEM:
4dd3972f 6867 case GFC_ISYM_TIME:
6868 case GFC_ISYM_TIME8:
ab5619bc 6869 case GFC_ISYM_UMASK:
6870 case GFC_ISYM_UNLINK:
faa9fea4 6871 case GFC_ISYM_YN2:
4ee9c684 6872 gfc_conv_intrinsic_funcall (se, expr);
6873 break;
6874
8572fdb4 6875 case GFC_ISYM_EOSHIFT:
6876 case GFC_ISYM_PACK:
6877 case GFC_ISYM_RESHAPE:
6878 /* For those, expr->rank should always be >0 and thus the if above the
6879 switch should have matched. */
6880 gcc_unreachable ();
6881 break;
6882
4ee9c684 6883 default:
6884 gfc_conv_intrinsic_lib_function (se, expr);
6885 break;
6886 }
6887}
6888
6889
1274527b 6890static gfc_ss *
6891walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
6892{
6893 gfc_ss *arg_ss, *tmp_ss;
6894 gfc_actual_arglist *arg;
6895
6896 arg = expr->value.function.actual;
6897
6898 gcc_assert (arg->expr);
6899
6900 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
6901 gcc_assert (arg_ss != gfc_ss_terminator);
6902
6903 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
6904 {
45f39826 6905 if (tmp_ss->info->type != GFC_SS_SCALAR
6906 && tmp_ss->info->type != GFC_SS_REFERENCE)
1274527b 6907 {
6908 int tmp_dim;
1274527b 6909
91c54654 6910 gcc_assert (tmp_ss->dimen == 2);
1274527b 6911
6912 /* We just invert dimensions. */
91c54654 6913 tmp_dim = tmp_ss->dim[0];
6914 tmp_ss->dim[0] = tmp_ss->dim[1];
6915 tmp_ss->dim[1] = tmp_dim;
1274527b 6916 }
6917
6918 /* Stop when tmp_ss points to the last valid element of the chain... */
6919 if (tmp_ss->next == gfc_ss_terminator)
6920 break;
6921 }
6922
6923 /* ... so that we can attach the rest of the chain to it. */
6924 tmp_ss->next = ss;
6925
6926 return arg_ss;
6927}
6928
6929
88df5e2f 6930/* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
6931 This has the side effect of reversing the nested list, so there is no
6932 need to call gfc_reverse_ss on it (the given list is assumed not to be
6933 reversed yet). */
6934
6935static gfc_ss *
6936nest_loop_dimension (gfc_ss *ss, int dim)
6937{
6938 int ss_dim, i;
6939 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
6940 gfc_loopinfo *new_loop;
6941
6942 gcc_assert (ss != gfc_ss_terminator);
6943
6944 for (; ss != gfc_ss_terminator; ss = ss->next)
6945 {
6946 new_ss = gfc_get_ss ();
6947 new_ss->next = prev_ss;
6948 new_ss->parent = ss;
6949 new_ss->info = ss->info;
6950 new_ss->info->refcount++;
6951 if (ss->dimen != 0)
6952 {
6953 gcc_assert (ss->info->type != GFC_SS_SCALAR
6954 && ss->info->type != GFC_SS_REFERENCE);
6955
6956 new_ss->dimen = 1;
6957 new_ss->dim[0] = ss->dim[dim];
6958
6959 gcc_assert (dim < ss->dimen);
6960
6961 ss_dim = --ss->dimen;
6962 for (i = dim; i < ss_dim; i++)
6963 ss->dim[i] = ss->dim[i + 1];
6964
6965 ss->dim[ss_dim] = 0;
6966 }
6967 prev_ss = new_ss;
6968
6969 if (ss->nested_ss)
6970 {
6971 ss->nested_ss->parent = new_ss;
6972 new_ss->nested_ss = ss->nested_ss;
6973 }
6974 ss->nested_ss = new_ss;
6975 }
6976
6977 new_loop = gfc_get_loopinfo ();
6978 gfc_init_loopinfo (new_loop);
6979
6980 gcc_assert (prev_ss != NULL);
6981 gcc_assert (prev_ss != gfc_ss_terminator);
6982 gfc_add_ss_to_loop (new_loop, prev_ss);
6983 return new_ss->parent;
6984}
6985
6986
6987/* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
6988 is to be inlined. */
6989
6990static gfc_ss *
6991walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
6992{
6993 gfc_ss *tmp_ss, *tail, *array_ss;
6994 gfc_actual_arglist *arg1, *arg2, *arg3;
6995 int sum_dim;
6996 bool scalar_mask = false;
6997
6998 /* The rank of the result will be determined later. */
6999 arg1 = expr->value.function.actual;
7000 arg2 = arg1->next;
7001 arg3 = arg2->next;
7002 gcc_assert (arg3 != NULL);
7003
7004 if (expr->rank == 0)
7005 return ss;
7006
7007 tmp_ss = gfc_ss_terminator;
7008
7009 if (arg3->expr)
7010 {
7011 gfc_ss *mask_ss;
7012
7013 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
7014 if (mask_ss == tmp_ss)
7015 scalar_mask = 1;
7016
7017 tmp_ss = mask_ss;
7018 }
7019
7020 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
7021 gcc_assert (array_ss != tmp_ss);
7022
7023 /* Odd thing: If the mask is scalar, it is used by the frontend after
7024 the array (to make an if around the nested loop). Thus it shall
7025 be after array_ss once the gfc_ss list is reversed. */
7026 if (scalar_mask)
7027 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
7028 else
7029 tmp_ss = array_ss;
7030
7031 /* "Hide" the dimension on which we will sum in the first arg's scalarization
7032 chain. */
7033 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
7034 tail = nest_loop_dimension (tmp_ss, sum_dim);
7035 tail->next = ss;
7036
7037 return tmp_ss;
7038}
7039
7040
1274527b 7041static gfc_ss *
7042walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
7043{
7044
7045 switch (expr->value.function.isym->id)
7046 {
88df5e2f 7047 case GFC_ISYM_PRODUCT:
7048 case GFC_ISYM_SUM:
7049 return walk_inline_intrinsic_arith (ss, expr);
7050
1274527b 7051 case GFC_ISYM_TRANSPOSE:
7052 return walk_inline_intrinsic_transpose (ss, expr);
7053
7054 default:
7055 gcc_unreachable ();
7056 }
7057 gcc_unreachable ();
7058}
7059
7060
4ee9c684 7061/* This generates code to execute before entering the scalarization loop.
7062 Currently does nothing. */
7063
7064void
7065gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
7066{
bfa43780 7067 switch (ss->info->expr->value.function.isym->id)
4ee9c684 7068 {
7069 case GFC_ISYM_UBOUND:
7070 case GFC_ISYM_LBOUND:
076094b7 7071 case GFC_ISYM_UCOBOUND:
7072 case GFC_ISYM_LCOBOUND:
7073 case GFC_ISYM_THIS_IMAGE:
4ee9c684 7074 break;
7075
7076 default:
22d678e8 7077 gcc_unreachable ();
4ee9c684 7078 }
7079}
7080
7081
076094b7 7082/* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
7083 are expanded into code inside the scalarization loop. */
4ee9c684 7084
7085static gfc_ss *
7086gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
7087{
fd23cc08 7088 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
7089 gfc_add_class_array_ref (expr->value.function.actual->expr);
7090
4ee9c684 7091 /* The two argument version returns a scalar. */
7092 if (expr->value.function.actual->next->expr)
7093 return ss;
7094
f912e858 7095 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
4ee9c684 7096}
7097
7098
7099/* Walk an intrinsic array libcall. */
7100
7101static gfc_ss *
7102gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
7103{
22d678e8 7104 gcc_assert (expr->rank > 0);
f912e858 7105 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
4ee9c684 7106}
7107
7108
1274527b 7109/* Return whether the function call expression EXPR will be expanded
7110 inline by gfc_conv_intrinsic_function. */
7111
7112bool
7113gfc_inline_intrinsic_function_p (gfc_expr *expr)
7114{
88df5e2f 7115 gfc_actual_arglist *args;
7116
1274527b 7117 if (!expr->value.function.isym)
7118 return false;
7119
7120 switch (expr->value.function.isym->id)
7121 {
88df5e2f 7122 case GFC_ISYM_PRODUCT:
7123 case GFC_ISYM_SUM:
7124 /* Disable inline expansion if code size matters. */
7125 if (optimize_size)
7126 return false;
7127
7128 args = expr->value.function.actual;
7129 /* We need to be able to subset the SUM argument at compile-time. */
7130 if (args->next->expr && args->next->expr->expr_type != EXPR_CONSTANT)
7131 return false;
7132
7133 return true;
7134
1274527b 7135 case GFC_ISYM_TRANSPOSE:
7136 return true;
7137
7138 default:
7139 return false;
7140 }
7141}
7142
7143
69b1505f 7144/* Returns nonzero if the specified intrinsic function call maps directly to
4ee9c684 7145 an external library call. Should only be used for functions that return
7146 arrays. */
7147
7148int
7149gfc_is_intrinsic_libcall (gfc_expr * expr)
7150{
22d678e8 7151 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
7152 gcc_assert (expr->rank > 0);
4ee9c684 7153
1274527b 7154 if (gfc_inline_intrinsic_function_p (expr))
7155 return 0;
7156
55cb4417 7157 switch (expr->value.function.isym->id)
4ee9c684 7158 {
7159 case GFC_ISYM_ALL:
7160 case GFC_ISYM_ANY:
7161 case GFC_ISYM_COUNT:
faa9fea4 7162 case GFC_ISYM_JN2:
9028d57d 7163 case GFC_ISYM_IANY:
7164 case GFC_ISYM_IALL:
7165 case GFC_ISYM_IPARITY:
4ee9c684 7166 case GFC_ISYM_MATMUL:
7167 case GFC_ISYM_MAXLOC:
7168 case GFC_ISYM_MAXVAL:
7169 case GFC_ISYM_MINLOC:
7170 case GFC_ISYM_MINVAL:
b4ba8232 7171 case GFC_ISYM_NORM2:
7172 case GFC_ISYM_PARITY:
4ee9c684 7173 case GFC_ISYM_PRODUCT:
7174 case GFC_ISYM_SUM:
7175 case GFC_ISYM_SHAPE:
7176 case GFC_ISYM_SPREAD:
faa9fea4 7177 case GFC_ISYM_YN2:
4ee9c684 7178 /* Ignore absent optional parameters. */
7179 return 1;
7180
7181 case GFC_ISYM_RESHAPE:
7182 case GFC_ISYM_CSHIFT:
7183 case GFC_ISYM_EOSHIFT:
7184 case GFC_ISYM_PACK:
7185 case GFC_ISYM_UNPACK:
7186 /* Pass absent optional parameters. */
7187 return 2;
7188
7189 default:
7190 return 0;
7191 }
7192}
7193
7194/* Walk an intrinsic function. */
7195gfc_ss *
7196gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
7197 gfc_intrinsic_sym * isym)
7198{
22d678e8 7199 gcc_assert (isym);
4ee9c684 7200
7201 if (isym->elemental)
1274527b 7202 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
4fd5163b 7203 NULL, GFC_SS_SCALAR);
4ee9c684 7204
7205 if (expr->rank == 0)
7206 return ss;
7207
1274527b 7208 if (gfc_inline_intrinsic_function_p (expr))
7209 return walk_inline_intrinsic_function (ss, expr);
7210
4ee9c684 7211 if (gfc_is_intrinsic_libcall (expr))
7212 return gfc_walk_intrinsic_libfunc (ss, expr);
7213
7214 /* Special cases. */
55cb4417 7215 switch (isym->id)
4ee9c684 7216 {
7217 case GFC_ISYM_LBOUND:
076094b7 7218 case GFC_ISYM_LCOBOUND:
4ee9c684 7219 case GFC_ISYM_UBOUND:
076094b7 7220 case GFC_ISYM_UCOBOUND:
7221 case GFC_ISYM_THIS_IMAGE:
4ee9c684 7222 return gfc_walk_intrinsic_bound (ss, expr);
7223
4eaa93a5 7224 case GFC_ISYM_TRANSFER:
7225 return gfc_walk_intrinsic_libfunc (ss, expr);
7226
4ee9c684 7227 default:
7228 /* This probably meant someone forgot to add an intrinsic to the above
cbbac028 7229 list(s) when they implemented it, or something's gone horribly
7230 wrong. */
7231 gcc_unreachable ();
4ee9c684 7232 }
7233}
7234
0fc13348 7235
6ccde1eb 7236static tree
7237conv_intrinsic_atomic_def (gfc_code *code)
7238{
7239 gfc_se atom, value;
7240 stmtblock_t block;
7241
7242 gfc_init_se (&atom, NULL);
7243 gfc_init_se (&value, NULL);
7244 gfc_conv_expr (&atom, code->ext.actual->expr);
7245 gfc_conv_expr (&value, code->ext.actual->next->expr);
7246
7247 gfc_init_block (&block);
7248 gfc_add_modify (&block, atom.expr,
7249 fold_convert (TREE_TYPE (atom.expr), value.expr));
7250 return gfc_finish_block (&block);
7251}
7252
7253
7254static tree
7255conv_intrinsic_atomic_ref (gfc_code *code)
7256{
7257 gfc_se atom, value;
7258 stmtblock_t block;
7259
7260 gfc_init_se (&atom, NULL);
7261 gfc_init_se (&value, NULL);
7262 gfc_conv_expr (&value, code->ext.actual->expr);
7263 gfc_conv_expr (&atom, code->ext.actual->next->expr);
7264
7265 gfc_init_block (&block);
7266 gfc_add_modify (&block, value.expr,
7267 fold_convert (TREE_TYPE (value.expr), atom.expr));
7268 return gfc_finish_block (&block);
7269}
7270
7271
7272static tree
7273conv_intrinsic_move_alloc (gfc_code *code)
0fc13348 7274{
5ce6c67e 7275 stmtblock_t block;
7276 gfc_expr *from_expr, *to_expr;
dd0cebe1 7277 gfc_expr *to_expr2, *from_expr2 = NULL;
5ce6c67e 7278 gfc_se from_se, to_se;
5ce6c67e 7279 tree tmp;
fc378a70 7280 bool coarray;
0fc13348 7281
5ce6c67e 7282 gfc_start_block (&block);
0fc13348 7283
5ce6c67e 7284 from_expr = code->ext.actual->expr;
7285 to_expr = code->ext.actual->next->expr;
0fc13348 7286
5ce6c67e 7287 gfc_init_se (&from_se, NULL);
7288 gfc_init_se (&to_se, NULL);
3e223d53 7289
3a19c063 7290 gcc_assert (from_expr->ts.type != BT_CLASS
7291 || to_expr->ts.type == BT_CLASS);
fc378a70 7292 coarray = gfc_get_corank (from_expr) != 0;
3a19c063 7293
fc378a70 7294 if (from_expr->rank == 0 && !coarray)
5ce6c67e 7295 {
7296 if (from_expr->ts.type != BT_CLASS)
dd0cebe1 7297 from_expr2 = from_expr;
7298 else
5ce6c67e 7299 {
dd0cebe1 7300 from_expr2 = gfc_copy_expr (from_expr);
7301 gfc_add_data_component (from_expr2);
5ce6c67e 7302 }
dd0cebe1 7303
7304 if (to_expr->ts.type != BT_CLASS)
7305 to_expr2 = to_expr;
0fc13348 7306 else
5ce6c67e 7307 {
7308 to_expr2 = gfc_copy_expr (to_expr);
5ce6c67e 7309 gfc_add_data_component (to_expr2);
7310 }
0fc13348 7311
5ce6c67e 7312 from_se.want_pointer = 1;
7313 to_se.want_pointer = 1;
7314 gfc_conv_expr (&from_se, from_expr2);
7315 gfc_conv_expr (&to_se, to_expr2);
7316 gfc_add_block_to_block (&block, &from_se.pre);
7317 gfc_add_block_to_block (&block, &to_se.pre);
7318
7319 /* Deallocate "to". */
7320 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, true,
7321 to_expr2, to_expr->ts);
0fc13348 7322 gfc_add_expr_to_block (&block, tmp);
7323
5ce6c67e 7324 /* Assign (_data) pointers. */
7325 gfc_add_modify_loc (input_location, &block, to_se.expr,
7326 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
7327
7328 /* Set "from" to NULL. */
7329 gfc_add_modify_loc (input_location, &block, from_se.expr,
7330 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
7331
7332 gfc_add_block_to_block (&block, &from_se.post);
7333 gfc_add_block_to_block (&block, &to_se.post);
7334
7335 /* Set _vptr. */
dd0cebe1 7336 if (to_expr->ts.type == BT_CLASS)
5ce6c67e 7337 {
dd0cebe1 7338 gfc_free_expr (to_expr2);
5ce6c67e 7339 gfc_init_se (&to_se, NULL);
5ce6c67e 7340 to_se.want_pointer = 1;
5ce6c67e 7341 gfc_add_vptr_component (to_expr);
5ce6c67e 7342 gfc_conv_expr (&to_se, to_expr);
dd0cebe1 7343
7344 if (from_expr->ts.type == BT_CLASS)
7345 {
7346 gfc_free_expr (from_expr2);
7347 gfc_init_se (&from_se, NULL);
7348 from_se.want_pointer = 1;
7349 gfc_add_vptr_component (from_expr);
7350 gfc_conv_expr (&from_se, from_expr);
7351 tmp = from_se.expr;
7352 }
7353 else
7354 {
7355 gfc_symbol *vtab;
7356 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
7357 gcc_assert (vtab);
7358 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7359 }
7360
5ce6c67e 7361 gfc_add_modify_loc (input_location, &block, to_se.expr,
dd0cebe1 7362 fold_convert (TREE_TYPE (to_se.expr), tmp));
5ce6c67e 7363 }
7364
0fc13348 7365 return gfc_finish_block (&block);
7366 }
5ce6c67e 7367
7368 /* Update _vptr component. */
dd0cebe1 7369 if (to_expr->ts.type == BT_CLASS)
5ce6c67e 7370 {
5ce6c67e 7371 to_se.want_pointer = 1;
5ce6c67e 7372 to_expr2 = gfc_copy_expr (to_expr);
5ce6c67e 7373 gfc_add_vptr_component (to_expr2);
5ce6c67e 7374 gfc_conv_expr (&to_se, to_expr2);
7375
dd0cebe1 7376 if (from_expr->ts.type == BT_CLASS)
7377 {
7378 from_se.want_pointer = 1;
7379 from_expr2 = gfc_copy_expr (from_expr);
7380 gfc_add_vptr_component (from_expr2);
7381 gfc_conv_expr (&from_se, from_expr2);
7382 tmp = from_se.expr;
7383 }
7384 else
7385 {
7386 gfc_symbol *vtab;
7387 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
7388 gcc_assert (vtab);
7389 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
7390 }
7391
5ce6c67e 7392 gfc_add_modify_loc (input_location, &block, to_se.expr,
dd0cebe1 7393 fold_convert (TREE_TYPE (to_se.expr), tmp));
5ce6c67e 7394 gfc_free_expr (to_expr2);
5ce6c67e 7395 gfc_init_se (&to_se, NULL);
dd0cebe1 7396
7397 if (from_expr->ts.type == BT_CLASS)
7398 {
7399 gfc_free_expr (from_expr2);
7400 gfc_init_se (&from_se, NULL);
7401 }
5ce6c67e 7402 }
7403
5d34a30f 7404
5ce6c67e 7405 /* Deallocate "to". */
5d34a30f 7406 if (from_expr->rank == 0)
fc378a70 7407 {
5d34a30f 7408 to_se.want_coarray = 1;
7409 from_se.want_coarray = 1;
fc378a70 7410 }
5d34a30f 7411 gfc_conv_expr_descriptor (&to_se, to_expr);
7412 gfc_conv_expr_descriptor (&from_se, from_expr);
5ce6c67e 7413
fc378a70 7414 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
7415 is an image control "statement", cf. IR F08/0040 in 12-006A. */
7416 if (coarray && gfc_option.coarray == GFC_FCOARRAY_LIB)
7417 {
7418 tree cond;
7419
7420 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
7421 NULL_TREE, NULL_TREE, true, to_expr,
7422 true);
7423 gfc_add_expr_to_block (&block, tmp);
7424
7425 tmp = gfc_conv_descriptor_data_get (to_se.expr);
7426 cond = fold_build2_loc (input_location, EQ_EXPR,
7427 boolean_type_node, tmp,
7428 fold_convert (TREE_TYPE (tmp),
7429 null_pointer_node));
7430 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
7431 3, null_pointer_node, null_pointer_node,
7432 build_int_cst (integer_type_node, 0));
7433
7434 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
7435 tmp, build_empty_stmt (input_location));
7436 gfc_add_expr_to_block (&block, tmp);
7437 }
7438 else
7439 {
7440 tmp = gfc_conv_descriptor_data_get (to_se.expr);
7441 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
7442 NULL_TREE, true, to_expr, false);
7443 gfc_add_expr_to_block (&block, tmp);
7444 }
5ce6c67e 7445
7446 /* Move the pointer and update the array descriptor data. */
7447 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
7448
7449 /* Set "to" to NULL. */
7450 tmp = gfc_conv_descriptor_data_get (from_se.expr);
7451 gfc_add_modify_loc (input_location, &block, tmp,
7452 fold_convert (TREE_TYPE (tmp), null_pointer_node));
7453
7454 return gfc_finish_block (&block);
0fc13348 7455}
7456
7457
6ccde1eb 7458tree
7459gfc_conv_intrinsic_subroutine (gfc_code *code)
7460{
7461 tree res;
7462
7463 gcc_assert (code->resolved_isym);
7464
7465 switch (code->resolved_isym->id)
7466 {
7467 case GFC_ISYM_MOVE_ALLOC:
7468 res = conv_intrinsic_move_alloc (code);
7469 break;
7470
7471 case GFC_ISYM_ATOMIC_DEF:
7472 res = conv_intrinsic_atomic_def (code);
7473 break;
7474
7475 case GFC_ISYM_ATOMIC_REF:
7476 res = conv_intrinsic_atomic_ref (code);
7477 break;
7478
7479 default:
7480 res = NULL_TREE;
7481 break;
7482 }
7483
7484 return res;
7485}
7486
4ee9c684 7487#include "gt-fortran-trans-intrinsic.h"