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