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