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