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