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