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