]> gcc.gnu.org Git - gcc.git/blame - gcc/fortran/trans-intrinsic.cc
fortran: Expand ieee_arithmetic module's ieee_class inline [PR106579]
[gcc.git] / gcc / fortran / trans-intrinsic.cc
CommitLineData
6de9cd9a 1/* Intrinsic translation
7adcbafe 2 Copyright (C) 2002-2022 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 21
e53b6e56 22/* trans-intrinsic.cc-- generate GENERIC trees for calls to intrinsics. */
6de9cd9a
DN
23
24#include "config.h"
25#include "system.h"
26#include "coretypes.h"
4d0cdd0c 27#include "memmodel.h"
a48ba7e1 28#include "tm.h" /* For UNITS_PER_WORD. */
6de9cd9a 29#include "tree.h"
2adfab87
AM
30#include "gfortran.h"
31#include "trans.h"
d8a2d370 32#include "stringpool.h"
2adfab87 33#include "fold-const.h"
e0c27d52 34#include "internal-fn.h"
d8a2d370
DN
35#include "tree-nested.h"
36#include "stor-layout.h"
c829d016 37#include "toplev.h" /* For rest_of_decl_compilation. */
f8e566e5 38#include "arith.h"
6de9cd9a
DN
39#include "trans-const.h"
40#include "trans-types.h"
41#include "trans-array.h"
93e2e046 42#include "dependency.h" /* For CAF array alias analysis. */
36ec54aa
TK
43#include "attribs.h"
44
6de9cd9a 45/* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
6de9cd9a 46
eea58adb 47/* This maps Fortran intrinsic math functions to external library or GCC
6de9cd9a 48 builtin functions. */
d1b38208 49typedef struct GTY(()) gfc_intrinsic_map_t {
6de9cd9a
DN
50 /* The explicit enum is required to work around inadequacies in the
51 garbage collection/gengtype parsing mechanism. */
cd5ecab6 52 enum gfc_isym_id id;
6de9cd9a
DN
53
54 /* Enum value from the "language-independent", aka C-centric, part
55 of gcc, or END_BUILTINS of no such value set. */
2921157d
FXC
56 enum built_in_function float_built_in;
57 enum built_in_function double_built_in;
58 enum built_in_function long_double_built_in;
59 enum built_in_function complex_float_built_in;
60 enum built_in_function complex_double_built_in;
61 enum built_in_function complex_long_double_built_in;
6de9cd9a
DN
62
63 /* True if the naming pattern is to prepend "c" for complex and
64 append "f" for kind=4. False if the naming pattern is to
644cb69f 65 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
6de9cd9a
DN
66 bool libm_name;
67
68 /* True if a complex version of the function exists. */
69 bool complex_available;
70
71 /* True if the function should be marked const. */
72 bool is_constant;
73
74 /* The base library name of this function. */
75 const char *name;
76
77 /* Cache decls created for the various operand types. */
78 tree real4_decl;
79 tree real8_decl;
644cb69f
FXC
80 tree real10_decl;
81 tree real16_decl;
6de9cd9a
DN
82 tree complex4_decl;
83 tree complex8_decl;
644cb69f
FXC
84 tree complex10_decl;
85 tree complex16_decl;
6de9cd9a
DN
86}
87gfc_intrinsic_map_t;
88
89/* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
90 defines complex variants of all of the entries in mathbuiltins.def
91 except for atan2. */
644cb69f
FXC
92#define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
93 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
2921157d
FXC
94 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
95 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
96 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
644cb69f
FXC
97
98#define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
99 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
2921157d
FXC
100 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
101 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
102 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
6de9cd9a 103
f489fba1 104#define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
2921157d
FXC
105 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
106 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
f489fba1
FXC
107 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
108 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
109
a3c85b74 110#define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
2921157d
FXC
111 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
112 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
a3c85b74 113 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
2921157d
FXC
114 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
115
6de9cd9a
DN
116static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
117{
2921157d
FXC
118 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
119 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
120 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
6de9cd9a
DN
121#include "mathbuiltins.def"
122
f489fba1
FXC
123 /* Functions in libgfortran. */
124 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
57391dda
FR
125 LIB_FUNCTION (SIND, "sind", false),
126 LIB_FUNCTION (COSD, "cosd", false),
127 LIB_FUNCTION (TAND, "tand", false),
f489fba1 128
6de9cd9a 129 /* End the list. */
f489fba1
FXC
130 LIB_FUNCTION (NONE, NULL, false)
131
6de9cd9a 132};
2921157d 133#undef OTHER_BUILTIN
f489fba1 134#undef LIB_FUNCTION
6de9cd9a 135#undef DEFINE_MATH_BUILTIN
e8525382 136#undef DEFINE_MATH_BUILTIN_C
6de9cd9a 137
6de9cd9a 138
f9f770a8 139enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
6de9cd9a 140
2921157d
FXC
141
142/* Find the correct variant of a given builtin from its argument. */
143static tree
144builtin_decl_for_precision (enum built_in_function base_built_in,
145 int precision)
146{
e79983f4 147 enum built_in_function i = END_BUILTINS;
2921157d
FXC
148
149 gfc_intrinsic_map_t *m;
150 for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
151 ;
152
153 if (precision == TYPE_PRECISION (float_type_node))
154 i = m->float_built_in;
155 else if (precision == TYPE_PRECISION (double_type_node))
156 i = m->double_built_in;
e79f6e61
JJ
157 else if (precision == TYPE_PRECISION (long_double_type_node)
158 && (!gfc_real16_is_float128
159 || long_double_type_node != gfc_float128_type_node))
2921157d 160 i = m->long_double_built_in;
c65699ef 161 else if (precision == TYPE_PRECISION (gfc_float128_type_node))
a3c85b74
FXC
162 {
163 /* Special treatment, because it is not exactly a built-in, but
164 a library function. */
165 return m->real16_decl;
166 }
2921157d 167
e79983f4 168 return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
2921157d
FXC
169}
170
171
166d08bd
FXC
172tree
173gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in,
174 int kind)
2921157d
FXC
175{
176 int i = gfc_validate_kind (BT_REAL, kind, false);
a3c85b74
FXC
177
178 if (gfc_real_kinds[i].c_float128)
179 {
00b1324f 180 /* For _Float128, the story is a bit different, because we return
a3c85b74 181 a decl to a library function rather than a built-in. */
029b2d55 182 gfc_intrinsic_map_t *m;
a3c85b74
FXC
183 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
184 ;
185
186 return m->real16_decl;
187 }
188
2921157d
FXC
189 return builtin_decl_for_precision (double_built_in,
190 gfc_real_kinds[i].mode_precision);
191}
192
193
55637e51
LM
194/* Evaluate the arguments to an intrinsic function. The value
195 of NARGS may be less than the actual number of arguments in EXPR
196 to allow optional "KIND" arguments that are not included in the
197 generated code to be ignored. */
6de9cd9a 198
55637e51
LM
199static void
200gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
201 tree *argarray, int nargs)
6de9cd9a
DN
202{
203 gfc_actual_arglist *actual;
e15e9be3
PT
204 gfc_expr *e;
205 gfc_intrinsic_arg *formal;
6de9cd9a 206 gfc_se argse;
55637e51 207 int curr_arg;
6de9cd9a 208
e15e9be3 209 formal = expr->value.function.isym->formal;
55637e51 210 actual = expr->value.function.actual;
e15e9be3 211
55637e51
LM
212 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
213 actual = actual->next,
214 formal = formal ? formal->next : NULL)
6de9cd9a 215 {
55637e51 216 gcc_assert (actual);
e15e9be3 217 e = actual->expr;
aa9c57ec 218 /* Skip omitted optional arguments. */
e15e9be3 219 if (!e)
55637e51
LM
220 {
221 --curr_arg;
222 continue;
223 }
6de9cd9a
DN
224
225 /* Evaluate the parameter. This will substitute scalarized
f7b529fa 226 references automatically. */
6de9cd9a
DN
227 gfc_init_se (&argse, se);
228
e15e9be3 229 if (e->ts.type == BT_CHARACTER)
6de9cd9a 230 {
e15e9be3 231 gfc_conv_expr (&argse, e);
6de9cd9a 232 gfc_conv_string_parameter (&argse);
55637e51
LM
233 argarray[curr_arg++] = argse.string_length;
234 gcc_assert (curr_arg < nargs);
6de9cd9a
DN
235 }
236 else
e15e9be3
PT
237 gfc_conv_expr_val (&argse, e);
238
239 /* If an optional argument is itself an optional dummy argument,
240 check its presence and substitute a null if absent. */
33717d59 241 if (e->expr_type == EXPR_VARIABLE
e15e9be3
PT
242 && e->symtree->n.sym->attr.optional
243 && formal
244 && formal->optional)
be9c3c6e 245 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
6de9cd9a
DN
246
247 gfc_add_block_to_block (&se->pre, &argse.pre);
248 gfc_add_block_to_block (&se->post, &argse.post);
55637e51
LM
249 argarray[curr_arg] = argse.expr;
250 }
251}
252
253/* Count the number of actual arguments to the intrinsic function EXPR
254 including any "hidden" string length arguments. */
255
256static unsigned int
257gfc_intrinsic_argument_list_length (gfc_expr *expr)
258{
259 int n = 0;
260 gfc_actual_arglist *actual;
261
262 for (actual = expr->value.function.actual; actual; actual = actual->next)
263 {
264 if (!actual->expr)
265 continue;
266
267 if (actual->expr->ts.type == BT_CHARACTER)
268 n += 2;
269 else
270 n++;
8374844f 271 }
55637e51
LM
272
273 return n;
6de9cd9a
DN
274}
275
276
277/* Conversions between different types are output by the frontend as
278 intrinsic functions. We implement these directly with inline code. */
279
280static void
281gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
282{
283 tree type;
55637e51
LM
284 tree *args;
285 int nargs;
6de9cd9a 286
55637e51 287 nargs = gfc_intrinsic_argument_list_length (expr);
1145e690 288 args = XALLOCAVEC (tree, nargs);
55637e51 289
029b2d55
PT
290 /* Evaluate all the arguments passed. Whilst we're only interested in the
291 first one here, there are other parts of the front-end that assume this
55637e51 292 and will trigger an ICE if it's not the case. */
6de9cd9a 293 type = gfc_typenode_for_spec (&expr->ts);
6e45f57b 294 gcc_assert (expr->value.function.actual->expr);
55637e51 295 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6de9cd9a 296
d393bbd7
FXC
297 /* Conversion between character kinds involves a call to a library
298 function. */
299 if (expr->ts.type == BT_CHARACTER)
300 {
301 tree fndecl, var, addr, tmp;
302
303 if (expr->ts.kind == 1
304 && expr->value.function.actual->expr->ts.kind == 4)
305 fndecl = gfor_fndecl_convert_char4_to_char1;
306 else if (expr->ts.kind == 4
307 && expr->value.function.actual->expr->ts.kind == 1)
308 fndecl = gfor_fndecl_convert_char1_to_char4;
309 else
310 gcc_unreachable ();
311
312 /* Create the variable storing the converted value. */
313 type = gfc_get_pchar_type (expr->ts.kind);
314 var = gfc_create_var (type, "str");
315 addr = gfc_build_addr_expr (build_pointer_type (type), var);
316
317 /* Call the library function that will perform the conversion. */
318 gcc_assert (nargs >= 2);
db3927fb
AH
319 tmp = build_call_expr_loc (input_location,
320 fndecl, 3, addr, args[0], args[1]);
d393bbd7
FXC
321 gfc_add_expr_to_block (&se->pre, tmp);
322
323 /* Free the temporary afterwards. */
324 tmp = gfc_call_free (var);
325 gfc_add_expr_to_block (&se->post, tmp);
326
327 se->expr = var;
328 se->string_length = args[0];
329
330 return;
331 }
332
6de9cd9a
DN
333 /* Conversion from complex to non-complex involves taking the real
334 component of the value. */
55637e51 335 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
6de9cd9a
DN
336 && expr->ts.type != BT_COMPLEX)
337 {
338 tree artype;
339
55637e51 340 artype = TREE_TYPE (TREE_TYPE (args[0]));
433ce291
TB
341 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
342 args[0]);
6de9cd9a
DN
343 }
344
55637e51 345 se->expr = convert (type, args[0]);
6de9cd9a
DN
346}
347
4fdb5c71
TS
348/* This is needed because the gcc backend only implements
349 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
350 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
6de9cd9a
DN
351 Similarly for CEILING. */
352
353static tree
354build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
355{
356 tree tmp;
357 tree cond;
358 tree argtype;
359 tree intval;
360
361 argtype = TREE_TYPE (arg);
362 arg = gfc_evaluate_now (arg, pblock);
363
364 intval = convert (type, arg);
365 intval = gfc_evaluate_now (intval, pblock);
366
367 tmp = convert (argtype, intval);
433ce291 368 cond = fold_build2_loc (input_location, up ? GE_EXPR : LE_EXPR,
63ee5404 369 logical_type_node, tmp, arg);
6de9cd9a 370
433ce291
TB
371 tmp = fold_build2_loc (input_location, up ? PLUS_EXPR : MINUS_EXPR, type,
372 intval, build_int_cst (type, 1));
373 tmp = fold_build3_loc (input_location, COND_EXPR, type, cond, intval, tmp);
6de9cd9a
DN
374 return tmp;
375}
376
377
94f548c2 378/* Round to nearest integer, away from zero. */
6de9cd9a
DN
379
380static tree
94f548c2 381build_round_expr (tree arg, tree restype)
6de9cd9a 382{
6de9cd9a 383 tree argtype;
94f548c2 384 tree fn;
94f548c2 385 int argprec, resprec;
6de9cd9a
DN
386
387 argtype = TREE_TYPE (arg);
94f548c2
FXC
388 argprec = TYPE_PRECISION (argtype);
389 resprec = TYPE_PRECISION (restype);
6de9cd9a 390
3cf04d1a 391 /* Depending on the type of the result, choose the int intrinsic (iround,
00b1324f 392 available only as a builtin, therefore cannot use it for _Float128), long
3cf04d1a
MM
393 int intrinsic (lround family) or long long intrinsic (llround). If we
394 don't have an appropriate function that converts directly to the integer
395 type (such as kind == 16), just use ROUND, and then convert the result to
396 an integer. We might also need to convert the result afterwards. */
c4256b35 397 if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE)
6715d47b
JB
398 fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec);
399 else if (resprec <= LONG_TYPE_SIZE)
400 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
94f548c2 401 else if (resprec <= LONG_LONG_TYPE_SIZE)
2921157d 402 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
3cf04d1a
MM
403 else if (resprec >= argprec)
404 fn = builtin_decl_for_precision (BUILT_IN_ROUND, argprec);
94f548c2 405 else
6715d47b 406 gcc_unreachable ();
94f548c2 407
9164caf2
HA
408 return convert (restype, build_call_expr_loc (input_location,
409 fn, 1, arg));
6de9cd9a
DN
410}
411
412
413/* Convert a real to an integer using a specific rounding mode.
414 Ideally we would just build the corresponding GENERIC node,
415 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
416
417static tree
e743d142 418build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
f9f770a8 419 enum rounding_mode op)
6de9cd9a
DN
420{
421 switch (op)
422 {
f9f770a8 423 case RND_FLOOR:
6de9cd9a 424 return build_fixbound_expr (pblock, arg, type, 0);
6de9cd9a 425
f9f770a8 426 case RND_CEIL:
6de9cd9a 427 return build_fixbound_expr (pblock, arg, type, 1);
6de9cd9a 428
f9f770a8 429 case RND_ROUND:
94f548c2 430 return build_round_expr (arg, type);
6de9cd9a 431
94f548c2 432 case RND_TRUNC:
433ce291 433 return fold_build1_loc (input_location, FIX_TRUNC_EXPR, type, arg);
94f548c2
FXC
434
435 default:
436 gcc_unreachable ();
6de9cd9a
DN
437 }
438}
439
440
441/* Round a real value using the specified rounding mode.
442 We use a temporary integer of that same kind size as the result.
e743d142 443 Values larger than those that can be represented by this kind are
e2ae1407 444 unchanged, as they will not be accurate enough to represent the
e743d142 445 rounding.
6de9cd9a
DN
446 huge = HUGE (KIND (a))
447 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
448 */
449
450static void
f9f770a8 451gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
6de9cd9a
DN
452{
453 tree type;
454 tree itype;
74687efe 455 tree arg[2];
6de9cd9a
DN
456 tree tmp;
457 tree cond;
2921157d 458 tree decl;
f8e566e5 459 mpfr_t huge;
74687efe 460 int n, nargs;
6de9cd9a
DN
461 int kind;
462
463 kind = expr->ts.kind;
36d9e52f 464 nargs = gfc_intrinsic_argument_list_length (expr);
6de9cd9a 465
2921157d 466 decl = NULL_TREE;
6de9cd9a
DN
467 /* We have builtin functions for some cases. */
468 switch (op)
469 {
f9f770a8 470 case RND_ROUND:
166d08bd 471 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
6de9cd9a
DN
472 break;
473
f9f770a8 474 case RND_TRUNC:
166d08bd 475 decl = gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
e743d142
TS
476 break;
477
478 default:
479 gcc_unreachable ();
6de9cd9a
DN
480 }
481
482 /* Evaluate the argument. */
6e45f57b 483 gcc_assert (expr->value.function.actual->expr);
74687efe 484 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
6de9cd9a
DN
485
486 /* Use a builtin function if one exists. */
2921157d 487 if (decl != NULL_TREE)
6de9cd9a 488 {
2921157d 489 se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
6de9cd9a
DN
490 return;
491 }
492
493 /* This code is probably redundant, but we'll keep it lying around just
494 in case. */
495 type = gfc_typenode_for_spec (&expr->ts);
74687efe 496 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
6de9cd9a
DN
497
498 /* Test if the value is too large to handle sensibly. */
f8e566e5
SK
499 gfc_set_model_kind (kind);
500 mpfr_init (huge);
e7a2d5fb 501 n = gfc_validate_kind (BT_INTEGER, kind, false);
f8e566e5 502 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
346a77d1 503 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
63ee5404 504 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, arg[0],
433ce291 505 tmp);
6de9cd9a 506
f8e566e5 507 mpfr_neg (huge, huge, GFC_RND_MODE);
346a77d1 508 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
63ee5404 509 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, arg[0],
433ce291 510 tmp);
63ee5404 511 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node,
433ce291 512 cond, tmp);
6de9cd9a
DN
513 itype = gfc_get_int_type (kind);
514
74687efe 515 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
6de9cd9a 516 tmp = convert (type, tmp);
433ce291
TB
517 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
518 arg[0]);
f8e566e5 519 mpfr_clear (huge);
6de9cd9a
DN
520}
521
522
523/* Convert to an integer using the specified rounding mode. */
524
525static void
f9f770a8 526gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
6de9cd9a
DN
527{
528 tree type;
ffd82975
LM
529 tree *args;
530 int nargs;
6de9cd9a 531
ffd82975 532 nargs = gfc_intrinsic_argument_list_length (expr);
1145e690 533 args = XALLOCAVEC (tree, nargs);
ffd82975 534
029b2d55 535 /* Evaluate the argument, we process all arguments even though we only
ffd82975 536 use the first one for code generation purposes. */
6de9cd9a 537 type = gfc_typenode_for_spec (&expr->ts);
6e45f57b 538 gcc_assert (expr->value.function.actual->expr);
ffd82975 539 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6de9cd9a 540
ffd82975 541 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
6de9cd9a
DN
542 {
543 /* Conversion to a different integer kind. */
ffd82975 544 se->expr = convert (type, args[0]);
6de9cd9a
DN
545 }
546 else
547 {
548 /* Conversion from complex to non-complex involves taking the real
549 component of the value. */
ffd82975 550 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
6de9cd9a
DN
551 && expr->ts.type != BT_COMPLEX)
552 {
553 tree artype;
554
ffd82975 555 artype = TREE_TYPE (TREE_TYPE (args[0]));
433ce291
TB
556 args[0] = fold_build1_loc (input_location, REALPART_EXPR, artype,
557 args[0]);
6de9cd9a
DN
558 }
559
ffd82975 560 se->expr = build_fix_expr (&se->pre, args[0], type, op);
6de9cd9a
DN
561 }
562}
563
564
565/* Get the imaginary component of a value. */
566
567static void
568gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
569{
570 tree arg;
571
55637e51 572 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
433ce291
TB
573 se->expr = fold_build1_loc (input_location, IMAGPART_EXPR,
574 TREE_TYPE (TREE_TYPE (arg)), arg);
6de9cd9a
DN
575}
576
577
578/* Get the complex conjugate of a value. */
579
580static void
581gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
582{
583 tree arg;
584
55637e51 585 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
433ce291 586 se->expr = fold_build1_loc (input_location, CONJ_EXPR, TREE_TYPE (arg), arg);
6de9cd9a
DN
587}
588
589
a3c85b74
FXC
590
591static tree
592define_quad_builtin (const char *name, tree type, bool is_const)
593{
594 tree fndecl;
595 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
596 type);
597
598 /* Mark the decl as external. */
599 DECL_EXTERNAL (fndecl) = 1;
600 TREE_PUBLIC (fndecl) = 1;
601
602 /* Mark it __attribute__((const)). */
603 TREE_READONLY (fndecl) = is_const;
604
605 rest_of_decl_compilation (fndecl, 1, 0);
606
607 return fndecl;
608}
609
facf0354
ML
610/* Add SIMD attribute for FNDECL built-in if the built-in
611 name is in VECTORIZED_BUILTINS. */
a3c85b74 612
facf0354
ML
613static void
614add_simd_flag_for_built_in (tree fndecl)
615{
616 if (gfc_vectorized_builtins == NULL
617 || fndecl == NULL_TREE)
618 return;
619
620 const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
621 int *clauses = gfc_vectorized_builtins->get (name);
622 if (clauses)
623 {
624 for (unsigned i = 0; i < 3; i++)
625 if (*clauses & (1 << i))
626 {
627 gfc_simd_clause simd_type = (gfc_simd_clause)*clauses;
628 tree omp_clause = NULL_TREE;
629 if (simd_type == SIMD_NONE)
630 ; /* No SIMD clause. */
631 else
632 {
633 omp_clause_code code
634 = (simd_type == SIMD_INBRANCH
635 ? OMP_CLAUSE_INBRANCH : OMP_CLAUSE_NOTINBRANCH);
636 omp_clause = build_omp_clause (UNKNOWN_LOCATION, code);
637 omp_clause = build_tree_list (NULL_TREE, omp_clause);
638 }
639
640 DECL_ATTRIBUTES (fndecl)
641 = tree_cons (get_identifier ("omp declare simd"), omp_clause,
642 DECL_ATTRIBUTES (fndecl));
643 }
644 }
645}
646
647 /* Set SIMD attribute to all built-in functions that are mentioned
648 in gfc_vectorized_builtins vector. */
649
650void
651gfc_adjust_builtins (void)
652{
653 gfc_intrinsic_map_t *m;
654 for (m = gfc_intrinsic_map;
655 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
656 {
657 add_simd_flag_for_built_in (m->real4_decl);
658 add_simd_flag_for_built_in (m->complex4_decl);
659 add_simd_flag_for_built_in (m->real8_decl);
660 add_simd_flag_for_built_in (m->complex8_decl);
661 add_simd_flag_for_built_in (m->real10_decl);
662 add_simd_flag_for_built_in (m->complex10_decl);
663 add_simd_flag_for_built_in (m->real16_decl);
664 add_simd_flag_for_built_in (m->complex16_decl);
665 add_simd_flag_for_built_in (m->real16_decl);
666 add_simd_flag_for_built_in (m->complex16_decl);
667 }
668
669 /* Release all strings. */
670 if (gfc_vectorized_builtins != NULL)
671 {
672 for (hash_map<nofree_string_hash, int>::iterator it
673 = gfc_vectorized_builtins->begin ();
674 it != gfc_vectorized_builtins->end (); ++it)
675 free (CONST_CAST (char *, (*it).first));
676
677 delete gfc_vectorized_builtins;
678 gfc_vectorized_builtins = NULL;
679 }
680}
a3c85b74 681
6de9cd9a
DN
682/* Initialize function decls for library functions. The external functions
683 are created as required. Builtin functions are added here. */
684
685void
686gfc_build_intrinsic_lib_fndecls (void)
687{
688 gfc_intrinsic_map_t *m;
eacbdaaa 689 tree quad_decls[END_BUILTINS + 1];
a3c85b74
FXC
690
691 if (gfc_real16_is_float128)
692 {
693 /* If we have soft-float types, we create the decls for their
00b1324f 694 C99-like library functions. For now, we only handle _Float128
133d0d42 695 q-suffixed or IEC 60559 f128-suffixed functions. */
a3c85b74 696
a4437d18 697 tree type, complex_type, func_1, func_2, func_cabs, func_frexp;
6715d47b 698 tree func_iround, func_lround, func_llround, func_scalbn, func_cpow;
a3c85b74 699
eacbdaaa 700 memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
a3c85b74 701
c65699ef
JM
702 type = gfc_float128_type_node;
703 complex_type = gfc_complex_float128_type_node;
a3c85b74 704 /* type (*) (type) */
a4437d18 705 func_1 = build_function_type_list (type, type, NULL_TREE);
6715d47b
JB
706 /* int (*) (type) */
707 func_iround = build_function_type_list (integer_type_node,
708 type, NULL_TREE);
a3c85b74 709 /* long (*) (type) */
a4437d18
NF
710 func_lround = build_function_type_list (long_integer_type_node,
711 type, NULL_TREE);
a3c85b74 712 /* long long (*) (type) */
a4437d18
NF
713 func_llround = build_function_type_list (long_long_integer_type_node,
714 type, NULL_TREE);
a3c85b74 715 /* type (*) (type, type) */
a4437d18 716 func_2 = build_function_type_list (type, type, type, NULL_TREE);
a3c85b74 717 /* type (*) (type, &int) */
a4437d18
NF
718 func_frexp
719 = build_function_type_list (type,
720 type,
721 build_pointer_type (integer_type_node),
722 NULL_TREE);
a3c85b74 723 /* type (*) (type, int) */
a4437d18
NF
724 func_scalbn = build_function_type_list (type,
725 type, integer_type_node, NULL_TREE);
a3c85b74 726 /* type (*) (complex type) */
a4437d18 727 func_cabs = build_function_type_list (type, complex_type, NULL_TREE);
166d08bd 728 /* complex type (*) (complex type, complex type) */
a4437d18
NF
729 func_cpow
730 = build_function_type_list (complex_type,
731 complex_type, complex_type, NULL_TREE);
a3c85b74
FXC
732
733#define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
734#define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
735#define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
736
737 /* Only these built-ins are actually needed here. These are used directly
738 from the code, when calling builtin_decl_for_precision() or
739 builtin_decl_for_float_type(). The others are all constructed by
740 gfc_get_intrinsic_lib_fndecl(). */
741#define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
133d0d42
JJ
742 quad_decls[BUILT_IN_ ## ID] \
743 = define_quad_builtin (gfc_real16_use_iec_60559 \
744 ? NAME "f128" : NAME "q", func_ ## TYPE, \
745 CONST);
a3c85b74
FXC
746
747#include "mathbuiltins.def"
748
749#undef OTHER_BUILTIN
750#undef LIB_FUNCTION
751#undef DEFINE_MATH_BUILTIN
752#undef DEFINE_MATH_BUILTIN_C
753
8c07a5f4
FXC
754 /* There is one built-in we defined manually, because it gets called
755 with builtin_decl_for_precision() or builtin_decl_for_float_type()
756 even though it is not an OTHER_BUILTIN: it is SQRT. */
133d0d42
JJ
757 quad_decls[BUILT_IN_SQRT]
758 = define_quad_builtin (gfc_real16_use_iec_60559
759 ? "sqrtf128" : "sqrtq", func_1, true);
a3c85b74 760 }
6de9cd9a
DN
761
762 /* Add GCC builtin functions. */
2921157d
FXC
763 for (m = gfc_intrinsic_map;
764 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
765 {
766 if (m->float_built_in != END_BUILTINS)
e79983f4 767 m->real4_decl = builtin_decl_explicit (m->float_built_in);
2921157d 768 if (m->complex_float_built_in != END_BUILTINS)
e79983f4 769 m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
2921157d 770 if (m->double_built_in != END_BUILTINS)
e79983f4 771 m->real8_decl = builtin_decl_explicit (m->double_built_in);
2921157d 772 if (m->complex_double_built_in != END_BUILTINS)
e79983f4 773 m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
2921157d
FXC
774
775 /* If real(kind=10) exists, it is always long double. */
776 if (m->long_double_built_in != END_BUILTINS)
e79983f4 777 m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
2921157d 778 if (m->complex_long_double_built_in != END_BUILTINS)
e79983f4
MM
779 m->complex10_decl
780 = builtin_decl_explicit (m->complex_long_double_built_in);
2921157d 781
a3c85b74
FXC
782 if (!gfc_real16_is_float128)
783 {
784 if (m->long_double_built_in != END_BUILTINS)
e79983f4 785 m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
a3c85b74 786 if (m->complex_long_double_built_in != END_BUILTINS)
e79983f4
MM
787 m->complex16_decl
788 = builtin_decl_explicit (m->complex_long_double_built_in);
a3c85b74
FXC
789 }
790 else if (quad_decls[m->double_built_in] != NULL_TREE)
791 {
792 /* Quad-precision function calls are constructed when first
793 needed by builtin_decl_for_precision(), except for those
794 that will be used directly (define by OTHER_BUILTIN). */
795 m->real16_decl = quad_decls[m->double_built_in];
796 }
797 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
798 {
799 /* Same thing for the complex ones. */
800 m->complex16_decl = quad_decls[m->double_built_in];
a3c85b74 801 }
6de9cd9a
DN
802 }
803}
804
805
806/* Create a fndecl for a simple intrinsic library function. */
807
808static tree
809gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
810{
811 tree type;
9771b263 812 vec<tree, va_gc> *argtypes;
6de9cd9a
DN
813 tree fndecl;
814 gfc_actual_arglist *actual;
815 tree *pdecl;
816 gfc_typespec *ts;
817 char name[GFC_MAX_SYMBOL_LEN + 3];
818
819 ts = &expr->ts;
820 if (ts->type == BT_REAL)
821 {
822 switch (ts->kind)
823 {
824 case 4:
825 pdecl = &m->real4_decl;
826 break;
827 case 8:
828 pdecl = &m->real8_decl;
829 break;
644cb69f
FXC
830 case 10:
831 pdecl = &m->real10_decl;
832 break;
833 case 16:
834 pdecl = &m->real16_decl;
835 break;
6de9cd9a 836 default:
6e45f57b 837 gcc_unreachable ();
6de9cd9a
DN
838 }
839 }
840 else if (ts->type == BT_COMPLEX)
841 {
6e45f57b 842 gcc_assert (m->complex_available);
6de9cd9a
DN
843
844 switch (ts->kind)
845 {
846 case 4:
847 pdecl = &m->complex4_decl;
848 break;
849 case 8:
850 pdecl = &m->complex8_decl;
851 break;
644cb69f
FXC
852 case 10:
853 pdecl = &m->complex10_decl;
854 break;
855 case 16:
856 pdecl = &m->complex16_decl;
857 break;
6de9cd9a 858 default:
6e45f57b 859 gcc_unreachable ();
6de9cd9a
DN
860 }
861 }
862 else
6e45f57b 863 gcc_unreachable ();
6de9cd9a
DN
864
865 if (*pdecl)
866 return *pdecl;
867
868 if (m->libm_name)
869 {
2921157d
FXC
870 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
871 if (gfc_real_kinds[n].c_float)
e48d66a9 872 snprintf (name, sizeof (name), "%s%s%s",
2921157d
FXC
873 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
874 else if (gfc_real_kinds[n].c_double)
e48d66a9 875 snprintf (name, sizeof (name), "%s%s",
2921157d
FXC
876 ts->type == BT_COMPLEX ? "c" : "", m->name);
877 else if (gfc_real_kinds[n].c_long_double)
878 snprintf (name, sizeof (name), "%s%s%s",
879 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
a3c85b74
FXC
880 else if (gfc_real_kinds[n].c_float128)
881 snprintf (name, sizeof (name), "%s%s%s",
133d0d42
JJ
882 ts->type == BT_COMPLEX ? "c" : "", m->name,
883 gfc_real_kinds[n].use_iec_60559 ? "f128" : "q");
e48d66a9 884 else
2921157d 885 gcc_unreachable ();
6de9cd9a
DN
886 }
887 else
888 {
889 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
890 ts->type == BT_COMPLEX ? 'c' : 'r',
5db042b2 891 gfc_type_abi_kind (ts));
6de9cd9a
DN
892 }
893
6c32445b 894 argtypes = NULL;
6de9cd9a
DN
895 for (actual = expr->value.function.actual; actual; actual = actual->next)
896 {
897 type = gfc_typenode_for_spec (&actual->expr->ts);
9771b263 898 vec_safe_push (argtypes, type);
6de9cd9a 899 }
6c32445b 900 type = build_function_type_vec (gfc_typenode_for_spec (ts), argtypes);
c2255bc4
AH
901 fndecl = build_decl (input_location,
902 FUNCTION_DECL, get_identifier (name), type);
6de9cd9a
DN
903
904 /* Mark the decl as external. */
905 DECL_EXTERNAL (fndecl) = 1;
906 TREE_PUBLIC (fndecl) = 1;
907
908 /* Mark it __attribute__((const)), if possible. */
909 TREE_READONLY (fndecl) = m->is_constant;
910
0e6df31e 911 rest_of_decl_compilation (fndecl, 1, 0);
6de9cd9a
DN
912
913 (*pdecl) = fndecl;
914 return fndecl;
915}
916
917
918/* Convert an intrinsic function into an external or builtin call. */
919
920static void
921gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
922{
923 gfc_intrinsic_map_t *m;
6de9cd9a 924 tree fndecl;
55637e51
LM
925 tree rettype;
926 tree *args;
927 unsigned int num_args;
cd5ecab6 928 gfc_isym_id id;
6de9cd9a 929
cd5ecab6 930 id = expr->value.function.isym->id;
6de9cd9a 931 /* Find the entry for this function. */
2921157d
FXC
932 for (m = gfc_intrinsic_map;
933 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
6de9cd9a
DN
934 {
935 if (id == m->id)
936 break;
937 }
938
939 if (m->id == GFC_ISYM_NONE)
940 {
17d5d49f
TB
941 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
942 expr->value.function.name, id);
6de9cd9a
DN
943 }
944
945 /* Get the decl and generate the call. */
55637e51 946 num_args = gfc_intrinsic_argument_list_length (expr);
1145e690 947 args = XALLOCAVEC (tree, num_args);
55637e51
LM
948
949 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6de9cd9a 950 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
55637e51
LM
951 rettype = TREE_TYPE (TREE_TYPE (fndecl));
952
aa00059c 953 fndecl = build_addr (fndecl);
db3927fb 954 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
6de9cd9a
DN
955}
956
8c13133c
DK
957
958/* If bounds-checking is enabled, create code to verify at runtime that the
959 string lengths for both expressions are the same (needed for e.g. MERGE).
960 If bounds-checking is not enabled, does nothing. */
961
fb5bc08b
DK
962void
963gfc_trans_same_strlen_check (const char* intr_name, locus* where,
964 tree a, tree b, stmtblock_t* target)
8c13133c
DK
965{
966 tree cond;
967 tree name;
968
969 /* If bounds-checking is disabled, do nothing. */
d3d3011f 970 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
8c13133c
DK
971 return;
972
973 /* Compare the two string lengths. */
63ee5404 974 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, a, b);
8c13133c
DK
975
976 /* Output the runtime-check. */
977 name = gfc_build_cstring_const (intr_name);
978 name = gfc_build_addr_expr (pchar_type_node, name);
979 gfc_trans_runtime_check (true, false, cond, target, where,
fb5bc08b 980 "Unequal character lengths (%ld/%ld) in %s",
8c13133c
DK
981 fold_convert (long_integer_type_node, a),
982 fold_convert (long_integer_type_node, b), name);
983}
984
985
565fad70 986/* The EXPONENT(X) intrinsic function is translated into
b5a4419c 987 int ret;
565fad70
FXC
988 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
989 so that if X is a NaN or infinity, the result is HUGE(0).
b5a4419c 990 */
6de9cd9a
DN
991
992static void
14b1261a 993gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
6de9cd9a 994{
565fad70
FXC
995 tree arg, type, res, tmp, frexp, cond, huge;
996 int i;
6de9cd9a 997
166d08bd 998 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP,
2921157d 999 expr->value.function.actual->expr->ts.kind);
6de9cd9a 1000
b5a4419c 1001 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
565fad70
FXC
1002 arg = gfc_evaluate_now (arg, &se->pre);
1003
1004 i = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
1005 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_c_int_kind);
1006 cond = build_call_expr_loc (input_location,
1007 builtin_decl_explicit (BUILT_IN_ISFINITE),
1008 1, arg);
b5a4419c
FXC
1009
1010 res = gfc_create_var (integer_type_node, NULL);
2921157d
FXC
1011 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
1012 gfc_build_addr_expr (NULL_TREE, res));
565fad70
FXC
1013 tmp = fold_build2_loc (input_location, COMPOUND_EXPR, integer_type_node,
1014 tmp, res);
1015 se->expr = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
1016 cond, tmp, huge);
b5a4419c 1017
14b1261a 1018 type = gfc_typenode_for_spec (&expr->ts);
565fad70 1019 se->expr = fold_convert (type, se->expr);
6de9cd9a
DN
1020}
1021
5af07930 1022
b5116268
TB
1023/* Fill in the following structure
1024 struct caf_vector_t {
1025 size_t nvec; // size of the vector
1026 union {
1027 struct {
1028 void *vector;
1029 int kind;
1030 } v;
1031 struct {
1032 ptrdiff_t lower_bound;
1033 ptrdiff_t upper_bound;
1034 ptrdiff_t stride;
1035 } triplet;
1036 } u;
1037 } */
1038
1039static void
1040conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
1041 tree lower, tree upper, tree stride,
1042 tree vector, int kind, tree nvec)
1043{
1044 tree field, type, tmp;
1045
1046 desc = gfc_build_array_ref (desc, gfc_rank_cst[i], NULL_TREE);
1047 type = TREE_TYPE (desc);
1048
1049 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1050 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1051 desc, field, NULL_TREE);
1052 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), nvec));
1053
1054 /* Access union. */
1055 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1056 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1057 desc, field, NULL_TREE);
1058 type = TREE_TYPE (desc);
1059
1060 /* Access the inner struct. */
1061 field = gfc_advance_chain (TYPE_FIELDS (type), vector != NULL_TREE ? 0 : 1);
1062 desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1063 desc, field, NULL_TREE);
1064 type = TREE_TYPE (desc);
1065
1066 if (vector != NULL_TREE)
1067 {
3c9f5092 1068 /* Set vector and kind. */
b5116268
TB
1069 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1070 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1071 desc, field, NULL_TREE);
1072 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), vector));
1073 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1074 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1075 desc, field, NULL_TREE);
1076 gfc_add_modify (block, tmp, build_int_cst (integer_type_node, kind));
1077 }
1078 else
1079 {
3c9f5092 1080 /* Set dim.lower/upper/stride. */
b5116268
TB
1081 field = gfc_advance_chain (TYPE_FIELDS (type), 0);
1082 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1083 desc, field, NULL_TREE);
1084 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), lower));
1085
1086 field = gfc_advance_chain (TYPE_FIELDS (type), 1);
1087 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1088 desc, field, NULL_TREE);
1089 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), upper));
1090
1091 field = gfc_advance_chain (TYPE_FIELDS (type), 2);
1092 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1093 desc, field, NULL_TREE);
1094 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field), stride));
1095 }
1096}
1097
1098
1099static tree
1100conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
1101{
1102 gfc_se argse;
1103 tree var, lower, upper = NULL_TREE, stride = NULL_TREE, vector, nvec;
1104 tree lbound, ubound, tmp;
1105 int i;
1106
1107 var = gfc_create_var (gfc_get_caf_vector_type (ar->dimen), "vector");
1108
1109 for (i = 0; i < ar->dimen; i++)
1110 switch (ar->dimen_type[i])
1111 {
1112 case DIMEN_RANGE:
1113 if (ar->end[i])
1114 {
1115 gfc_init_se (&argse, NULL);
1116 gfc_conv_expr (&argse, ar->end[i]);
1117 gfc_add_block_to_block (block, &argse.pre);
1118 upper = gfc_evaluate_now (argse.expr, block);
1119 }
1120 else
1121 upper = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1122 if (ar->stride[i])
1123 {
1124 gfc_init_se (&argse, NULL);
1125 gfc_conv_expr (&argse, ar->stride[i]);
1126 gfc_add_block_to_block (block, &argse.pre);
1127 stride = gfc_evaluate_now (argse.expr, block);
1128 }
1129 else
1130 stride = gfc_index_one_node;
1131
1132 /* Fall through. */
1133 case DIMEN_ELEMENT:
1134 if (ar->start[i])
1135 {
1136 gfc_init_se (&argse, NULL);
1137 gfc_conv_expr (&argse, ar->start[i]);
1138 gfc_add_block_to_block (block, &argse.pre);
1139 lower = gfc_evaluate_now (argse.expr, block);
1140 }
1141 else
1142 lower = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1143 if (ar->dimen_type[i] == DIMEN_ELEMENT)
1144 {
1145 upper = lower;
1146 stride = gfc_index_one_node;
1147 }
1148 vector = NULL_TREE;
1149 nvec = size_zero_node;
1150 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1151 vector, 0, nvec);
1152 break;
1153
1154 case DIMEN_VECTOR:
1155 gfc_init_se (&argse, NULL);
1156 argse.descriptor_only = 1;
1157 gfc_conv_expr_descriptor (&argse, ar->start[i]);
1158 gfc_add_block_to_block (block, &argse.pre);
1159 vector = argse.expr;
1160 lbound = gfc_conv_descriptor_lbound_get (vector, gfc_rank_cst[0]);
1161 ubound = gfc_conv_descriptor_ubound_get (vector, gfc_rank_cst[0]);
1162 nvec = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1163 tmp = gfc_conv_descriptor_stride_get (vector, gfc_rank_cst[0]);
1164 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1165 TREE_TYPE (nvec), nvec, tmp);
1166 lower = gfc_index_zero_node;
1167 upper = gfc_index_zero_node;
1168 stride = gfc_index_zero_node;
1169 vector = gfc_conv_descriptor_data_get (vector);
1170 conv_caf_vector_subscript_elem (block, i, var, lower, upper, stride,
1171 vector, ar->start[i]->ts.kind, nvec);
1172 break;
1173 default:
1174 gcc_unreachable();
1175 }
1176 return gfc_build_addr_expr (NULL_TREE, var);
1177}
1178
1179
3c9f5092
AV
1180static tree
1181compute_component_offset (tree field, tree type)
1182{
1183 tree tmp;
1184 if (DECL_FIELD_BIT_OFFSET (field) != NULL_TREE
1185 && !integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
1186 {
1187 tmp = fold_build2 (TRUNC_DIV_EXPR, type,
1188 DECL_FIELD_BIT_OFFSET (field),
1189 bitsize_unit_node);
1190 return fold_build2 (PLUS_EXPR, type, DECL_FIELD_OFFSET (field), tmp);
1191 }
1192 else
1193 return DECL_FIELD_OFFSET (field);
1194}
1195
1196
1197static tree
1198conv_expr_ref_to_caf_ref (stmtblock_t *block, gfc_expr *expr)
1199{
26f391e8 1200 gfc_ref *ref = expr->ref, *last_comp_ref;
3c9f5092
AV
1201 tree caf_ref = NULL_TREE, prev_caf_ref = NULL_TREE, reference_type, tmp, tmp2,
1202 field, last_type, inner_struct, mode, mode_rhs, dim_array, dim, dim_type,
1203 start, end, stride, vector, nvec;
1204 gfc_se se;
1205 bool ref_static_array = false;
1206 tree last_component_ref_tree = NULL_TREE;
1207 int i, last_type_n;
1208
1209 if (expr->symtree)
1210 {
1211 last_component_ref_tree = expr->symtree->n.sym->backend_decl;
de91486c
AV
1212 ref_static_array = !expr->symtree->n.sym->attr.allocatable
1213 && !expr->symtree->n.sym->attr.pointer;
3c9f5092
AV
1214 }
1215
1216 /* Prevent uninit-warning. */
1217 reference_type = NULL_TREE;
26f391e8
AV
1218
1219 /* Skip refs upto the first coarray-ref. */
1220 last_comp_ref = NULL;
1221 while (ref && (ref->type != REF_ARRAY || ref->u.ar.codimen == 0))
1222 {
1223 /* Remember the type of components skipped. */
1224 if (ref->type == REF_COMPONENT)
1225 last_comp_ref = ref;
1226 ref = ref->next;
1227 }
1228 /* When a component was skipped, get the type information of the last
1229 component ref, else get the type from the symbol. */
1230 if (last_comp_ref)
1231 {
1232 last_type = gfc_typenode_for_spec (&last_comp_ref->u.c.component->ts);
1233 last_type_n = last_comp_ref->u.c.component->ts.type;
1234 }
1235 else
1236 {
1237 last_type = gfc_typenode_for_spec (&expr->symtree->n.sym->ts);
1238 last_type_n = expr->symtree->n.sym->ts.type;
1239 }
1240
3c9f5092
AV
1241 while (ref)
1242 {
1243 if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0
1244 && ref->u.ar.dimen == 0)
1245 {
1246 /* Skip pure coindexes. */
1247 ref = ref->next;
1248 continue;
1249 }
1250 tmp = gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
1251 reference_type = TREE_TYPE (tmp);
1252
1253 if (caf_ref == NULL_TREE)
1254 caf_ref = tmp;
1255
1256 /* Construct the chain of refs. */
1257 if (prev_caf_ref != NULL_TREE)
1258 {
1259 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1260 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1261 TREE_TYPE (field), prev_caf_ref, field,
1262 NULL_TREE);
1263 gfc_add_modify (block, tmp2, gfc_build_addr_expr (TREE_TYPE (field),
1264 tmp));
1265 }
1266 prev_caf_ref = tmp;
1267
1268 switch (ref->type)
1269 {
1270 case REF_COMPONENT:
1271 last_type = gfc_typenode_for_spec (&ref->u.c.component->ts);
1272 last_type_n = ref->u.c.component->ts.type;
1273 /* Set the type of the ref. */
1274 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1275 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1276 TREE_TYPE (field), prev_caf_ref, field,
1277 NULL_TREE);
1278 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1279 GFC_CAF_REF_COMPONENT));
1280
1281 /* Ref the c in union u. */
1282 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1283 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1284 TREE_TYPE (field), prev_caf_ref, field,
1285 NULL_TREE);
1286 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 0);
1287 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1288 TREE_TYPE (field), tmp, field,
1289 NULL_TREE);
1290
1291 /* Set the offset. */
1292 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1293 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1294 TREE_TYPE (field), inner_struct, field,
1295 NULL_TREE);
1296 /* Computing the offset is somewhat harder. The bit_offset has to be
1297 taken into account. When the bit_offset in the field_decl is non-
1298 null, divide it by the bitsize_unit and add it to the regular
1299 offset. */
1300 tmp2 = compute_component_offset (ref->u.c.component->backend_decl,
1301 TREE_TYPE (tmp));
1302 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1303
1304 /* Set caf_token_offset. */
1305 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 1);
1306 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1307 TREE_TYPE (field), inner_struct, field,
1308 NULL_TREE);
de91486c
AV
1309 if ((ref->u.c.component->attr.allocatable
1310 || ref->u.c.component->attr.pointer)
3c9f5092
AV
1311 && ref->u.c.component->attr.dimension)
1312 {
1313 tree arr_desc_token_offset;
ff3598bc
PT
1314 /* Get the token field from the descriptor. */
1315 arr_desc_token_offset = TREE_OPERAND (
1316 gfc_conv_descriptor_token (ref->u.c.component->backend_decl), 1);
3c9f5092
AV
1317 arr_desc_token_offset
1318 = compute_component_offset (arr_desc_token_offset,
1319 TREE_TYPE (tmp));
1320 tmp2 = fold_build2_loc (input_location, PLUS_EXPR,
1321 TREE_TYPE (tmp2), tmp2,
1322 arr_desc_token_offset);
1323 }
1324 else if (ref->u.c.component->caf_token)
1325 tmp2 = compute_component_offset (ref->u.c.component->caf_token,
1326 TREE_TYPE (tmp));
1327 else
1328 tmp2 = integer_zero_node;
1329 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
1330
1331 /* Remember whether this ref was to a non-allocatable/non-pointer
1332 component so the next array ref can be tailored correctly. */
de91486c
AV
1333 ref_static_array = !ref->u.c.component->attr.allocatable
1334 && !ref->u.c.component->attr.pointer;
3c9f5092
AV
1335 last_component_ref_tree = ref_static_array
1336 ? ref->u.c.component->backend_decl : NULL_TREE;
1337 break;
1338 case REF_ARRAY:
1339 if (ref_static_array && ref->u.ar.as->type == AS_DEFERRED)
1340 ref_static_array = false;
1341 /* Set the type of the ref. */
1342 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
1343 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1344 TREE_TYPE (field), prev_caf_ref, field,
1345 NULL_TREE);
1346 gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
1347 ref_static_array
1348 ? GFC_CAF_REF_STATIC_ARRAY
1349 : GFC_CAF_REF_ARRAY));
1350
1351 /* Ref the a in union u. */
1352 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
1353 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1354 TREE_TYPE (field), prev_caf_ref, field,
1355 NULL_TREE);
1356 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 1);
1357 inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
1358 TREE_TYPE (field), tmp, field,
1359 NULL_TREE);
1360
1361 /* Set the static_array_type in a for static arrays. */
1362 if (ref_static_array)
1363 {
1364 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)),
1365 1);
1366 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1367 TREE_TYPE (field), inner_struct, field,
1368 NULL_TREE);
1369 gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (tmp),
1370 last_type_n));
1371 }
1372 /* Ref the mode in the inner_struct. */
1373 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
1374 mode = fold_build3_loc (input_location, COMPONENT_REF,
1375 TREE_TYPE (field), inner_struct, field,
1376 NULL_TREE);
1377 /* Ref the dim in the inner_struct. */
1378 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 2);
1379 dim_array = fold_build3_loc (input_location, COMPONENT_REF,
1380 TREE_TYPE (field), inner_struct, field,
1381 NULL_TREE);
1382 for (i = 0; i < ref->u.ar.dimen; ++i)
1383 {
1384 /* Ref dim i. */
1385 dim = gfc_build_array_ref (dim_array, gfc_rank_cst[i], NULL_TREE);
1386 dim_type = TREE_TYPE (dim);
1387 mode_rhs = start = end = stride = NULL_TREE;
1388 switch (ref->u.ar.dimen_type[i])
1389 {
1390 case DIMEN_RANGE:
1391 if (ref->u.ar.end[i])
1392 {
1393 gfc_init_se (&se, NULL);
1394 gfc_conv_expr (&se, ref->u.ar.end[i]);
1395 gfc_add_block_to_block (block, &se.pre);
1396 if (ref_static_array)
1397 {
1398 /* Make the index zero-based, when reffing a static
1399 array. */
1400 end = se.expr;
1401 gfc_init_se (&se, NULL);
1402 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1403 gfc_add_block_to_block (block, &se.pre);
1404 se.expr = fold_build2 (MINUS_EXPR,
1405 gfc_array_index_type,
1406 end, fold_convert (
1407 gfc_array_index_type,
1408 se.expr));
1409 }
1410 end = gfc_evaluate_now (fold_convert (
1411 gfc_array_index_type,
1412 se.expr),
1413 block);
1414 }
1415 else if (ref_static_array)
1416 end = fold_build2 (MINUS_EXPR,
1417 gfc_array_index_type,
1418 gfc_conv_array_ubound (
1419 last_component_ref_tree, i),
1420 gfc_conv_array_lbound (
1421 last_component_ref_tree, i));
1422 else
1423 {
1424 end = NULL_TREE;
1425 mode_rhs = build_int_cst (unsigned_char_type_node,
1426 GFC_CAF_ARR_REF_OPEN_END);
1427 }
1428 if (ref->u.ar.stride[i])
1429 {
1430 gfc_init_se (&se, NULL);
1431 gfc_conv_expr (&se, ref->u.ar.stride[i]);
1432 gfc_add_block_to_block (block, &se.pre);
1433 stride = gfc_evaluate_now (fold_convert (
1434 gfc_array_index_type,
1435 se.expr),
1436 block);
1437 if (ref_static_array)
1438 {
1439 /* Make the index zero-based, when reffing a static
1440 array. */
1441 stride = fold_build2 (MULT_EXPR,
1442 gfc_array_index_type,
1443 gfc_conv_array_stride (
1444 last_component_ref_tree,
1445 i),
1446 stride);
1447 gcc_assert (end != NULL_TREE);
1448 /* Multiply with the product of array's stride and
1449 the step of the ref to a virtual upper bound.
67914693 1450 We cannot compute the actual upper bound here or
3c9f5092
AV
1451 the caflib would compute the extend
1452 incorrectly. */
1453 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1454 end, gfc_conv_array_stride (
1455 last_component_ref_tree,
1456 i));
1457 end = gfc_evaluate_now (end, block);
1458 stride = gfc_evaluate_now (stride, block);
1459 }
1460 }
1461 else if (ref_static_array)
1462 {
1463 stride = gfc_conv_array_stride (last_component_ref_tree,
1464 i);
1465 end = fold_build2 (MULT_EXPR, gfc_array_index_type,
1466 end, stride);
1467 end = gfc_evaluate_now (end, block);
1468 }
1469 else
1470 /* Always set a ref stride of one to make caflib's
1471 handling easier. */
1472 stride = gfc_index_one_node;
1473
60590933 1474 /* Fall through. */
3c9f5092
AV
1475 case DIMEN_ELEMENT:
1476 if (ref->u.ar.start[i])
1477 {
1478 gfc_init_se (&se, NULL);
1479 gfc_conv_expr (&se, ref->u.ar.start[i]);
1480 gfc_add_block_to_block (block, &se.pre);
1481 if (ref_static_array)
1482 {
1483 /* Make the index zero-based, when reffing a static
1484 array. */
1485 start = fold_convert (gfc_array_index_type, se.expr);
1486 gfc_init_se (&se, NULL);
1487 gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
1488 gfc_add_block_to_block (block, &se.pre);
1489 se.expr = fold_build2 (MINUS_EXPR,
1490 gfc_array_index_type,
1491 start, fold_convert (
1492 gfc_array_index_type,
1493 se.expr));
1494 /* Multiply with the stride. */
1495 se.expr = fold_build2 (MULT_EXPR,
1496 gfc_array_index_type,
1497 se.expr,
1498 gfc_conv_array_stride (
1499 last_component_ref_tree,
1500 i));
1501 }
1502 start = gfc_evaluate_now (fold_convert (
1503 gfc_array_index_type,
1504 se.expr),
1505 block);
1506 if (mode_rhs == NULL_TREE)
1507 mode_rhs = build_int_cst (unsigned_char_type_node,
1508 ref->u.ar.dimen_type[i]
1509 == DIMEN_ELEMENT
1510 ? GFC_CAF_ARR_REF_SINGLE
1511 : GFC_CAF_ARR_REF_RANGE);
1512 }
1513 else if (ref_static_array)
1514 {
1515 start = integer_zero_node;
1516 mode_rhs = build_int_cst (unsigned_char_type_node,
1517 ref->u.ar.start[i] == NULL
1518 ? GFC_CAF_ARR_REF_FULL
1519 : GFC_CAF_ARR_REF_RANGE);
1520 }
1521 else if (end == NULL_TREE)
1522 mode_rhs = build_int_cst (unsigned_char_type_node,
1523 GFC_CAF_ARR_REF_FULL);
1524 else
1525 mode_rhs = build_int_cst (unsigned_char_type_node,
1526 GFC_CAF_ARR_REF_OPEN_START);
1527
1528 /* Ref the s in dim. */
1529 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 0);
1530 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1531 TREE_TYPE (field), dim, field,
1532 NULL_TREE);
1533
1534 /* Set start in s. */
1535 if (start != NULL_TREE)
1536 {
1537 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1538 0);
1539 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1540 TREE_TYPE (field), tmp, field,
1541 NULL_TREE);
1542 gfc_add_modify (block, tmp2,
1543 fold_convert (TREE_TYPE (tmp2), start));
1544 }
1545
1546 /* Set end in s. */
1547 if (end != NULL_TREE)
1548 {
1549 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1550 1);
1551 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1552 TREE_TYPE (field), tmp, field,
1553 NULL_TREE);
1554 gfc_add_modify (block, tmp2,
1555 fold_convert (TREE_TYPE (tmp2), end));
1556 }
1557
1558 /* Set end in s. */
1559 if (stride != NULL_TREE)
1560 {
1561 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
1562 2);
1563 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1564 TREE_TYPE (field), tmp, field,
1565 NULL_TREE);
1566 gfc_add_modify (block, tmp2,
1567 fold_convert (TREE_TYPE (tmp2), stride));
1568 }
1569 break;
1570 case DIMEN_VECTOR:
1571 /* TODO: In case of static array. */
1572 gcc_assert (!ref_static_array);
1573 mode_rhs = build_int_cst (unsigned_char_type_node,
1574 GFC_CAF_ARR_REF_VECTOR);
1575 gfc_init_se (&se, NULL);
1576 se.descriptor_only = 1;
1577 gfc_conv_expr_descriptor (&se, ref->u.ar.start[i]);
1578 gfc_add_block_to_block (block, &se.pre);
1579 vector = se.expr;
1580 tmp = gfc_conv_descriptor_lbound_get (vector,
1581 gfc_rank_cst[0]);
1582 tmp2 = gfc_conv_descriptor_ubound_get (vector,
1583 gfc_rank_cst[0]);
1584 nvec = gfc_conv_array_extent_dim (tmp, tmp2, NULL);
1585 tmp = gfc_conv_descriptor_stride_get (vector,
1586 gfc_rank_cst[0]);
1587 nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1588 TREE_TYPE (nvec), nvec, tmp);
1589 vector = gfc_conv_descriptor_data_get (vector);
1590
1591 /* Ref the v in dim. */
1592 field = gfc_advance_chain (TYPE_FIELDS (dim_type), 1);
1593 tmp = fold_build3_loc (input_location, COMPONENT_REF,
1594 TREE_TYPE (field), dim, field,
1595 NULL_TREE);
1596
1597 /* Set vector in v. */
1598 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 0);
1599 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1600 TREE_TYPE (field), tmp, field,
1601 NULL_TREE);
1602 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1603 vector));
1604
1605 /* Set nvec in v. */
1606 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 1);
1607 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1608 TREE_TYPE (field), tmp, field,
1609 NULL_TREE);
1610 gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
1611 nvec));
1612
1613 /* Set kind in v. */
1614 field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 2);
1615 tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
1616 TREE_TYPE (field), tmp, field,
1617 NULL_TREE);
1618 gfc_add_modify (block, tmp2, build_int_cst (integer_type_node,
1619 ref->u.ar.start[i]->ts.kind));
1620 break;
1621 default:
1622 gcc_unreachable ();
1623 }
1624 /* Set the mode for dim i. */
1625 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1626 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp),
1627 mode_rhs));
1628 }
1629
1630 /* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
1631 if (i < GFC_MAX_DIMENSIONS)
1632 {
1633 tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
1634 gfc_add_modify (block, tmp,
1635 build_int_cst (unsigned_char_type_node,
1636 GFC_CAF_ARR_REF_NONE));
1637 }
1638 break;
1639 default:
1640 gcc_unreachable ();
1641 }
1642
1643 /* Set the size of the current type. */
1644 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 2);
1645 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1646 prev_caf_ref, field, NULL_TREE);
1647 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1648 TYPE_SIZE_UNIT (last_type)));
1649
1650 ref = ref->next;
1651 }
1652
1653 if (prev_caf_ref != NULL_TREE)
1654 {
1655 field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
1656 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
1657 prev_caf_ref, field, NULL_TREE);
1658 gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
1659 null_pointer_node));
1660 }
1661 return caf_ref != NULL_TREE ? gfc_build_addr_expr (NULL_TREE, caf_ref)
1662 : NULL_TREE;
1663}
1664
b5116268
TB
1665/* Get data from a remote coarray. */
1666
1667static void
93e2e046 1668gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
3c9f5092
AV
1669 tree may_require_tmp, bool may_realloc,
1670 symbol_attribute *caf_attr)
b5116268 1671{
20d0bfce 1672 gfc_expr *array_expr, *tmp_stat;
b5116268
TB
1673 gfc_se argse;
1674 tree caf_decl, token, offset, image_index, tmp;
20d0bfce 1675 tree res_var, dst_var, type, kind, vec, stat;
3c9f5092
AV
1676 tree caf_reference;
1677 symbol_attribute caf_attr_store;
b5116268 1678
f19626cf 1679 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
b5116268
TB
1680
1681 if (se->ss && se->ss->info->useflags)
1682 {
1683 /* Access the previously obtained result. */
1684 gfc_conv_tmp_array_ref (se);
1685 return;
1686 }
1687
1688 /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1689 array_expr = (lhs == NULL_TREE) ? expr->value.function.actual->expr : expr;
1690 type = gfc_typenode_for_spec (&array_expr->ts);
1691
3c9f5092
AV
1692 if (caf_attr == NULL)
1693 {
1694 caf_attr_store = gfc_caf_attr (array_expr);
1695 caf_attr = &caf_attr_store;
1696 }
1697
b5116268
TB
1698 res_var = lhs;
1699 dst_var = lhs;
1700
69859058 1701 vec = null_pointer_node;
4971dd80 1702 tmp_stat = gfc_find_stat_co (expr);
20d0bfce
AF
1703
1704 if (tmp_stat)
1705 {
1706 gfc_se stat_se;
4971dd80 1707 gfc_init_se (&stat_se, NULL);
20d0bfce
AF
1708 gfc_conv_expr_reference (&stat_se, tmp_stat);
1709 stat = stat_se.expr;
1710 gfc_add_block_to_block (&se->pre, &stat_se.pre);
1711 gfc_add_block_to_block (&se->post, &stat_se.post);
1712 }
1713 else
1714 stat = null_pointer_node;
69859058 1715
8ed3eeac
AV
1716 /* Only use the new get_by_ref () where it is necessary. I.e., when the lhs
1717 is reallocatable or the right-hand side has allocatable components. */
de91486c 1718 if (caf_attr->alloc_comp || caf_attr->pointer_comp || may_realloc)
3c9f5092
AV
1719 {
1720 /* Get using caf_get_by_ref. */
1721 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, array_expr);
1722
1723 if (caf_reference != NULL_TREE)
1724 {
1725 if (lhs == NULL_TREE)
1726 {
1727 if (array_expr->ts.type == BT_CHARACTER)
1728 gfc_init_se (&argse, NULL);
1729 if (array_expr->rank == 0)
1730 {
1731 symbol_attribute attr;
1732 gfc_clear_attr (&attr);
1733 if (array_expr->ts.type == BT_CHARACTER)
1734 {
1735 res_var = gfc_conv_string_tmp (se,
1736 build_pointer_type (type),
1737 array_expr->ts.u.cl->backend_decl);
1738 argse.string_length = array_expr->ts.u.cl->backend_decl;
1739 }
1740 else
1741 res_var = gfc_create_var (type, "caf_res");
1742 dst_var = gfc_conv_scalar_to_descriptor (se, res_var, attr);
1743 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1744 }
1745 else
1746 {
1747 /* Create temporary. */
1748 if (array_expr->ts.type == BT_CHARACTER)
1749 gfc_conv_expr_descriptor (&argse, array_expr);
1750 may_realloc = gfc_trans_create_temp_array (&se->pre,
1751 &se->post,
1752 se->ss, type,
1753 NULL_TREE, false,
1754 false, false,
1755 &array_expr->where)
1756 == NULL_TREE;
1757 res_var = se->ss->info->data.array.descriptor;
1758 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1759 if (may_realloc)
1760 {
1761 tmp = gfc_conv_descriptor_data_get (res_var);
1762 tmp = gfc_deallocate_with_status (tmp, NULL_TREE,
1763 NULL_TREE, NULL_TREE,
1764 NULL_TREE, true,
ba85c8c3
AV
1765 NULL,
1766 GFC_CAF_COARRAY_NOCOARRAY);
3c9f5092
AV
1767 gfc_add_expr_to_block (&se->post, tmp);
1768 }
1769 }
1770 }
1771
1772 kind = build_int_cst (integer_type_node, expr->ts.kind);
1773 if (lhs_kind == NULL_TREE)
1774 lhs_kind = kind;
1775
1776 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1777 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1778 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
1779 image_index = gfc_caf_get_image_index (&se->pre, array_expr,
1780 caf_decl);
1781 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
1782 array_expr);
1783
1784 /* No overlap possible as we have generated a temporary. */
1785 if (lhs == NULL_TREE)
1786 may_require_tmp = boolean_false_node;
1787
1788 /* It guarantees memory consistency within the same segment. */
1789 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
1790 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1791 gfc_build_string_const (1, ""), NULL_TREE,
1792 NULL_TREE, tree_cons (NULL_TREE, tmp, NULL_TREE),
1793 NULL_TREE);
1794 ASM_VOLATILE_P (tmp) = 1;
1795 gfc_add_expr_to_block (&se->pre, tmp);
1796
1797 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get_by_ref,
87e8aa3b 1798 10, token, image_index, dst_var,
3c9f5092
AV
1799 caf_reference, lhs_kind, kind,
1800 may_require_tmp,
1801 may_realloc ? boolean_true_node :
1802 boolean_false_node,
87e8aa3b
AV
1803 stat, build_int_cst (integer_type_node,
1804 array_expr->ts.type));
3c9f5092
AV
1805
1806 gfc_add_expr_to_block (&se->pre, tmp);
1807
1808 if (se->ss)
1809 gfc_advance_se_ss_chain (se);
1810
1811 se->expr = res_var;
1812 if (array_expr->ts.type == BT_CHARACTER)
1813 se->string_length = argse.string_length;
1814
1815 return;
1816 }
1817 }
1818
b5116268
TB
1819 gfc_init_se (&argse, NULL);
1820 if (array_expr->rank == 0)
1821 {
1822 symbol_attribute attr;
1823
1824 gfc_clear_attr (&attr);
1825 gfc_conv_expr (&argse, array_expr);
1826
1827 if (lhs == NULL_TREE)
1828 {
1829 gfc_clear_attr (&attr);
1830 if (array_expr->ts.type == BT_CHARACTER)
aa9ca5ca
TB
1831 res_var = gfc_conv_string_tmp (se, build_pointer_type (type),
1832 argse.string_length);
b5116268
TB
1833 else
1834 res_var = gfc_create_var (type, "caf_res");
1835 dst_var = gfc_conv_scalar_to_descriptor (&argse, res_var, attr);
1836 dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
1837 }
1838 argse.expr = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
1839 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1840 }
1841 else
1842 {
1843 /* If has_vector, pass descriptor for whole array and the
1844 vector bounds separately. */
1845 gfc_array_ref *ar, ar2;
1846 bool has_vector = false;
1847
1848 if (gfc_is_coindexed (expr) && gfc_has_vector_subscript (expr))
1849 {
1850 has_vector = true;
1851 ar = gfc_find_array_ref (expr);
1852 ar2 = *ar;
1853 memset (ar, '\0', sizeof (*ar));
1854 ar->as = ar2.as;
1855 ar->type = AR_FULL;
1856 }
ba85c8c3 1857 // TODO: Check whether argse.want_coarray = 1 can help with the below.
b5116268 1858 gfc_conv_expr_descriptor (&argse, array_expr);
d7463e5b 1859 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
3c9f5092 1860 has the wrong type if component references are done. */
d7463e5b 1861 gfc_add_modify (&argse.pre, gfc_conv_descriptor_dtype (argse.expr),
3c9f5092 1862 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
69859058
TB
1863 : array_expr->rank,
1864 type));
b5116268
TB
1865 if (has_vector)
1866 {
69859058 1867 vec = conv_caf_vector_subscript (&argse.pre, argse.expr, &ar2);
b5116268
TB
1868 *ar = ar2;
1869 }
1870
1871 if (lhs == NULL_TREE)
1872 {
1873 /* Create temporary. */
1874 for (int n = 0; n < se->ss->loop->dimen; n++)
1875 if (se->loop->to[n] == NULL_TREE)
1876 {
3c9f5092
AV
1877 se->loop->from[n] = gfc_conv_descriptor_lbound_get (argse.expr,
1878 gfc_rank_cst[n]);
1879 se->loop->to[n] = gfc_conv_descriptor_ubound_get (argse.expr,
1880 gfc_rank_cst[n]);
b5116268
TB
1881 }
1882 gfc_trans_create_temp_array (&argse.pre, &argse.post, se->ss, type,
1883 NULL_TREE, false, true, false,
1884 &array_expr->where);
1885 res_var = se->ss->info->data.array.descriptor;
1886 dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
1887 }
1888 argse.expr = gfc_build_addr_expr (NULL_TREE, argse.expr);
1889 }
1890
1891 kind = build_int_cst (integer_type_node, expr->ts.kind);
1892 if (lhs_kind == NULL_TREE)
1893 lhs_kind = kind;
1894
b5116268
TB
1895 gfc_add_block_to_block (&se->pre, &argse.pre);
1896 gfc_add_block_to_block (&se->post, &argse.post);
1897
1898 caf_decl = gfc_get_tree_for_caf_expr (array_expr);
1899 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
1900 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2c69df3b 1901 image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
3c9f5092
AV
1902 gfc_get_caf_token_offset (se, &token, &offset, caf_decl, argse.expr,
1903 array_expr);
b5116268 1904
93e2e046
TB
1905 /* No overlap possible as we have generated a temporary. */
1906 if (lhs == NULL_TREE)
1907 may_require_tmp = boolean_false_node;
1908
3c9f5092
AV
1909 /* It guarantees memory consistency within the same segment. */
1910 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
985f6c79
TB
1911 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1912 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1913 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1914 ASM_VOLATILE_P (tmp) = 1;
1915 gfc_add_expr_to_block (&se->pre, tmp);
1916
20d0bfce 1917 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 10,
b5116268 1918 token, offset, image_index, argse.expr, vec,
20d0bfce 1919 dst_var, kind, lhs_kind, may_require_tmp, stat);
3c9f5092 1920
b5116268
TB
1921 gfc_add_expr_to_block (&se->pre, tmp);
1922
1923 if (se->ss)
1924 gfc_advance_se_ss_chain (se);
1925
1926 se->expr = res_var;
1927 if (array_expr->ts.type == BT_CHARACTER)
1928 se->string_length = argse.string_length;
1929}
1930
1931
3c9f5092 1932/* Send data to a remote coarray. */
029b2d55 1933
b5116268
TB
1934static tree
1935conv_caf_send (gfc_code *code) {
f8862a1b 1936 gfc_expr *lhs_expr, *rhs_expr, *tmp_stat, *tmp_team;
b5116268
TB
1937 gfc_se lhs_se, rhs_se;
1938 stmtblock_t block;
1939 tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
f8862a1b 1940 tree may_require_tmp, src_stat, dst_stat, dst_team;
5c75088c 1941 tree lhs_type = NULL_TREE;
b5116268 1942 tree vec = null_pointer_node, rhs_vec = null_pointer_node;
3c9f5092 1943 symbol_attribute lhs_caf_attr, rhs_caf_attr;
b5116268 1944
f19626cf 1945 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
b5116268
TB
1946
1947 lhs_expr = code->ext.actual->expr;
1948 rhs_expr = code->ext.actual->next->expr;
8309b221 1949 may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, true) == 0
93e2e046 1950 ? boolean_false_node : boolean_true_node;
b5116268
TB
1951 gfc_init_block (&block);
1952
3c9f5092
AV
1953 lhs_caf_attr = gfc_caf_attr (lhs_expr);
1954 rhs_caf_attr = gfc_caf_attr (rhs_expr);
1955 src_stat = dst_stat = null_pointer_node;
f8862a1b 1956 dst_team = null_pointer_node;
20d0bfce 1957
b5116268
TB
1958 /* LHS. */
1959 gfc_init_se (&lhs_se, NULL);
1960 if (lhs_expr->rank == 0)
1961 {
7c4acac3
AV
1962 if (lhs_expr->ts.type == BT_CHARACTER && lhs_expr->ts.deferred)
1963 {
1964 lhs_se.expr = gfc_get_tree_for_caf_expr (lhs_expr);
1965 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1966 }
1967 else
1968 {
1969 symbol_attribute attr;
1970 gfc_clear_attr (&attr);
1971 gfc_conv_expr (&lhs_se, lhs_expr);
1972 lhs_type = TREE_TYPE (lhs_se.expr);
1973 lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr,
1974 attr);
1975 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
1976 }
b5116268 1977 }
de91486c
AV
1978 else if ((lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
1979 && lhs_caf_attr.codimension)
3c9f5092
AV
1980 {
1981 lhs_se.want_pointer = 1;
1982 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
1983 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1984 has the wrong type if component references are done. */
1985 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
1986 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
1987 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
1988 gfc_get_dtype_rank_type (
1989 gfc_has_vector_subscript (lhs_expr)
1990 ? gfc_find_array_ref (lhs_expr)->dimen
1991 : lhs_expr->rank,
1992 lhs_type));
1993 }
b5116268
TB
1994 else
1995 {
2368eaf9 1996 bool has_vector = gfc_has_vector_subscript (lhs_expr);
b5116268 1997
2368eaf9 1998 if (gfc_is_coindexed (lhs_expr) || !has_vector)
b5116268 1999 {
2368eaf9
AV
2000 /* If has_vector, pass descriptor for whole array and the
2001 vector bounds separately. */
2002 gfc_array_ref *ar, ar2;
2003 bool has_tmp_lhs_array = false;
2004 if (has_vector)
2005 {
2006 has_tmp_lhs_array = true;
2007 ar = gfc_find_array_ref (lhs_expr);
2008 ar2 = *ar;
2009 memset (ar, '\0', sizeof (*ar));
2010 ar->as = ar2.as;
2011 ar->type = AR_FULL;
2012 }
2013 lhs_se.want_pointer = 1;
2014 gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
2015 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but
2016 that has the wrong type if component references are done. */
2017 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2018 tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
2019 gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2020 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2021 : lhs_expr->rank,
2022 lhs_type));
2023 if (has_tmp_lhs_array)
2024 {
2025 vec = conv_caf_vector_subscript (&block, lhs_se.expr, &ar2);
2026 *ar = ar2;
2027 }
b5116268 2028 }
2368eaf9 2029 else
b5116268 2030 {
2368eaf9
AV
2031 /* Special casing for arr1 ([...]) = arr2[...], i.e. caf_get to
2032 indexed array expression. This is rewritten to:
2033
2034 tmp_array = arr2[...]
2035 arr1 ([...]) = tmp_array
2036
2037 because using the standard gfc_conv_expr (lhs_expr) did the
2038 assignment with lhs and rhs exchanged. */
2039
2040 gfc_ss *lss_for_tmparray, *lss_real;
2041 gfc_loopinfo loop;
2042 gfc_se se;
2043 stmtblock_t body;
2044 tree tmparr_desc, src;
2045 tree index = gfc_index_zero_node;
2046 tree stride = gfc_index_zero_node;
2047 int n;
2048
2049 /* Walk both sides of the assignment, once to get the shape of the
2050 temporary array to create right. */
2051 lss_for_tmparray = gfc_walk_expr (lhs_expr);
2052 /* And a second time to be able to create an assignment of the
2053 temporary to the lhs_expr. gfc_trans_create_temp_array replaces
2054 the tree in the descriptor with the one for the temporary
2055 array. */
2056 lss_real = gfc_walk_expr (lhs_expr);
2057 gfc_init_loopinfo (&loop);
2058 gfc_add_ss_to_loop (&loop, lss_for_tmparray);
2059 gfc_add_ss_to_loop (&loop, lss_real);
2060 gfc_conv_ss_startstride (&loop);
2061 gfc_conv_loop_setup (&loop, &lhs_expr->where);
2062 lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
2063 gfc_trans_create_temp_array (&lhs_se.pre, &lhs_se.post,
2064 lss_for_tmparray, lhs_type, NULL_TREE,
2065 false, true, false,
2066 &lhs_expr->where);
2067 tmparr_desc = lss_for_tmparray->info->data.array.descriptor;
2068 gfc_start_scalarized_body (&loop, &body);
2069 gfc_init_se (&se, NULL);
2070 gfc_copy_loopinfo_to_se (&se, &loop);
2071 se.ss = lss_real;
2072 gfc_conv_expr (&se, lhs_expr);
2073 gfc_add_block_to_block (&body, &se.pre);
2074
2075 /* Walk over all indexes of the loop. */
2076 for (n = loop.dimen - 1; n > 0; --n)
2077 {
2078 tmp = loop.loopvar[n];
2079 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2080 gfc_array_index_type, tmp, loop.from[n]);
2081 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2082 gfc_array_index_type, tmp, index);
2083
2084 stride = fold_build2_loc (input_location, MINUS_EXPR,
2085 gfc_array_index_type,
2086 loop.to[n - 1], loop.from[n - 1]);
2087 stride = fold_build2_loc (input_location, PLUS_EXPR,
2088 gfc_array_index_type,
2089 stride, gfc_index_one_node);
2090
2091 index = fold_build2_loc (input_location, MULT_EXPR,
2092 gfc_array_index_type, tmp, stride);
2093 }
2094
2095 index = fold_build2_loc (input_location, MINUS_EXPR,
2096 gfc_array_index_type,
2097 index, loop.from[0]);
2098
2099 index = fold_build2_loc (input_location, PLUS_EXPR,
2100 gfc_array_index_type,
2101 loop.loopvar[0], index);
2102
2103 src = build_fold_indirect_ref (gfc_conv_array_data (tmparr_desc));
2104 src = gfc_build_array_ref (src, index, NULL);
2105 /* Now create the assignment of lhs_expr = tmp_array. */
2106 gfc_add_modify (&body, se.expr, src);
2107 gfc_add_block_to_block (&body, &se.post);
2108 lhs_se.expr = gfc_build_addr_expr (NULL_TREE, tmparr_desc);
2109 gfc_trans_scalarizing_loops (&loop, &body);
2110 gfc_add_block_to_block (&loop.pre, &loop.post);
2111 gfc_add_expr_to_block (&lhs_se.post, gfc_finish_block (&loop.pre));
2112 gfc_free_ss (lss_for_tmparray);
2113 gfc_free_ss (lss_real);
b5116268
TB
2114 }
2115 }
2116
2117 lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
b5116268
TB
2118
2119 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
2120 temporary and a loop. */
ba85c8c3
AV
2121 if (!gfc_is_coindexed (lhs_expr)
2122 && (!lhs_caf_attr.codimension
de91486c
AV
2123 || !(lhs_expr->rank > 0
2124 && (lhs_caf_attr.allocatable || lhs_caf_attr.pointer))))
b5116268 2125 {
3c9f5092 2126 bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
b5116268
TB
2127 gcc_assert (gfc_is_coindexed (rhs_expr));
2128 gfc_init_se (&rhs_se, NULL);
de91486c 2129 if (lhs_expr->rank == 0 && lhs_caf_attr.allocatable)
3c9f5092
AV
2130 {
2131 gfc_se scal_se;
2132 gfc_init_se (&scal_se, NULL);
2133 scal_se.want_pointer = 1;
2134 gfc_conv_expr (&scal_se, lhs_expr);
2135 /* Ensure scalar on lhs is allocated. */
2136 gfc_add_block_to_block (&block, &scal_se.pre);
2137
2138 gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
2139 TYPE_SIZE_UNIT (
2140 gfc_typenode_for_spec (&lhs_expr->ts)),
2141 NULL_TREE);
63ee5404 2142 tmp = fold_build2 (EQ_EXPR, logical_type_node, scal_se.expr,
3c9f5092
AV
2143 null_pointer_node);
2144 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2145 tmp, gfc_finish_block (&scal_se.pre),
2146 build_empty_stmt (input_location));
2147 gfc_add_expr_to_block (&block, tmp);
2148 }
2149 else
2150 lhs_may_realloc = lhs_may_realloc
2151 && gfc_full_array_ref_p (lhs_expr->ref, NULL);
2152 gfc_add_block_to_block (&block, &lhs_se.pre);
93e2e046 2153 gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
3c9f5092 2154 may_require_tmp, lhs_may_realloc,
ba85c8c3 2155 &rhs_caf_attr);
b5116268
TB
2156 gfc_add_block_to_block (&block, &rhs_se.pre);
2157 gfc_add_block_to_block (&block, &rhs_se.post);
2158 gfc_add_block_to_block (&block, &lhs_se.post);
2159 return gfc_finish_block (&block);
2160 }
2161
3c9f5092 2162 gfc_add_block_to_block (&block, &lhs_se.pre);
b5116268 2163
3c9f5092 2164 /* Obtain token, offset and image index for the LHS. */
b5116268
TB
2165 caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
2166 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2167 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2c69df3b 2168 image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
3c9f5092
AV
2169 tmp = lhs_se.expr;
2170 if (lhs_caf_attr.alloc_comp)
2171 gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL_TREE,
2172 NULL);
2173 else
2174 gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
2175 lhs_expr);
2176 lhs_se.expr = tmp;
b5116268
TB
2177
2178 /* RHS. */
2179 gfc_init_se (&rhs_se, NULL);
5c75088c
TB
2180 if (rhs_expr->expr_type == EXPR_FUNCTION && rhs_expr->value.function.isym
2181 && rhs_expr->value.function.isym->id == GFC_ISYM_CONVERSION)
2182 rhs_expr = rhs_expr->value.function.actual->expr;
b5116268
TB
2183 if (rhs_expr->rank == 0)
2184 {
2185 symbol_attribute attr;
2186 gfc_clear_attr (&attr);
2187 gfc_conv_expr (&rhs_se, rhs_expr);
2188 rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
2189 rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
2190 }
de91486c
AV
2191 else if ((rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
2192 && rhs_caf_attr.codimension)
3c9f5092
AV
2193 {
2194 tree tmp2;
2195 rhs_se.want_pointer = 1;
2196 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
2197 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2198 has the wrong type if component references are done. */
2199 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2200 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2201 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
2202 gfc_get_dtype_rank_type (
2203 gfc_has_vector_subscript (rhs_expr)
2204 ? gfc_find_array_ref (rhs_expr)->dimen
2205 : rhs_expr->rank,
2206 tmp2));
2207 }
b5116268
TB
2208 else
2209 {
2210 /* If has_vector, pass descriptor for whole array and the
2211 vector bounds separately. */
2212 gfc_array_ref *ar, ar2;
2213 bool has_vector = false;
d7463e5b 2214 tree tmp2;
b5116268
TB
2215
2216 if (gfc_is_coindexed (rhs_expr) && gfc_has_vector_subscript (rhs_expr))
2217 {
2218 has_vector = true;
2219 ar = gfc_find_array_ref (rhs_expr);
2220 ar2 = *ar;
2221 memset (ar, '\0', sizeof (*ar));
2222 ar->as = ar2.as;
2223 ar->type = AR_FULL;
2224 }
2225 rhs_se.want_pointer = 1;
2226 gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
d7463e5b
TB
2227 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2228 has the wrong type if component references are done. */
2229 tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
2230 tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
2231 gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
69859058
TB
2232 gfc_get_dtype_rank_type (has_vector ? ar2.dimen
2233 : rhs_expr->rank,
2234 tmp2));
b5116268
TB
2235 if (has_vector)
2236 {
69859058 2237 rhs_vec = conv_caf_vector_subscript (&block, rhs_se.expr, &ar2);
b5116268
TB
2238 *ar = ar2;
2239 }
2240 }
2241
2242 gfc_add_block_to_block (&block, &rhs_se.pre);
2243
2244 rhs_kind = build_int_cst (integer_type_node, rhs_expr->ts.kind);
2245
4971dd80 2246 tmp_stat = gfc_find_stat_co (lhs_expr);
20d0bfce
AF
2247
2248 if (tmp_stat)
2249 {
2250 gfc_se stat_se;
2251 gfc_init_se (&stat_se, NULL);
2252 gfc_conv_expr_reference (&stat_se, tmp_stat);
3c9f5092 2253 dst_stat = stat_se.expr;
20d0bfce
AF
2254 gfc_add_block_to_block (&block, &stat_se.pre);
2255 gfc_add_block_to_block (&block, &stat_se.post);
2256 }
20d0bfce 2257
f8862a1b
DR
2258 tmp_team = gfc_find_team_co (lhs_expr);
2259
2260 if (tmp_team)
2261 {
2262 gfc_se team_se;
2263 gfc_init_se (&team_se, NULL);
2264 gfc_conv_expr_reference (&team_se, tmp_team);
2265 dst_team = team_se.expr;
2266 gfc_add_block_to_block (&block, &team_se.pre);
2267 gfc_add_block_to_block (&block, &team_se.post);
2268 }
2269
ba85c8c3 2270 if (!gfc_is_coindexed (rhs_expr))
3c9f5092 2271 {
de91486c 2272 if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp)
3c9f5092
AV
2273 {
2274 tree reference, dst_realloc;
2275 reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2276 dst_realloc = lhs_caf_attr.allocatable ? boolean_true_node
2277 : boolean_false_node;
2278 tmp = build_call_expr_loc (input_location,
2279 gfor_fndecl_caf_send_by_ref,
87e8aa3b 2280 10, token, image_index, rhs_se.expr,
3c9f5092 2281 reference, lhs_kind, rhs_kind,
87e8aa3b
AV
2282 may_require_tmp, dst_realloc, src_stat,
2283 build_int_cst (integer_type_node,
2284 lhs_expr->ts.type));
3c9f5092
AV
2285 }
2286 else
f8862a1b 2287 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 11,
3c9f5092
AV
2288 token, offset, image_index, lhs_se.expr, vec,
2289 rhs_se.expr, lhs_kind, rhs_kind,
f8862a1b 2290 may_require_tmp, src_stat, dst_team);
3c9f5092 2291 }
b5116268
TB
2292 else
2293 {
2294 tree rhs_token, rhs_offset, rhs_image_index;
2295
3c9f5092
AV
2296 /* It guarantees memory consistency within the same segment. */
2297 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
4971dd80 2298 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
985f6c79
TB
2299 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2300 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2301 ASM_VOLATILE_P (tmp) = 1;
2302 gfc_add_expr_to_block (&block, tmp);
2303
b5116268
TB
2304 caf_decl = gfc_get_tree_for_caf_expr (rhs_expr);
2305 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
2306 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2c69df3b 2307 rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
3c9f5092 2308 tmp = rhs_se.expr;
de91486c 2309 if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp)
3c9f5092
AV
2310 {
2311 tmp_stat = gfc_find_stat_co (lhs_expr);
2312
2313 if (tmp_stat)
2314 {
2315 gfc_se stat_se;
2316 gfc_init_se (&stat_se, NULL);
2317 gfc_conv_expr_reference (&stat_se, tmp_stat);
2318 src_stat = stat_se.expr;
2319 gfc_add_block_to_block (&block, &stat_se.pre);
2320 gfc_add_block_to_block (&block, &stat_se.post);
2321 }
2322
2323 gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL, caf_decl,
2324 NULL_TREE, NULL);
2325 tree lhs_reference, rhs_reference;
2326 lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
2327 rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
2328 tmp = build_call_expr_loc (input_location,
87e8aa3b 2329 gfor_fndecl_caf_sendget_by_ref, 13,
3c9f5092
AV
2330 token, image_index, lhs_reference,
2331 rhs_token, rhs_image_index, rhs_reference,
2332 lhs_kind, rhs_kind, may_require_tmp,
87e8aa3b
AV
2333 dst_stat, src_stat,
2334 build_int_cst (integer_type_node,
2335 lhs_expr->ts.type),
2336 build_int_cst (integer_type_node,
2337 rhs_expr->ts.type));
3c9f5092
AV
2338 }
2339 else
2340 {
2341 gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
2342 tmp, rhs_expr);
2343 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
2344 14, token, offset, image_index,
2345 lhs_se.expr, vec, rhs_token, rhs_offset,
2346 rhs_image_index, tmp, rhs_vec, lhs_kind,
2347 rhs_kind, may_require_tmp, src_stat);
2348 }
b5116268
TB
2349 }
2350 gfc_add_expr_to_block (&block, tmp);
2351 gfc_add_block_to_block (&block, &lhs_se.post);
2352 gfc_add_block_to_block (&block, &rhs_se.post);
985f6c79 2353
3c9f5092
AV
2354 /* It guarantees memory consistency within the same segment. */
2355 tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
985f6c79
TB
2356 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
2357 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
2358 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
2359 ASM_VOLATILE_P (tmp) = 1;
2360 gfc_add_expr_to_block (&block, tmp);
2361
b5116268
TB
2362 return gfc_finish_block (&block);
2363}
2364
2365
60386f50 2366static void
0e3184ac 2367trans_this_image (gfc_se * se, gfc_expr *expr)
60386f50 2368{
0e3184ac
TB
2369 stmtblock_t loop;
2370 tree type, desc, dim_arg, cond, tmp, m, loop_var, exit_label, min_var,
2371 lbound, ubound, extent, ml;
2372 gfc_se argse;
0e3184ac 2373 int rank, corank;
05fc16dd
TB
2374 gfc_expr *distance = expr->value.function.actual->next->next->expr;
2375
2376 if (expr->value.function.actual->expr
2377 && !gfc_is_coarray (expr->value.function.actual->expr))
2378 distance = expr->value.function.actual->expr;
0e3184ac
TB
2379
2380 /* The case -fcoarray=single is handled elsewhere. */
f19626cf 2381 gcc_assert (flag_coarray != GFC_FCOARRAY_SINGLE);
0e3184ac 2382
0e3184ac 2383 /* Argument-free version: THIS_IMAGE(). */
05fc16dd 2384 if (distance || expr->value.function.actual->expr == NULL)
0e3184ac 2385 {
05fc16dd
TB
2386 if (distance)
2387 {
2388 gfc_init_se (&argse, NULL);
2389 gfc_conv_expr_val (&argse, distance);
2390 gfc_add_block_to_block (&se->pre, &argse.pre);
2391 gfc_add_block_to_block (&se->post, &argse.post);
2392 tmp = fold_convert (integer_type_node, argse.expr);
2393 }
2394 else
2395 tmp = integer_zero_node;
a8a5f4a9 2396 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
05fc16dd 2397 tmp);
5a155783 2398 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
a8a5f4a9 2399 tmp);
0e3184ac
TB
2400 return;
2401 }
2402
2403 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2404
2405 type = gfc_get_int_type (gfc_default_integer_kind);
2406 corank = gfc_get_corank (expr->value.function.actual->expr);
2407 rank = expr->value.function.actual->expr->rank;
2408
2409 /* Obtain the descriptor of the COARRAY. */
2410 gfc_init_se (&argse, NULL);
23c3d0f9 2411 argse.want_coarray = 1;
2960a368 2412 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
0e3184ac
TB
2413 gfc_add_block_to_block (&se->pre, &argse.pre);
2414 gfc_add_block_to_block (&se->post, &argse.post);
2415 desc = argse.expr;
2416
2417 if (se->ss)
2418 {
2419 /* Create an implicit second parameter from the loop variable. */
2420 gcc_assert (!expr->value.function.actual->next->expr);
2421 gcc_assert (corank > 0);
2422 gcc_assert (se->loop->dimen == 1);
f98cfd3c 2423 gcc_assert (se->ss->info->expr == expr);
0e3184ac
TB
2424
2425 dim_arg = se->loop->loopvar[0];
2426 dim_arg = fold_build2_loc (input_location, PLUS_EXPR,
2427 gfc_array_index_type, dim_arg,
c81e79b5 2428 build_int_cst (TREE_TYPE (dim_arg), 1));
0e3184ac
TB
2429 gfc_advance_se_ss_chain (se);
2430 }
2431 else
2432 {
2433 /* Use the passed DIM= argument. */
2434 gcc_assert (expr->value.function.actual->next->expr);
2435 gfc_init_se (&argse, NULL);
2436 gfc_conv_expr_type (&argse, expr->value.function.actual->next->expr,
2437 gfc_array_index_type);
2438 gfc_add_block_to_block (&se->pre, &argse.pre);
2439 dim_arg = argse.expr;
2440
2441 if (INTEGER_CST_P (dim_arg))
2442 {
8e6cdc90
RS
2443 if (wi::ltu_p (wi::to_wide (dim_arg), 1)
2444 || wi::gtu_p (wi::to_wide (dim_arg),
2445 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
a4d9b221 2446 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
0e3184ac
TB
2447 "dimension index", expr->value.function.isym->name,
2448 &expr->where);
2449 }
2450 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2451 {
2452 dim_arg = gfc_evaluate_now (dim_arg, &se->pre);
63ee5404 2453 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
0e3184ac
TB
2454 dim_arg,
2455 build_int_cst (TREE_TYPE (dim_arg), 1));
2456 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
63ee5404 2457 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
0e3184ac
TB
2458 dim_arg, tmp);
2459 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
63ee5404 2460 logical_type_node, cond, tmp);
0e3184ac
TB
2461 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
2462 gfc_msg_fault);
2463 }
2464 }
2465
2466 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2467 one always has a dim_arg argument.
2468
5a155783 2469 m = this_image() - 1
492792ed
TB
2470 if (corank == 1)
2471 {
2472 sub(1) = m + lcobound(corank)
2473 return;
2474 }
0e3184ac 2475 i = rank
c81e79b5 2476 min_var = min (rank + corank - 2, rank + dim_arg - 1)
0e3184ac
TB
2477 for (;;)
2478 {
2479 extent = gfc_extent(i)
2480 ml = m
2481 m = m/extent
029b2d55 2482 if (i >= min_var)
0e3184ac
TB
2483 goto exit_label
2484 i++
2485 }
2486 exit_label:
2487 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2488 : m + lcobound(corank)
2489 */
2490
492792ed 2491 /* this_image () - 1. */
a8a5f4a9
TB
2492 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2493 integer_zero_node);
2494 tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
2495 fold_convert (type, tmp), build_int_cst (type, 1));
492792ed
TB
2496 if (corank == 1)
2497 {
2498 /* sub(1) = m + lcobound(corank). */
2499 lbound = gfc_conv_descriptor_lbound_get (desc,
2500 build_int_cst (TREE_TYPE (gfc_array_index_type),
2501 corank+rank-1));
2502 lbound = fold_convert (type, lbound);
2503 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2504
2505 se->expr = tmp;
2506 return;
2507 }
2508
029b2d55
PT
2509 m = gfc_create_var (type, NULL);
2510 ml = gfc_create_var (type, NULL);
2511 loop_var = gfc_create_var (integer_type_node, NULL);
2512 min_var = gfc_create_var (integer_type_node, NULL);
0e3184ac
TB
2513
2514 /* m = this_image () - 1. */
0e3184ac
TB
2515 gfc_add_modify (&se->pre, m, tmp);
2516
c81e79b5
TB
2517 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2518 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2519 fold_convert (integer_type_node, dim_arg),
2520 build_int_cst (integer_type_node, rank - 1));
0e3184ac
TB
2521 tmp = fold_build2_loc (input_location, MIN_EXPR, integer_type_node,
2522 build_int_cst (integer_type_node, rank + corank - 2),
c81e79b5 2523 tmp);
0e3184ac
TB
2524 gfc_add_modify (&se->pre, min_var, tmp);
2525
2526 /* i = rank. */
2527 tmp = build_int_cst (integer_type_node, rank);
2528 gfc_add_modify (&se->pre, loop_var, tmp);
2529
2530 exit_label = gfc_build_label_decl (NULL_TREE);
2531 TREE_USED (exit_label) = 1;
2532
2533 /* Loop body. */
2534 gfc_init_block (&loop);
2535
2536 /* ml = m. */
2537 gfc_add_modify (&loop, ml, m);
2538
2539 /* extent = ... */
2540 lbound = gfc_conv_descriptor_lbound_get (desc, loop_var);
2541 ubound = gfc_conv_descriptor_ubound_get (desc, loop_var);
2542 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2543 extent = fold_convert (type, extent);
2544
2545 /* m = m/extent. */
029b2d55 2546 gfc_add_modify (&loop, m,
0e3184ac
TB
2547 fold_build2_loc (input_location, TRUNC_DIV_EXPR, type,
2548 m, extent));
2549
2550 /* Exit condition: if (i >= min_var) goto exit_label. */
63ee5404 2551 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, loop_var,
0e3184ac
TB
2552 min_var);
2553 tmp = build1_v (GOTO_EXPR, exit_label);
2554 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
2555 build_empty_stmt (input_location));
2556 gfc_add_expr_to_block (&loop, tmp);
2557
2558 /* Increment loop variable: i++. */
2559 gfc_add_modify (&loop, loop_var,
2560 fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
2561 loop_var,
2562 build_int_cst (integer_type_node, 1)));
2563
2564 /* Making the loop... actually loop! */
2565 tmp = gfc_finish_block (&loop);
2566 tmp = build1_v (LOOP_EXPR, tmp);
2567 gfc_add_expr_to_block (&se->pre, tmp);
2568
2569 /* The exit label. */
2570 tmp = build1_v (LABEL_EXPR, exit_label);
2571 gfc_add_expr_to_block (&se->pre, tmp);
2572
2573 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2574 : m + lcobound(corank) */
2575
63ee5404 2576 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, dim_arg,
0e3184ac
TB
2577 build_int_cst (TREE_TYPE (dim_arg), corank));
2578
2579 lbound = gfc_conv_descriptor_lbound_get (desc,
c81e79b5
TB
2580 fold_build2_loc (input_location, PLUS_EXPR,
2581 gfc_array_index_type, dim_arg,
2582 build_int_cst (TREE_TYPE (dim_arg), rank-1)));
0e3184ac
TB
2583 lbound = fold_convert (type, lbound);
2584
2585 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, ml,
2586 fold_build2_loc (input_location, MULT_EXPR, type,
2587 m, extent));
2588 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp, lbound);
2589
2590 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, tmp,
2591 fold_build2_loc (input_location, PLUS_EXPR, type,
2592 m, lbound));
60386f50
TB
2593}
2594
5af07930 2595
ef78bc3c
AV
2596/* Convert a call to image_status. */
2597
2598static void
2599conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr)
2600{
2601 unsigned int num_args;
2602 tree *args, tmp;
2603
2604 num_args = gfc_intrinsic_argument_list_length (expr);
2605 args = XALLOCAVEC (tree, num_args);
2606 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2607 /* In args[0] the number of the image the status is desired for has to be
2608 given. */
2609
2610 if (flag_coarray == GFC_FCOARRAY_SINGLE)
2611 {
2612 tree arg;
2613 arg = gfc_evaluate_now (args[0], &se->pre);
63ee5404 2614 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
ef78bc3c
AV
2615 fold_convert (integer_type_node, arg),
2616 integer_one_node);
2617 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2618 tmp, integer_zero_node,
2619 build_int_cst (integer_type_node,
2620 GFC_STAT_STOPPED_IMAGE));
2621 }
2622 else if (flag_coarray == GFC_FCOARRAY_LIB)
2623 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_image_status, 2,
2624 args[0], build_int_cst (integer_type_node, -1));
2625 else
2626 gcc_unreachable ();
2627
7eb61a45 2628 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
ef78bc3c
AV
2629}
2630
f8862a1b
DR
2631static void
2632conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr)
2633{
2634 unsigned int num_args;
2635
2636 tree *args, tmp;
2637
2638 num_args = gfc_intrinsic_argument_list_length (expr);
2639 args = XALLOCAVEC (tree, num_args);
2640 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2641
2642 if (flag_coarray ==
2643 GFC_FCOARRAY_SINGLE && expr->value.function.actual->expr)
2644 {
2645 tree arg;
2646
2647 arg = gfc_evaluate_now (args[0], &se->pre);
2648 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
2649 fold_convert (integer_type_node, arg),
2650 integer_one_node);
2651 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
2652 tmp, integer_zero_node,
2653 build_int_cst (integer_type_node,
2654 GFC_STAT_STOPPED_IMAGE));
2655 }
2656 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
2657 {
2658 // the value -1 represents that no team has been created yet
2659 tmp = build_int_cst (integer_type_node, -1);
2660 }
2661 else if (flag_coarray == GFC_FCOARRAY_LIB && expr->value.function.actual->expr)
2662 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2663 args[0], build_int_cst (integer_type_node, -1));
2664 else if (flag_coarray == GFC_FCOARRAY_LIB)
2665 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_team_number, 1,
2666 integer_zero_node, build_int_cst (integer_type_node, -1));
2667 else
2668 gcc_unreachable ();
2669
7eb61a45 2670 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
f8862a1b
DR
2671}
2672
ef78bc3c 2673
5af07930
TB
2674static void
2675trans_image_index (gfc_se * se, gfc_expr *expr)
2676{
2677 tree num_images, cond, coindex, type, lbound, ubound, desc, subdesc,
2678 tmp, invalid_bound;
2679 gfc_se argse, subse;
5af07930
TB
2680 int rank, corank, codim;
2681
2682 type = gfc_get_int_type (gfc_default_integer_kind);
2683 corank = gfc_get_corank (expr->value.function.actual->expr);
2684 rank = expr->value.function.actual->expr->rank;
2685
2686 /* Obtain the descriptor of the COARRAY. */
2687 gfc_init_se (&argse, NULL);
23c3d0f9 2688 argse.want_coarray = 1;
2960a368 2689 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
5af07930
TB
2690 gfc_add_block_to_block (&se->pre, &argse.pre);
2691 gfc_add_block_to_block (&se->post, &argse.post);
2692 desc = argse.expr;
2693
2694 /* Obtain a handle to the SUB argument. */
2695 gfc_init_se (&subse, NULL);
2960a368 2696 gfc_conv_expr_descriptor (&subse, expr->value.function.actual->next->expr);
5af07930
TB
2697 gfc_add_block_to_block (&se->pre, &subse.pre);
2698 gfc_add_block_to_block (&se->post, &subse.post);
2699 subdesc = build_fold_indirect_ref_loc (input_location,
2700 gfc_conv_descriptor_data_get (subse.expr));
2701
2702 /* Fortran 2008 does not require that the values remain in the cobounds,
2703 thus we need explicitly check this - and return 0 if they are exceeded. */
2704
2705 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2706 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1], NULL);
63ee5404 2707 invalid_bound = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
5af07930
TB
2708 fold_convert (gfc_array_index_type, tmp),
2709 lbound);
2710
2711 for (codim = corank + rank - 2; codim >= rank; codim--)
2712 {
2713 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2714 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2715 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
63ee5404 2716 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
5af07930
TB
2717 fold_convert (gfc_array_index_type, tmp),
2718 lbound);
2719 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
63ee5404
JB
2720 logical_type_node, invalid_bound, cond);
2721 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
5af07930
TB
2722 fold_convert (gfc_array_index_type, tmp),
2723 ubound);
2724 invalid_bound = fold_build2_loc (input_location, TRUTH_OR_EXPR,
63ee5404 2725 logical_type_node, invalid_bound, cond);
5af07930
TB
2726 }
2727
ed9c79e1 2728 invalid_bound = gfc_unlikely (invalid_bound, PRED_FORTRAN_INVALID_BOUND);
5af07930
TB
2729
2730 /* See Fortran 2008, C.10 for the following algorithm. */
2731
2732 /* coindex = sub(corank) - lcobound(n). */
2733 coindex = fold_convert (gfc_array_index_type,
2734 gfc_build_array_ref (subdesc, gfc_rank_cst[corank-1],
2735 NULL));
2736 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[rank+corank-1]);
2737 coindex = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2738 fold_convert (gfc_array_index_type, coindex),
2739 lbound);
2740
2741 for (codim = corank + rank - 2; codim >= rank; codim--)
2742 {
2743 tree extent, ubound;
2744
2745 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2746 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2747 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[codim]);
2748 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2749
2750 /* coindex *= extent. */
2751 coindex = fold_build2_loc (input_location, MULT_EXPR,
2752 gfc_array_index_type, coindex, extent);
2753
2754 /* coindex += sub(codim). */
2755 tmp = gfc_build_array_ref (subdesc, gfc_rank_cst[codim-rank], NULL);
2756 coindex = fold_build2_loc (input_location, PLUS_EXPR,
2757 gfc_array_index_type, coindex,
2758 fold_convert (gfc_array_index_type, tmp));
2759
2760 /* coindex -= lbound(codim). */
2761 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[codim]);
2762 coindex = fold_build2_loc (input_location, MINUS_EXPR,
2763 gfc_array_index_type, coindex, lbound);
2764 }
2765
2766 coindex = fold_build2_loc (input_location, PLUS_EXPR, type,
2767 fold_convert(type, coindex),
2768 build_int_cst (type, 1));
2769
2770 /* Return 0 if "coindex" exceeds num_images(). */
2771
f19626cf 2772 if (flag_coarray == GFC_FCOARRAY_SINGLE)
5af07930
TB
2773 num_images = build_int_cst (type, 1);
2774 else
2775 {
a8a5f4a9
TB
2776 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2777 integer_zero_node,
2778 build_int_cst (integer_type_node, -1));
2779 num_images = fold_convert (type, tmp);
5af07930
TB
2780 }
2781
2782 tmp = gfc_create_var (type, NULL);
2783 gfc_add_modify (&se->pre, tmp, coindex);
2784
63ee5404 2785 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, tmp,
5af07930 2786 num_images);
63ee5404 2787 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
5af07930 2788 cond,
63ee5404 2789 fold_convert (logical_type_node, invalid_bound));
5af07930
TB
2790 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
2791 build_int_cst (type, 0), tmp);
2792}
2793
60386f50 2794static void
05fc16dd 2795trans_num_images (gfc_se * se, gfc_expr *expr)
60386f50 2796{
05fc16dd
TB
2797 tree tmp, distance, failed;
2798 gfc_se argse;
2799
2800 if (expr->value.function.actual->expr)
2801 {
2802 gfc_init_se (&argse, NULL);
2803 gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
2804 gfc_add_block_to_block (&se->pre, &argse.pre);
2805 gfc_add_block_to_block (&se->post, &argse.post);
2806 distance = fold_convert (integer_type_node, argse.expr);
2807 }
2808 else
2809 distance = integer_zero_node;
2810
2811 if (expr->value.function.actual->next->expr)
2812 {
2813 gfc_init_se (&argse, NULL);
2814 gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
2815 gfc_add_block_to_block (&se->pre, &argse.pre);
2816 gfc_add_block_to_block (&se->post, &argse.post);
2817 failed = fold_convert (integer_type_node, argse.expr);
2818 }
2819 else
2820 failed = build_int_cst (integer_type_node, -1);
05fc16dd
TB
2821 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
2822 distance, failed);
a8a5f4a9 2823 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
60386f50
TB
2824}
2825
a3935ffc 2826
32e7b05d
TB
2827static void
2828gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
2829{
2830 gfc_se argse;
32e7b05d 2831
32e7b05d
TB
2832 gfc_init_se (&argse, NULL);
2833 argse.data_not_needed = 1;
c62c6622 2834 argse.descriptor_only = 1;
32e7b05d 2835
2960a368 2836 gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr);
32e7b05d
TB
2837 gfc_add_block_to_block (&se->pre, &argse.pre);
2838 gfc_add_block_to_block (&se->post, &argse.post);
c62c6622 2839
17aa6ab6 2840 se->expr = gfc_conv_descriptor_rank (argse.expr);
7fb43006
PT
2841 se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
2842 se->expr);
32e7b05d
TB
2843}
2844
2845
419af57c
TK
2846static void
2847gfc_conv_intrinsic_is_contiguous (gfc_se * se, gfc_expr * expr)
2848{
2849 gfc_expr *arg;
1585b483
TK
2850 arg = expr->value.function.actual->expr;
2851 gfc_conv_is_contiguous_expr (se, arg);
2852 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
2853}
2854
2855/* This function does the work for gfc_conv_intrinsic_is_contiguous,
2856 plus it can be called directly. */
2857
2858void
2859gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg)
2860{
419af57c
TK
2861 gfc_ss *ss;
2862 gfc_se argse;
2863 tree desc, tmp, stride, extent, cond;
2864 int i;
2865 tree fncall0;
2866 gfc_array_spec *as;
2867
419af57c
TK
2868 if (arg->ts.type == BT_CLASS)
2869 gfc_add_class_array_ref (arg);
2870
2871 ss = gfc_walk_expr (arg);
2872 gcc_assert (ss != gfc_ss_terminator);
2873 gfc_init_se (&argse, NULL);
2874 argse.data_not_needed = 1;
2875 gfc_conv_expr_descriptor (&argse, arg);
2876
2877 as = gfc_get_full_arrayspec_from_expr (arg);
2878
2879 /* Create: stride[0] == 1 && stride[1] == extend[0]*stride[0] && ...
2880 Note in addition that zero-sized arrays don't count as contiguous. */
2881
2882 if (as && as->type == AS_ASSUMED_RANK)
2883 {
2884 /* Build the call to is_contiguous0. */
2885 argse.want_pointer = 1;
2886 gfc_conv_expr_descriptor (&argse, arg);
2887 gfc_add_block_to_block (&se->pre, &argse.pre);
2888 gfc_add_block_to_block (&se->post, &argse.post);
2889 desc = gfc_evaluate_now (argse.expr, &se->pre);
2890 fncall0 = build_call_expr_loc (input_location,
2891 gfor_fndecl_is_contiguous0, 1, desc);
2892 se->expr = fncall0;
2893 se->expr = convert (logical_type_node, se->expr);
2894 }
2895 else
2896 {
2897 gfc_add_block_to_block (&se->pre, &argse.pre);
2898 gfc_add_block_to_block (&se->post, &argse.post);
2899 desc = gfc_evaluate_now (argse.expr, &se->pre);
0e308880 2900
419af57c
TK
2901 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[0]);
2902 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2903 stride, build_int_cst (TREE_TYPE (stride), 1));
2904
1585b483 2905 for (i = 0; i < arg->rank - 1; i++)
419af57c
TK
2906 {
2907 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
2908 extent = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
2909 extent = fold_build2_loc (input_location, MINUS_EXPR,
2910 gfc_array_index_type, extent, tmp);
2911 extent = fold_build2_loc (input_location, PLUS_EXPR,
2912 gfc_array_index_type, extent,
2913 gfc_index_one_node);
2914 tmp = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i]);
2915 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
2916 tmp, extent);
2917 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[i+1]);
2918 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
2919 stride, tmp);
2920 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
2921 boolean_type_node, cond, tmp);
2922 }
1585b483 2923 se->expr = cond;
419af57c
TK
2924 }
2925}
2926
2927
6de9cd9a 2928/* Evaluate a single upper or lower bound. */
1f2959f0 2929/* TODO: bound intrinsic generates way too much unnecessary code. */
6de9cd9a
DN
2930
2931static void
1af78e73 2932gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, enum gfc_isym_id op)
6de9cd9a
DN
2933{
2934 gfc_actual_arglist *arg;
2935 gfc_actual_arglist *arg2;
2936 tree desc;
2937 tree type;
2938 tree bound;
2939 tree tmp;
1af78e73 2940 tree cond, cond1;
ac677cc8
FXC
2941 tree ubound;
2942 tree lbound;
1af78e73 2943 tree size;
6de9cd9a 2944 gfc_se argse;
ac677cc8 2945 gfc_array_spec * as;
63fbf586 2946 bool assumed_rank_lb_one;
6de9cd9a 2947
6de9cd9a
DN
2948 arg = expr->value.function.actual;
2949 arg2 = arg->next;
2950
2951 if (se->ss)
2952 {
2953 /* Create an implicit second parameter from the loop variable. */
1af78e73 2954 gcc_assert (!arg2->expr || op == GFC_ISYM_SHAPE);
6e45f57b 2955 gcc_assert (se->loop->dimen == 1);
f98cfd3c 2956 gcc_assert (se->ss->info->expr == expr);
6de9cd9a
DN
2957 gfc_advance_se_ss_chain (se);
2958 bound = se->loop->loopvar[0];
433ce291
TB
2959 bound = fold_build2_loc (input_location, MINUS_EXPR,
2960 gfc_array_index_type, bound,
2961 se->loop->from[0]);
6de9cd9a
DN
2962 }
2963 else
2964 {
2965 /* use the passed argument. */
a3935ffc 2966 gcc_assert (arg2->expr);
6de9cd9a 2967 gfc_init_se (&argse, NULL);
a3935ffc 2968 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
6de9cd9a
DN
2969 gfc_add_block_to_block (&se->pre, &argse.pre);
2970 bound = argse.expr;
2971 /* Convert from one based to zero based. */
433ce291
TB
2972 bound = fold_build2_loc (input_location, MINUS_EXPR,
2973 gfc_array_index_type, bound,
2974 gfc_index_one_node);
6de9cd9a
DN
2975 }
2976
2977 /* TODO: don't re-evaluate the descriptor on each iteration. */
2978 /* Get a descriptor for the first parameter. */
4fd9a813 2979 gfc_init_se (&argse, NULL);
2960a368 2980 gfc_conv_expr_descriptor (&argse, arg->expr);
6de9cd9a
DN
2981 gfc_add_block_to_block (&se->pre, &argse.pre);
2982 gfc_add_block_to_block (&se->post, &argse.post);
2983
2984 desc = argse.expr;
2985
63fbf586
TB
2986 as = gfc_get_full_arrayspec_from_expr (arg->expr);
2987
6de9cd9a
DN
2988 if (INTEGER_CST_P (bound))
2989 {
1af78e73 2990 gcc_assert (op != GFC_ISYM_SHAPE);
807e902e 2991 if (((!as || as->type != AS_ASSUMED_RANK)
8e6cdc90
RS
2992 && wi::geu_p (wi::to_wide (bound),
2993 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))))
2994 || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS))
a4d9b221 2995 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
1af78e73
SL
2996 "dimension index",
2997 (op == GFC_ISYM_UBOUND) ? "UBOUND" : "LBOUND",
9f1dce56 2998 &expr->where);
6de9cd9a 2999 }
63fbf586
TB
3000
3001 if (!INTEGER_CST_P (bound) || (as && as->type == AS_ASSUMED_RANK))
6de9cd9a 3002 {
d3d3011f 3003 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
6de9cd9a
DN
3004 {
3005 bound = gfc_evaluate_now (bound, &se->pre);
63ee5404 3006 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
433ce291 3007 bound, build_int_cst (TREE_TYPE (bound), 0));
63fbf586 3008 if (as && as->type == AS_ASSUMED_RANK)
17aa6ab6 3009 tmp = gfc_conv_descriptor_rank (desc);
63fbf586
TB
3010 else
3011 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
63ee5404 3012 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
63fbf586 3013 bound, fold_convert(TREE_TYPE (bound), tmp));
433ce291 3014 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
63ee5404 3015 logical_type_node, cond, tmp);
0d52899f
TB
3016 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3017 gfc_msg_fault);
6de9cd9a
DN
3018 }
3019 }
3020
1af78e73
SL
3021 /* Take care of the lbound shift for assumed-rank arrays that are
3022 nonallocatable and nonpointers. Those have a lbound of 1. */
63fbf586
TB
3023 assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK
3024 && ((arg->expr->ts.type != BT_CLASS
3025 && !arg->expr->symtree->n.sym->attr.allocatable
3026 && !arg->expr->symtree->n.sym->attr.pointer)
3027 || (arg->expr->ts.type == BT_CLASS
3028 && !CLASS_DATA (arg->expr)->attr.allocatable
3029 && !CLASS_DATA (arg->expr)->attr.class_pointer));
3030
568e8e1e
PT
3031 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
3032 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
1af78e73
SL
3033 size = fold_build2_loc (input_location, MINUS_EXPR,
3034 gfc_array_index_type, ubound, lbound);
3035 size = fold_build2_loc (input_location, PLUS_EXPR,
3036 gfc_array_index_type, size, gfc_index_one_node);
029b2d55 3037
ac677cc8
FXC
3038 /* 13.14.53: Result value for LBOUND
3039
3040 Case (i): For an array section or for an array expression other than a
3041 whole array or array structure component, LBOUND(ARRAY, DIM)
3042 has the value 1. For a whole array or array structure
3043 component, LBOUND(ARRAY, DIM) has the value:
3044 (a) equal to the lower bound for subscript DIM of ARRAY if
3045 dimension DIM of ARRAY does not have extent zero
3046 or if ARRAY is an assumed-size array of rank DIM,
3047 or (b) 1 otherwise.
3048
3049 13.14.113: Result value for UBOUND
3050
3051 Case (i): For an array section or for an array expression other than a
3052 whole array or array structure component, UBOUND(ARRAY, DIM)
3053 has the value equal to the number of elements in the given
3054 dimension; otherwise, it has a value equal to the upper bound
3055 for subscript DIM of ARRAY if dimension DIM of ARRAY does
3056 not have size zero and has value zero if dimension DIM has
3057 size zero. */
3058
1af78e73 3059 if (op == GFC_ISYM_LBOUND && assumed_rank_lb_one)
63fbf586
TB
3060 se->expr = gfc_index_one_node;
3061 else if (as)
ac677cc8 3062 {
1af78e73 3063 if (op == GFC_ISYM_UBOUND)
ac677cc8 3064 {
1af78e73
SL
3065 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3066 size, gfc_index_zero_node);
3067 se->expr = fold_build3_loc (input_location, COND_EXPR,
3068 gfc_array_index_type, cond,
3069 (assumed_rank_lb_one ? size : ubound),
3070 gfc_index_zero_node);
3071 }
3072 else if (op == GFC_ISYM_LBOUND)
3073 {
3074 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3075 size, gfc_index_zero_node);
3076 if (as->type == AS_ASSUMED_SIZE)
63fbf586 3077 {
1af78e73
SL
3078 cond1 = fold_build2_loc (input_location, EQ_EXPR,
3079 logical_type_node, bound,
3080 build_int_cst (TREE_TYPE (bound),
3081 arg->expr->rank - 1));
3082 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3083 logical_type_node, cond, cond1);
63fbf586 3084 }
433ce291
TB
3085 se->expr = fold_build3_loc (input_location, COND_EXPR,
3086 gfc_array_index_type, cond,
1af78e73 3087 lbound, gfc_index_one_node);
ac677cc8 3088 }
1af78e73
SL
3089 else if (op == GFC_ISYM_SHAPE)
3090 se->expr = size;
ac677cc8 3091 else
1af78e73 3092 gcc_unreachable ();
ac677cc8 3093
1af78e73
SL
3094 /* According to F2018 16.9.172, para 5, an assumed rank object,
3095 argument associated with and assumed size array, has the ubound
3096 of the final dimension set to -1 and UBOUND must return this.
3097 Similarly for the SHAPE intrinsic. */
3098 if (op != GFC_ISYM_LBOUND && assumed_rank_lb_one)
3099 {
3100 tree minus_one = build_int_cst (gfc_array_index_type, -1);
3101 tree rank = fold_convert (gfc_array_index_type,
3102 gfc_conv_descriptor_rank (desc));
3103 rank = fold_build2_loc (input_location, PLUS_EXPR,
3104 gfc_array_index_type, rank, minus_one);
3105
3106 /* Fix the expression to stop it from becoming even more
3107 complicated. */
3108 se->expr = gfc_evaluate_now (se->expr, &se->pre);
3109
3110 /* Descriptors for assumed-size arrays have ubound = -1
3111 in the last dimension. */
3112 cond1 = fold_build2_loc (input_location, EQ_EXPR,
3113 logical_type_node, ubound, minus_one);
3114 cond = fold_build2_loc (input_location, EQ_EXPR,
3115 logical_type_node, bound, rank);
3116 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 3117 logical_type_node, cond, cond1);
433ce291
TB
3118 se->expr = fold_build3_loc (input_location, COND_EXPR,
3119 gfc_array_index_type, cond,
1af78e73 3120 minus_one, se->expr);
ac677cc8
FXC
3121 }
3122 }
1af78e73 3123 else /* as is null; this is an old-fashioned 1-based array. */
ac677cc8 3124 {
1af78e73 3125 if (op != GFC_ISYM_LBOUND)
ac677cc8 3126 {
433ce291 3127 se->expr = fold_build2_loc (input_location, MAX_EXPR,
1af78e73 3128 gfc_array_index_type, size,
433ce291 3129 gfc_index_zero_node);
ac677cc8
FXC
3130 }
3131 else
3132 se->expr = gfc_index_one_node;
3133 }
6de9cd9a 3134
0e308880 3135
6de9cd9a
DN
3136 type = gfc_typenode_for_spec (&expr->ts);
3137 se->expr = convert (type, se->expr);
3138}
3139
3140
a3935ffc
TB
3141static void
3142conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
3143{
3144 gfc_actual_arglist *arg;
3145 gfc_actual_arglist *arg2;
3146 gfc_se argse;
a3935ffc
TB
3147 tree bound, resbound, resbound2, desc, cond, tmp;
3148 tree type;
a3935ffc
TB
3149 int corank;
3150
3151 gcc_assert (expr->value.function.isym->id == GFC_ISYM_LCOBOUND
3152 || expr->value.function.isym->id == GFC_ISYM_UCOBOUND
3153 || expr->value.function.isym->id == GFC_ISYM_THIS_IMAGE);
3154
3155 arg = expr->value.function.actual;
3156 arg2 = arg->next;
3157
3158 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
3159 corank = gfc_get_corank (arg->expr);
3160
a3935ffc 3161 gfc_init_se (&argse, NULL);
23c3d0f9 3162 argse.want_coarray = 1;
a3935ffc 3163
2960a368 3164 gfc_conv_expr_descriptor (&argse, arg->expr);
a3935ffc
TB
3165 gfc_add_block_to_block (&se->pre, &argse.pre);
3166 gfc_add_block_to_block (&se->post, &argse.post);
3167 desc = argse.expr;
3168
3169 if (se->ss)
3170 {
a3935ffc
TB
3171 /* Create an implicit second parameter from the loop variable. */
3172 gcc_assert (!arg2->expr);
3173 gcc_assert (corank > 0);
3174 gcc_assert (se->loop->dimen == 1);
f98cfd3c 3175 gcc_assert (se->ss->info->expr == expr);
a3935ffc 3176
a3935ffc 3177 bound = se->loop->loopvar[0];
155e5d5f 3178 bound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
0e3184ac 3179 bound, gfc_rank_cst[arg->expr->rank]);
a3935ffc
TB
3180 gfc_advance_se_ss_chain (se);
3181 }
3182 else
3183 {
3184 /* use the passed argument. */
3185 gcc_assert (arg2->expr);
3186 gfc_init_se (&argse, NULL);
3187 gfc_conv_expr_type (&argse, arg2->expr, gfc_array_index_type);
3188 gfc_add_block_to_block (&se->pre, &argse.pre);
3189 bound = argse.expr;
3190
3191 if (INTEGER_CST_P (bound))
3192 {
8e6cdc90
RS
3193 if (wi::ltu_p (wi::to_wide (bound), 1)
3194 || wi::gtu_p (wi::to_wide (bound),
3195 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))))
a4d9b221 3196 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
a3935ffc
TB
3197 "dimension index", expr->value.function.isym->name,
3198 &expr->where);
3199 }
3200 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3201 {
3202 bound = gfc_evaluate_now (bound, &se->pre);
63ee5404 3203 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
155e5d5f 3204 bound, build_int_cst (TREE_TYPE (bound), 1));
a3935ffc 3205 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc))];
63ee5404 3206 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
155e5d5f
TB
3207 bound, tmp);
3208 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
63ee5404 3209 logical_type_node, cond, tmp);
a3935ffc
TB
3210 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
3211 gfc_msg_fault);
3212 }
3213
3214
eea58adb 3215 /* Subtract 1 to get to zero based and add dimensions. */
a3935ffc
TB
3216 switch (arg->expr->rank)
3217 {
3218 case 0:
155e5d5f
TB
3219 bound = fold_build2_loc (input_location, MINUS_EXPR,
3220 gfc_array_index_type, bound,
3221 gfc_index_one_node);
a3935ffc
TB
3222 case 1:
3223 break;
3224 default:
155e5d5f
TB
3225 bound = fold_build2_loc (input_location, PLUS_EXPR,
3226 gfc_array_index_type, bound,
3227 gfc_rank_cst[arg->expr->rank - 1]);
a3935ffc
TB
3228 }
3229 }
3230
3231 resbound = gfc_conv_descriptor_lbound_get (desc, bound);
3232
155e5d5f 3233 /* Handle UCOBOUND with special handling of the last codimension. */
a3935ffc
TB
3234 if (expr->value.function.isym->id == GFC_ISYM_UCOBOUND)
3235 {
155e5d5f
TB
3236 /* Last codimension: For -fcoarray=single just return
3237 the lcobound - otherwise add
3238 ceiling (real (num_images ()) / real (size)) - 1
3239 = (num_images () + size - 1) / size - 1
3240 = (num_images - 1) / size(),
5af07930 3241 where size is the product of the extent of all but the last
155e5d5f
TB
3242 codimension. */
3243
f19626cf 3244 if (flag_coarray != GFC_FCOARRAY_SINGLE && corank > 1)
155e5d5f
TB
3245 {
3246 tree cosize;
3247
155e5d5f 3248 cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
a8a5f4a9
TB
3249 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3250 2, integer_zero_node,
3251 build_int_cst (integer_type_node, -1));
155e5d5f
TB
3252 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3253 gfc_array_index_type,
a8a5f4a9 3254 fold_convert (gfc_array_index_type, tmp),
155e5d5f
TB
3255 build_int_cst (gfc_array_index_type, 1));
3256 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
3257 gfc_array_index_type, tmp,
3258 fold_convert (gfc_array_index_type, cosize));
3259 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3260 gfc_array_index_type, resbound, tmp);
3261 }
f19626cf 3262 else if (flag_coarray != GFC_FCOARRAY_SINGLE)
155e5d5f
TB
3263 {
3264 /* ubound = lbound + num_images() - 1. */
a8a5f4a9
TB
3265 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
3266 2, integer_zero_node,
3267 build_int_cst (integer_type_node, -1));
155e5d5f
TB
3268 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3269 gfc_array_index_type,
a8a5f4a9 3270 fold_convert (gfc_array_index_type, tmp),
155e5d5f
TB
3271 build_int_cst (gfc_array_index_type, 1));
3272 resbound = fold_build2_loc (input_location, PLUS_EXPR,
3273 gfc_array_index_type, resbound, tmp);
3274 }
3275
3276 if (corank > 1)
3277 {
63ee5404 3278 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
155e5d5f
TB
3279 bound,
3280 build_int_cst (TREE_TYPE (bound),
3281 arg->expr->rank + corank - 1));
3282
3283 resbound2 = gfc_conv_descriptor_ubound_get (desc, bound);
3284 se->expr = fold_build3_loc (input_location, COND_EXPR,
3285 gfc_array_index_type, cond,
3286 resbound, resbound2);
3287 }
3288 else
3289 se->expr = resbound;
a3935ffc
TB
3290 }
3291 else
3292 se->expr = resbound;
3293
3294 type = gfc_typenode_for_spec (&expr->ts);
3295 se->expr = convert (type, se->expr);
3296}
3297
3298
0881224e
TB
3299static void
3300conv_intrinsic_stride (gfc_se * se, gfc_expr * expr)
3301{
3302 gfc_actual_arglist *array_arg;
3303 gfc_actual_arglist *dim_arg;
3304 gfc_se argse;
3305 tree desc, tmp;
3306
3307 array_arg = expr->value.function.actual;
3308 dim_arg = array_arg->next;
3309
3310 gcc_assert (array_arg->expr->expr_type == EXPR_VARIABLE);
3311
3312 gfc_init_se (&argse, NULL);
3313 gfc_conv_expr_descriptor (&argse, array_arg->expr);
3314 gfc_add_block_to_block (&se->pre, &argse.pre);
3315 gfc_add_block_to_block (&se->post, &argse.post);
3316 desc = argse.expr;
3317
3318 gcc_assert (dim_arg->expr);
3319 gfc_init_se (&argse, NULL);
3320 gfc_conv_expr_type (&argse, dim_arg->expr, gfc_array_index_type);
3321 gfc_add_block_to_block (&se->pre, &argse.pre);
3322 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3323 argse.expr, gfc_index_one_node);
3324 se->expr = gfc_conv_descriptor_stride_get (desc, tmp);
3325}
3326
6de9cd9a
DN
3327static void
3328gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
3329{
2921157d 3330 tree arg, cabs;
6de9cd9a 3331
55637e51 3332 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6de9cd9a
DN
3333
3334 switch (expr->value.function.actual->expr->ts.type)
3335 {
3336 case BT_INTEGER:
3337 case BT_REAL:
433ce291
TB
3338 se->expr = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (arg),
3339 arg);
6de9cd9a
DN
3340 break;
3341
3342 case BT_COMPLEX:
166d08bd 3343 cabs = gfc_builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
2921157d 3344 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
6de9cd9a
DN
3345 break;
3346
3347 default:
6e45f57b 3348 gcc_unreachable ();
6de9cd9a
DN
3349 }
3350}
3351
3352
3353/* Create a complex value from one or two real components. */
3354
3355static void
3356gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
3357{
6de9cd9a
DN
3358 tree real;
3359 tree imag;
3360 tree type;
55637e51
LM
3361 tree *args;
3362 unsigned int num_args;
3363
3364 num_args = gfc_intrinsic_argument_list_length (expr);
1145e690 3365 args = XALLOCAVEC (tree, num_args);
6de9cd9a
DN
3366
3367 type = gfc_typenode_for_spec (&expr->ts);
55637e51
LM
3368 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3369 real = convert (TREE_TYPE (type), args[0]);
6de9cd9a 3370 if (both)
55637e51
LM
3371 imag = convert (TREE_TYPE (type), args[1]);
3372 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
6de9cd9a 3373 {
433ce291
TB
3374 imag = fold_build1_loc (input_location, IMAGPART_EXPR,
3375 TREE_TYPE (TREE_TYPE (args[0])), args[0]);
6de9cd9a
DN
3376 imag = convert (TREE_TYPE (type), imag);
3377 }
3378 else
3379 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
3380
433ce291 3381 se->expr = fold_build2_loc (input_location, COMPLEX_EXPR, type, real, imag);
6de9cd9a
DN
3382}
3383
4ecad771 3384
e98a8b5b 3385/* Remainder function MOD(A, P) = A - INT(A / P) * P
029b2d55 3386 MODULO(A, P) = A - FLOOR (A / P) * P
4ecad771
JB
3387
3388 The obvious algorithms above are numerically instable for large
3389 arguments, hence these intrinsics are instead implemented via calls
3390 to the fmod family of functions. It is the responsibility of the
3391 user to ensure that the second argument is non-zero. */
6de9cd9a
DN
3392
3393static void
3394gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
3395{
6de9cd9a 3396 tree type;
6de9cd9a 3397 tree tmp;
6de9cd9a
DN
3398 tree test;
3399 tree test2;
2921157d 3400 tree fmod;
4ecad771 3401 tree zero;
55637e51 3402 tree args[2];
6de9cd9a 3403
55637e51 3404 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6de9cd9a
DN
3405
3406 switch (expr->ts.type)
3407 {
3408 case BT_INTEGER:
3409 /* Integer case is easy, we've got a builtin op. */
55637e51 3410 type = TREE_TYPE (args[0]);
58b6e047 3411
e98a8b5b 3412 if (modulo)
433ce291
TB
3413 se->expr = fold_build2_loc (input_location, FLOOR_MOD_EXPR, type,
3414 args[0], args[1]);
e98a8b5b 3415 else
433ce291
TB
3416 se->expr = fold_build2_loc (input_location, TRUNC_MOD_EXPR, type,
3417 args[0], args[1]);
6de9cd9a
DN
3418 break;
3419
3420 case BT_REAL:
2921157d 3421 fmod = NULL_TREE;
58b6e047 3422 /* Check if we have a builtin fmod. */
166d08bd 3423 fmod = gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
58b6e047 3424
4ecad771
JB
3425 /* The builtin should always be available. */
3426 gcc_assert (fmod != NULL_TREE);
3427
aa00059c 3428 tmp = build_addr (fmod);
4ecad771 3429 se->expr = build_call_array_loc (input_location,
2921157d 3430 TREE_TYPE (TREE_TYPE (fmod)),
55637e51 3431 tmp, 2, args);
4ecad771
JB
3432 if (modulo == 0)
3433 return;
58b6e047 3434
55637e51 3435 type = TREE_TYPE (args[0]);
58b6e047 3436
55637e51
LM
3437 args[0] = gfc_evaluate_now (args[0], &se->pre);
3438 args[1] = gfc_evaluate_now (args[1], &se->pre);
6de9cd9a 3439
58b6e047 3440 /* Definition:
4ecad771
JB
3441 modulo = arg - floor (arg/arg2) * arg2
3442
3443 In order to calculate the result accurately, we use the fmod
3444 function as follows.
029b2d55 3445
4ecad771
JB
3446 res = fmod (arg, arg2);
3447 if (res)
3448 {
3449 if ((arg < 0) xor (arg2 < 0))
3450 res += arg2;
3451 }
3452 else
3453 res = copysign (0., arg2);
3454
3455 => As two nested ternary exprs:
3456
029b2d55 3457 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
4ecad771
JB
3458 : copysign (0., arg2);
3459
3460 */
3461
3462 zero = gfc_build_const (type, integer_zero_node);
3463 tmp = gfc_evaluate_now (se->expr, &se->pre);
3464 if (!flag_signed_zeros)
58b6e047 3465 {
63ee5404 3466 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
433ce291 3467 args[0], zero);
63ee5404 3468 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
433ce291
TB
3469 args[1], zero);
3470 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
63ee5404
JB
3471 logical_type_node, test, test2);
3472 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
433ce291
TB
3473 tmp, zero);
3474 test = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 3475 logical_type_node, test, test2);
58b6e047 3476 test = gfc_evaluate_now (test, &se->pre);
433ce291 3477 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
029b2d55 3478 fold_build2_loc (input_location,
4ecad771 3479 PLUS_EXPR,
029b2d55 3480 type, tmp, args[1]),
4ecad771 3481 tmp);
58b6e047 3482 }
4ecad771 3483 else
3e7cb1c7 3484 {
4ecad771 3485 tree expr1, copysign, cscall;
029b2d55 3486 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN,
4ecad771 3487 expr->ts.kind);
63ee5404 3488 test = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
4ecad771 3489 args[0], zero);
63ee5404 3490 test2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
4ecad771
JB
3491 args[1], zero);
3492 test2 = fold_build2_loc (input_location, TRUTH_XOR_EXPR,
63ee5404 3493 logical_type_node, test, test2);
4ecad771 3494 expr1 = fold_build3_loc (input_location, COND_EXPR, type, test2,
029b2d55 3495 fold_build2_loc (input_location,
4ecad771 3496 PLUS_EXPR,
029b2d55 3497 type, tmp, args[1]),
4ecad771 3498 tmp);
63ee5404 3499 test = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
4ecad771 3500 tmp, zero);
029b2d55 3501 cscall = build_call_expr_loc (input_location, copysign, 2, zero,
4ecad771
JB
3502 args[1]);
3503 se->expr = fold_build3_loc (input_location, COND_EXPR, type, test,
3504 expr1, cscall);
3e7cb1c7 3505 }
4ecad771 3506 return;
6de9cd9a
DN
3507
3508 default:
6e45f57b 3509 gcc_unreachable ();
6de9cd9a 3510 }
6de9cd9a
DN
3511}
3512
88a95a11
FXC
3513/* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3514 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3515 where the right shifts are logical (i.e. 0's are shifted in).
3516 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3517 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3518 DSHIFTL(I,J,0) = I
3519 DSHIFTL(I,J,BITSIZE) = J
3520 DSHIFTR(I,J,0) = J
3521 DSHIFTR(I,J,BITSIZE) = I. */
3522
3523static void
3524gfc_conv_intrinsic_dshift (gfc_se * se, gfc_expr * expr, bool dshiftl)
3525{
3526 tree type, utype, stype, arg1, arg2, shift, res, left, right;
3527 tree args[3], cond, tmp;
3528 int bitsize;
3529
3530 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3531
3532 gcc_assert (TREE_TYPE (args[0]) == TREE_TYPE (args[1]));
3533 type = TREE_TYPE (args[0]);
3534 bitsize = TYPE_PRECISION (type);
3535 utype = unsigned_type_for (type);
3536 stype = TREE_TYPE (args[2]);
3537
3538 arg1 = gfc_evaluate_now (args[0], &se->pre);
3539 arg2 = gfc_evaluate_now (args[1], &se->pre);
3540 shift = gfc_evaluate_now (args[2], &se->pre);
3541
3542 /* The generic case. */
3543 tmp = fold_build2_loc (input_location, MINUS_EXPR, stype,
3544 build_int_cst (stype, bitsize), shift);
3545 left = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3546 arg1, dshiftl ? shift : tmp);
3547
3548 right = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
3549 fold_convert (utype, arg2), dshiftl ? tmp : shift);
3550 right = fold_convert (type, right);
3551
3552 res = fold_build2_loc (input_location, BIT_IOR_EXPR, type, left, right);
3553
3554 /* Special cases. */
63ee5404 3555 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
88a95a11
FXC
3556 build_int_cst (stype, 0));
3557 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3558 dshiftl ? arg1 : arg2, res);
3559
63ee5404 3560 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, shift,
88a95a11
FXC
3561 build_int_cst (stype, bitsize));
3562 res = fold_build3_loc (input_location, COND_EXPR, type, cond,
3563 dshiftl ? arg2 : arg1, res);
3564
3565 se->expr = res;
3566}
3567
3568
6de9cd9a
DN
3569/* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3570
3571static void
3572gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
3573{
6de9cd9a
DN
3574 tree val;
3575 tree tmp;
3576 tree type;
3577 tree zero;
55637e51 3578 tree args[2];
6de9cd9a 3579
55637e51
LM
3580 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3581 type = TREE_TYPE (args[0]);
6de9cd9a 3582
433ce291 3583 val = fold_build2_loc (input_location, MINUS_EXPR, type, args[0], args[1]);
6de9cd9a
DN
3584 val = gfc_evaluate_now (val, &se->pre);
3585
3586 zero = gfc_build_const (type, integer_zero_node);
63ee5404 3587 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node, val, zero);
433ce291 3588 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, zero, val);
6de9cd9a
DN
3589}
3590
3591
3592/* SIGN(A, B) is absolute value of A times sign of B.
3593 The real value versions use library functions to ensure the correct
3594 handling of negative zero. Integer case implemented as:
0eadc091 3595 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
6de9cd9a
DN
3596 */
3597
3598static void
3599gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
3600{
3601 tree tmp;
6de9cd9a 3602 tree type;
55637e51 3603 tree args[2];
6de9cd9a 3604
55637e51 3605 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6de9cd9a
DN
3606 if (expr->ts.type == BT_REAL)
3607 {
60d340ef
TB
3608 tree abs;
3609
166d08bd
FXC
3610 tmp = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
3611 abs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
60d340ef
TB
3612
3613 /* We explicitly have to ignore the minus sign. We do so by using
3614 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
c61819ff 3615 if (!flag_sign_zero
60d340ef
TB
3616 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
3617 {
3618 tree cond, zero;
3619 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
63ee5404 3620 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
433ce291
TB
3621 args[1], zero);
3622 se->expr = fold_build3_loc (input_location, COND_EXPR,
3623 TREE_TYPE (args[0]), cond,
65a9ca82
TB
3624 build_call_expr_loc (input_location, abs, 1,
3625 args[0]),
3626 build_call_expr_loc (input_location, tmp, 2,
3627 args[0], args[1]));
60d340ef
TB
3628 }
3629 else
2921157d
FXC
3630 se->expr = build_call_expr_loc (input_location, tmp, 2,
3631 args[0], args[1]);
6de9cd9a
DN
3632 return;
3633 }
3634
0eadc091
RS
3635 /* Having excluded floating point types, we know we are now dealing
3636 with signed integer types. */
55637e51 3637 type = TREE_TYPE (args[0]);
6de9cd9a 3638
55637e51
LM
3639 /* Args[0] is used multiple times below. */
3640 args[0] = gfc_evaluate_now (args[0], &se->pre);
0eadc091
RS
3641
3642 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3643 the signs of A and B are the same, and of all ones if they differ. */
433ce291
TB
3644 tmp = fold_build2_loc (input_location, BIT_XOR_EXPR, type, args[0], args[1]);
3645 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, tmp,
3646 build_int_cst (type, TYPE_PRECISION (type) - 1));
0eadc091
RS
3647 tmp = gfc_evaluate_now (tmp, &se->pre);
3648
3649 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3650 is all ones (i.e. -1). */
433ce291
TB
3651 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, type,
3652 fold_build2_loc (input_location, PLUS_EXPR,
3653 type, args[0], tmp), tmp);
6de9cd9a
DN
3654}
3655
3656
3657/* Test for the presence of an optional argument. */
3658
3659static void
3660gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
3661{
3662 gfc_expr *arg;
3663
3664 arg = expr->value.function.actual->expr;
6e45f57b 3665 gcc_assert (arg->expr_type == EXPR_VARIABLE);
6de9cd9a
DN
3666 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
3667 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3668}
3669
3670
3671/* Calculate the double precision product of two single precision values. */
3672
3673static void
3674gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
3675{
6de9cd9a 3676 tree type;
55637e51 3677 tree args[2];
6de9cd9a 3678
55637e51 3679 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6de9cd9a
DN
3680
3681 /* Convert the args to double precision before multiplying. */
3682 type = gfc_typenode_for_spec (&expr->ts);
55637e51
LM
3683 args[0] = convert (type, args[0]);
3684 args[1] = convert (type, args[1]);
433ce291
TB
3685 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, args[0],
3686 args[1]);
6de9cd9a
DN
3687}
3688
3689
3690/* Return a length one character string containing an ascii character. */
3691
3692static void
3693gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
3694{
c2408681 3695 tree arg[2];
6de9cd9a
DN
3696 tree var;
3697 tree type;
c2408681 3698 unsigned int num_args;
6de9cd9a 3699
c2408681
PT
3700 num_args = gfc_intrinsic_argument_list_length (expr);
3701 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
6de9cd9a 3702
d393bbd7 3703 type = gfc_get_char_type (expr->ts.kind);
6de9cd9a
DN
3704 var = gfc_create_var (type, "char");
3705
433ce291 3706 arg[0] = fold_build1_loc (input_location, NOP_EXPR, type, arg[0]);
726a989a 3707 gfc_add_modify (&se->pre, var, arg[0]);
6de9cd9a 3708 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
86e033e2 3709 se->string_length = build_int_cst (gfc_charlen_type_node, 1);
6de9cd9a
DN
3710}
3711
3712
35059811
FXC
3713static void
3714gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
3715{
3716 tree var;
3717 tree len;
3718 tree tmp;
35059811 3719 tree cond;
55637e51
LM
3720 tree fndecl;
3721 tree *args;
3722 unsigned int num_args;
3723
3724 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1145e690 3725 args = XALLOCAVEC (tree, num_args);
35059811 3726
691da334 3727 var = gfc_create_var (pchar_type_node, "pstr");
8e421af9 3728 len = gfc_create_var (gfc_charlen_type_node, "len");
35059811 3729
55637e51 3730 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
628c189e
RG
3731 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3732 args[1] = gfc_build_addr_expr (NULL_TREE, len);
35059811 3733
aa00059c 3734 fndecl = build_addr (gfor_fndecl_ctime);
db3927fb
AH
3735 tmp = build_call_array_loc (input_location,
3736 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
55637e51 3737 fndecl, num_args, args);
35059811
FXC
3738 gfc_add_expr_to_block (&se->pre, tmp);
3739
3740 /* Free the temporary afterwards, if necessary. */
63ee5404 3741 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
433ce291 3742 len, build_int_cst (TREE_TYPE (len), 0));
1529b8d9 3743 tmp = gfc_call_free (var);
c2255bc4 3744 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
35059811
FXC
3745 gfc_add_expr_to_block (&se->post, tmp);
3746
3747 se->expr = var;
3748 se->string_length = len;
3749}
3750
3751
3752static void
3753gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
3754{
3755 tree var;
3756 tree len;
3757 tree tmp;
35059811 3758 tree cond;
55637e51
LM
3759 tree fndecl;
3760 tree *args;
3761 unsigned int num_args;
3762
3763 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1145e690 3764 args = XALLOCAVEC (tree, num_args);
35059811 3765
691da334 3766 var = gfc_create_var (pchar_type_node, "pstr");
6cd8d93a 3767 len = gfc_create_var (gfc_charlen_type_node, "len");
35059811 3768
55637e51 3769 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
628c189e
RG
3770 args[0] = gfc_build_addr_expr (NULL_TREE, var);
3771 args[1] = gfc_build_addr_expr (NULL_TREE, len);
35059811 3772
aa00059c 3773 fndecl = build_addr (gfor_fndecl_fdate);
db3927fb
AH
3774 tmp = build_call_array_loc (input_location,
3775 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
55637e51 3776 fndecl, num_args, args);
35059811
FXC
3777 gfc_add_expr_to_block (&se->pre, tmp);
3778
3779 /* Free the temporary afterwards, if necessary. */
63ee5404 3780 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
433ce291 3781 len, build_int_cst (TREE_TYPE (len), 0));
1529b8d9 3782 tmp = gfc_call_free (var);
c2255bc4 3783 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
35059811
FXC
3784 gfc_add_expr_to_block (&se->post, tmp);
3785
3786 se->expr = var;
3787 se->string_length = len;
3788}
3789
3790
8b40ca6a
FXC
3791/* Generate a direct call to free() for the FREE subroutine. */
3792
3793static tree
3794conv_intrinsic_free (gfc_code *code)
3795{
3796 stmtblock_t block;
3797 gfc_se argse;
3798 tree arg, call;
3799
3800 gfc_init_se (&argse, NULL);
3801 gfc_conv_expr (&argse, code->ext.actual->expr);
3802 arg = fold_convert (ptr_type_node, argse.expr);
3803
3804 gfc_init_block (&block);
3805 call = build_call_expr_loc (input_location,
3806 builtin_decl_explicit (BUILT_IN_FREE), 1, arg);
3807 gfc_add_expr_to_block (&block, call);
3808 return gfc_finish_block (&block);
3809}
3810
3811
ddd3e26e
SK
3812/* Call the RANDOM_INIT library subroutine with a hidden argument for
3813 handling seeding on coarray images. */
3814
3815static tree
3816conv_intrinsic_random_init (gfc_code *code)
3817{
3818 stmtblock_t block;
3819 gfc_se se;
26ca6dbd
AV
3820 tree arg1, arg2, tmp;
3821 /* On none coarray == lib compiles use LOGICAL(4) else regular LOGICAL. */
3822 tree used_bool_type_node = flag_coarray == GFC_FCOARRAY_LIB
3823 ? logical_type_node
3824 : gfc_get_logical_type (4);
ddd3e26e
SK
3825
3826 /* Make the function call. */
3827 gfc_init_block (&block);
3828 gfc_init_se (&se, NULL);
3829
26ca6dbd 3830 /* Convert REPEATABLE to the desired LOGICAL entity. */
ddd3e26e
SK
3831 gfc_conv_expr (&se, code->ext.actual->expr);
3832 gfc_add_block_to_block (&block, &se.pre);
26ca6dbd 3833 arg1 = fold_convert (used_bool_type_node, gfc_evaluate_now (se.expr, &block));
ddd3e26e
SK
3834 gfc_add_block_to_block (&block, &se.post);
3835
26ca6dbd 3836 /* Convert IMAGE_DISTINCT to the desired LOGICAL entity. */
ddd3e26e
SK
3837 gfc_conv_expr (&se, code->ext.actual->next->expr);
3838 gfc_add_block_to_block (&block, &se.pre);
26ca6dbd 3839 arg2 = fold_convert (used_bool_type_node, gfc_evaluate_now (se.expr, &block));
ddd3e26e
SK
3840 gfc_add_block_to_block (&block, &se.post);
3841
ddd3e26e
SK
3842 if (flag_coarray == GFC_FCOARRAY_LIB)
3843 {
26ca6dbd
AV
3844 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_random_init,
3845 2, arg1, arg2);
3846 }
3847 else
3848 {
3849 /* The ABI for libgfortran needs to be maintained, so a hidden
3850 argument must be include if code is compiled with -fcoarray=single
3851 or without the option. Set to 0. */
3852 tree arg3 = build_int_cst (gfc_get_int_type (4), 0);
3853 tmp = build_call_expr_loc (input_location, gfor_fndecl_random_init,
3854 3, arg1, arg2, arg3);
ddd3e26e
SK
3855 }
3856
ddd3e26e 3857 gfc_add_expr_to_block (&block, tmp);
9a8013d1 3858
ddd3e26e
SK
3859 return gfc_finish_block (&block);
3860}
3861
3862
a416c4c7
FXC
3863/* Call the SYSTEM_CLOCK library functions, handling the type and kind
3864 conversions. */
3865
3866static tree
3867conv_intrinsic_system_clock (gfc_code *code)
3868{
3869 stmtblock_t block;
3870 gfc_se count_se, count_rate_se, count_max_se;
3871 tree arg1 = NULL_TREE, arg2 = NULL_TREE, arg3 = NULL_TREE;
65263c1f
JD
3872 tree tmp;
3873 int least;
a416c4c7
FXC
3874
3875 gfc_expr *count = code->ext.actual->expr;
3876 gfc_expr *count_rate = code->ext.actual->next->expr;
3877 gfc_expr *count_max = code->ext.actual->next->next->expr;
3878
a416c4c7
FXC
3879 /* Evaluate our arguments. */
3880 if (count)
3881 {
3882 gfc_init_se (&count_se, NULL);
3883 gfc_conv_expr (&count_se, count);
3884 }
3885
3886 if (count_rate)
3887 {
3888 gfc_init_se (&count_rate_se, NULL);
3889 gfc_conv_expr (&count_rate_se, count_rate);
3890 }
3891
3892 if (count_max)
3893 {
3894 gfc_init_se (&count_max_se, NULL);
3895 gfc_conv_expr (&count_max_se, count_max);
3896 }
3897
65263c1f
JD
3898 /* Find the smallest kind found of the arguments. */
3899 least = 16;
3900 least = (count && count->ts.kind < least) ? count->ts.kind : least;
3901 least = (count_rate && count_rate->ts.kind < least) ? count_rate->ts.kind
3902 : least;
3903 least = (count_max && count_max->ts.kind < least) ? count_max->ts.kind
3904 : least;
3905
3906 /* Prepare temporary variables. */
3907
3908 if (count)
3909 {
3910 if (least >= 8)
3911 arg1 = gfc_create_var (gfc_get_int_type (8), "count");
3912 else if (least == 4)
3913 arg1 = gfc_create_var (gfc_get_int_type (4), "count");
3914 else if (count->ts.kind == 1)
3915 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[0].pedantic_min_int,
3916 count->ts.kind);
3917 else
3918 arg1 = gfc_conv_mpz_to_tree (gfc_integer_kinds[1].pedantic_min_int,
3919 count->ts.kind);
3920 }
a416c4c7 3921
65263c1f
JD
3922 if (count_rate)
3923 {
3924 if (least >= 8)
3925 arg2 = gfc_create_var (gfc_get_int_type (8), "count_rate");
3926 else if (least == 4)
3927 arg2 = gfc_create_var (gfc_get_int_type (4), "count_rate");
3928 else
3929 arg2 = integer_zero_node;
3930 }
a416c4c7 3931
65263c1f
JD
3932 if (count_max)
3933 {
3934 if (least >= 8)
3935 arg3 = gfc_create_var (gfc_get_int_type (8), "count_max");
3936 else if (least == 4)
3937 arg3 = gfc_create_var (gfc_get_int_type (4), "count_max");
3938 else
3939 arg3 = integer_zero_node;
3940 }
a416c4c7 3941
1cc0e193 3942 /* Make the function call. */
a416c4c7 3943 gfc_init_block (&block);
65263c1f
JD
3944
3945if (least <= 2)
3946 {
3947 if (least == 1)
3948 {
3949 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3950 : null_pointer_node;
3951 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3952 : null_pointer_node;
3953 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3954 : null_pointer_node;
3955 }
34d9d749 3956
65263c1f
JD
3957 if (least == 2)
3958 {
3959 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3960 : null_pointer_node;
3961 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3962 : null_pointer_node;
3963 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3964 : null_pointer_node;
3965 }
3966 }
3967else
3968 {
3969 if (least == 4)
3970 {
3971 tmp = build_call_expr_loc (input_location,
3972 gfor_fndecl_system_clock4, 3,
3973 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3974 : null_pointer_node,
3975 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3976 : null_pointer_node,
3977 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3978 : null_pointer_node);
3979 gfc_add_expr_to_block (&block, tmp);
3980 }
3981 /* Handle kind>=8, 10, or 16 arguments */
3982 if (least >= 8)
3983 {
3984 tmp = build_call_expr_loc (input_location,
3985 gfor_fndecl_system_clock8, 3,
3986 arg1 ? gfc_build_addr_expr (NULL_TREE, arg1)
3987 : null_pointer_node,
3988 arg2 ? gfc_build_addr_expr (NULL_TREE, arg2)
3989 : null_pointer_node,
3990 arg3 ? gfc_build_addr_expr (NULL_TREE, arg3)
3991 : null_pointer_node);
3992 gfc_add_expr_to_block (&block, tmp);
3993 }
3994 }
a416c4c7
FXC
3995
3996 /* And store values back if needed. */
3997 if (arg1 && arg1 != count_se.expr)
3998 gfc_add_modify (&block, count_se.expr,
3999 fold_convert (TREE_TYPE (count_se.expr), arg1));
4000 if (arg2 && arg2 != count_rate_se.expr)
4001 gfc_add_modify (&block, count_rate_se.expr,
4002 fold_convert (TREE_TYPE (count_rate_se.expr), arg2));
4003 if (arg3 && arg3 != count_max_se.expr)
4004 gfc_add_modify (&block, count_max_se.expr,
4005 fold_convert (TREE_TYPE (count_max_se.expr), arg3));
4006
4007 return gfc_finish_block (&block);
4008}
4009
4010
25fc05eb
FXC
4011/* Return a character string containing the tty name. */
4012
4013static void
4014gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
4015{
4016 tree var;
4017 tree len;
4018 tree tmp;
25fc05eb 4019 tree cond;
55637e51 4020 tree fndecl;
55637e51
LM
4021 tree *args;
4022 unsigned int num_args;
4023
4024 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1145e690 4025 args = XALLOCAVEC (tree, num_args);
25fc05eb 4026
691da334 4027 var = gfc_create_var (pchar_type_node, "pstr");
6cd8d93a 4028 len = gfc_create_var (gfc_charlen_type_node, "len");
25fc05eb 4029
55637e51 4030 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
628c189e
RG
4031 args[0] = gfc_build_addr_expr (NULL_TREE, var);
4032 args[1] = gfc_build_addr_expr (NULL_TREE, len);
25fc05eb 4033
aa00059c 4034 fndecl = build_addr (gfor_fndecl_ttynam);
db3927fb
AH
4035 tmp = build_call_array_loc (input_location,
4036 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
55637e51 4037 fndecl, num_args, args);
25fc05eb
FXC
4038 gfc_add_expr_to_block (&se->pre, tmp);
4039
4040 /* Free the temporary afterwards, if necessary. */
63ee5404 4041 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
433ce291 4042 len, build_int_cst (TREE_TYPE (len), 0));
1529b8d9 4043 tmp = gfc_call_free (var);
c2255bc4 4044 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
25fc05eb
FXC
4045 gfc_add_expr_to_block (&se->post, tmp);
4046
4047 se->expr = var;
4048 se->string_length = len;
4049}
4050
4051
6de9cd9a
DN
4052/* Get the minimum/maximum value of all the parameters.
4053 minmax (a1, a2, a3, ...)
4054 {
7af6648c 4055 mvar = a1;
e0c27d52
KT
4056 mvar = COMP (mvar, a2)
4057 mvar = COMP (mvar, a3)
6de9cd9a 4058 ...
e0c27d52 4059 return mvar;
6de9cd9a 4060 }
e0c27d52
KT
4061 Where COMP is MIN/MAX_EXPR for integral types or when we don't
4062 care about NaNs, or IFN_FMIN/MAX when the target has support for
4063 fast NaN-honouring min/max. When neither holds expand a sequence
4064 of explicit comparisons. */
6de9cd9a
DN
4065
4066/* TODO: Mismatching types can occur when specific names are used.
4067 These should be handled during resolution. */
4068static void
8fa2df72 4069gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
6de9cd9a 4070{
6de9cd9a
DN
4071 tree tmp;
4072 tree mvar;
4073 tree val;
55637e51 4074 tree *args;
6de9cd9a 4075 tree type;
3c04bd60 4076 tree argtype;
0160a2c7 4077 gfc_actual_arglist *argexpr;
7af6648c 4078 unsigned int i, nargs;
6de9cd9a 4079
55637e51 4080 nargs = gfc_intrinsic_argument_list_length (expr);
1145e690 4081 args = XALLOCAVEC (tree, nargs);
55637e51
LM
4082
4083 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6de9cd9a
DN
4084 type = gfc_typenode_for_spec (&expr->ts);
4085
6de9cd9a 4086 /* Only evaluate the argument once. */
d168c883 4087 if (!VAR_P (args[0]) && !TREE_CONSTANT (args[0]))
7af6648c 4088 args[0] = gfc_evaluate_now (args[0], &se->pre);
6de9cd9a 4089
3c04bd60
HA
4090 /* Determine suitable type of temporary, as a GNU extension allows
4091 different argument kinds. */
4092 argtype = TREE_TYPE (args[0]);
4093 argexpr = expr->value.function.actual;
4094 for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
4095 {
4096 tree tmptype = TREE_TYPE (args[i]);
4097 if (TYPE_PRECISION (tmptype) > TYPE_PRECISION (argtype))
4098 argtype = tmptype;
4099 }
4100 mvar = gfc_create_var (argtype, "M");
4101 gfc_add_modify (&se->pre, mvar, convert (argtype, args[0]));
0160a2c7 4102
3c04bd60 4103 argexpr = expr->value.function.actual;
e0c27d52
KT
4104 for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
4105 {
4106 tree cond = NULL_TREE;
029b2d55 4107 val = args[i];
6de9cd9a 4108
0160a2c7 4109 /* Handle absent optional arguments by ignoring the comparison. */
7af6648c 4110 if (argexpr->expr->expr_type == EXPR_VARIABLE
0160a2c7
FXC
4111 && argexpr->expr->symtree->n.sym->attr.optional
4112 && TREE_CODE (val) == INDIRECT_REF)
e0c27d52
KT
4113 {
4114 cond = fold_build2_loc (input_location,
63ee5404 4115 NE_EXPR, logical_type_node,
029b2d55 4116 TREE_OPERAND (val, 0),
db3927fb 4117 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
e0c27d52
KT
4118 }
4119 else if (!VAR_P (val) && !TREE_CONSTANT (val))
0160a2c7 4120 /* Only evaluate the argument once. */
e0c27d52 4121 val = gfc_evaluate_now (val, &se->pre);
6de9cd9a 4122
e0c27d52 4123 tree calc;
fa3d2d38
JB
4124 /* For floating point types, the question is what MAX(a, NaN) or
4125 MIN(a, NaN) should return (where "a" is a normal number).
4126 There are valid usecase for returning either one, but the
4127 Fortran standard doesn't specify which one should be chosen.
4128 Also, there is no consensus among other tested compilers. In
4129 short, it's a mess. So lets just do whatever is fastest. */
4130 tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR;
3c04bd60
HA
4131 calc = fold_build2_loc (input_location, code, argtype,
4132 convert (argtype, val), mvar);
fa3d2d38 4133 tmp = build2_v (MODIFY_EXPR, mvar, calc);
0160a2c7
FXC
4134
4135 if (cond != NULL_TREE)
c2255bc4
AH
4136 tmp = build3_v (COND_EXPR, cond, tmp,
4137 build_empty_stmt (input_location));
6de9cd9a 4138 gfc_add_expr_to_block (&se->pre, tmp);
6de9cd9a 4139 }
6fc54339 4140 se->expr = convert (type, mvar);
6de9cd9a
DN
4141}
4142
4143
2263c775
FXC
4144/* Generate library calls for MIN and MAX intrinsics for character
4145 variables. */
4146static void
4147gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
4148{
4149 tree *args;
374929b2 4150 tree var, len, fndecl, tmp, cond, function;
2263c775
FXC
4151 unsigned int nargs;
4152
4153 nargs = gfc_intrinsic_argument_list_length (expr);
1145e690 4154 args = XALLOCAVEC (tree, nargs + 4);
2263c775
FXC
4155 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
4156
4157 /* Create the result variables. */
4158 len = gfc_create_var (gfc_charlen_type_node, "len");
628c189e 4159 args[0] = gfc_build_addr_expr (NULL_TREE, len);
691da334 4160 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
2263c775 4161 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
df09d1d5
RG
4162 args[2] = build_int_cst (integer_type_node, op);
4163 args[3] = build_int_cst (integer_type_node, nargs / 2);
2263c775 4164
374929b2
FXC
4165 if (expr->ts.kind == 1)
4166 function = gfor_fndecl_string_minmax;
4167 else if (expr->ts.kind == 4)
4168 function = gfor_fndecl_string_minmax_char4;
4169 else
4170 gcc_unreachable ();
4171
2263c775 4172 /* Make the function call. */
aa00059c 4173 fndecl = build_addr (function);
db3927fb
AH
4174 tmp = build_call_array_loc (input_location,
4175 TREE_TYPE (TREE_TYPE (function)), fndecl,
374929b2 4176 nargs + 4, args);
2263c775
FXC
4177 gfc_add_expr_to_block (&se->pre, tmp);
4178
4179 /* Free the temporary afterwards, if necessary. */
63ee5404 4180 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
433ce291 4181 len, build_int_cst (TREE_TYPE (len), 0));
2263c775 4182 tmp = gfc_call_free (var);
c2255bc4 4183 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2263c775
FXC
4184 gfc_add_expr_to_block (&se->post, tmp);
4185
4186 se->expr = var;
4187 se->string_length = len;
4188}
4189
4190
4b9b6210
TS
4191/* Create a symbol node for this intrinsic. The symbol from the frontend
4192 has the generic name. */
6de9cd9a
DN
4193
4194static gfc_symbol *
8fdcb6a9 4195gfc_get_symbol_for_expr (gfc_expr * expr, bool ignore_optional)
6de9cd9a
DN
4196{
4197 gfc_symbol *sym;
4198
4199 /* TODO: Add symbols for intrinsic function to the global namespace. */
6e45f57b 4200 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
6de9cd9a
DN
4201 sym = gfc_new_symbol (expr->value.function.name, NULL);
4202
4203 sym->ts = expr->ts;
4204 sym->attr.external = 1;
4205 sym->attr.function = 1;
4206 sym->attr.always_explicit = 1;
4207 sym->attr.proc = PROC_INTRINSIC;
4208 sym->attr.flavor = FL_PROCEDURE;
4209 sym->result = sym;
4210 if (expr->rank > 0)
4211 {
4212 sym->attr.dimension = 1;
4213 sym->as = gfc_get_array_spec ();
4214 sym->as->type = AS_ASSUMED_SHAPE;
4215 sym->as->rank = expr->rank;
4216 }
4217
8fdcb6a9
TB
4218 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4219 ignore_optional ? expr->value.function.actual
4220 : NULL);
47b99694 4221
6de9cd9a
DN
4222 return sym;
4223}
4224
47d13acb
TK
4225/* Remove empty actual arguments. */
4226
4227static void
4228remove_empty_actual_arguments (gfc_actual_arglist **ap)
4229{
4230 while (*ap)
4231 {
4232 if ((*ap)->expr == NULL)
4233 {
4234 gfc_actual_arglist *r = *ap;
4235 *ap = r->next;
4236 r->next = NULL;
4237 gfc_free_actual_arglist (r);
4238 }
4239 else
4240 ap = &((*ap)->next);
4241 }
4242}
4243
36ec54aa
TK
4244#define MAX_SPEC_ARG 12
4245
4246/* Make up an fn spec that's right for intrinsic functions that we
4247 want to call. */
4248
4249static char *
4250intrinsic_fnspec (gfc_expr *expr)
4251{
4252 static char fnspec_buf[MAX_SPEC_ARG*2+1];
4253 char *fp;
4254 int i;
4255 int num_char_args;
4256
4257#define ADD_CHAR(c) do { *fp++ = c; *fp++ = ' '; } while(0)
4258
4259 /* Set the fndecl. */
4260 fp = fnspec_buf;
4261 /* Function return value. FIXME: Check if the second letter could
4262 be something other than a space, for further optimization. */
4263 ADD_CHAR ('.');
4264 if (expr->rank == 0)
4265 {
4266 if (expr->ts.type == BT_CHARACTER)
4267 {
4268 ADD_CHAR ('w'); /* Address of character. */
4269 ADD_CHAR ('.'); /* Length of character. */
4270 }
4271 }
4272 else
4273 ADD_CHAR ('w'); /* Return value is a descriptor. */
4274
4275 num_char_args = 0;
4276 for (gfc_actual_arglist *a = expr->value.function.actual; a; a = a->next)
4277 {
4278 if (a->expr == NULL)
4279 continue;
4280
4281 if (a->name && strcmp (a->name,"%VAL") == 0)
4282 ADD_CHAR ('.');
4283 else
4284 {
4285 if (a->expr->rank > 0)
4286 ADD_CHAR ('r');
4287 else
4288 ADD_CHAR ('R');
4289 }
4290 num_char_args += a->expr->ts.type == BT_CHARACTER;
4291 gcc_assert (fp - fnspec_buf + num_char_args <= MAX_SPEC_ARG*2);
4292 }
4293
4294 for (i = 0; i < num_char_args; i++)
4295 ADD_CHAR ('.');
4296
4297 *fp = '\0';
4298 return fnspec_buf;
4299}
4300
4301#undef MAX_SPEC_ARG
4302#undef ADD_CHAR
4303
47d13acb
TK
4304/* Generate the right symbol for the specific intrinsic function and
4305 modify the expr accordingly. This assumes that absent optional
36ec54aa 4306 arguments should be removed. */
47d13acb
TK
4307
4308gfc_symbol *
4309specific_intrinsic_symbol (gfc_expr *expr)
4310{
4311 gfc_symbol *sym;
4312
4313 sym = gfc_find_intrinsic_symbol (expr);
4314 if (sym == NULL)
4315 {
4316 sym = gfc_get_intrinsic_function_symbol (expr);
4317 sym->ts = expr->ts;
4318 if (sym->ts.type == BT_CHARACTER && sym->ts.u.cl)
4319 sym->ts.u.cl = gfc_new_charlen (sym->ns, NULL);
4320
4321 gfc_copy_formal_args_intr (sym, expr->value.function.isym,
4322 expr->value.function.actual, true);
4323 sym->backend_decl
36ec54aa
TK
4324 = gfc_get_extern_function_decl (sym, expr->value.function.actual,
4325 intrinsic_fnspec (expr));
47d13acb 4326 }
36ec54aa 4327
47d13acb
TK
4328 remove_empty_actual_arguments (&(expr->value.function.actual));
4329
4330 return sym;
4331}
4332
36ec54aa
TK
4333/* Generate a call to an external intrinsic function. FIXME: So far,
4334 this only works for functions which are called with well-defined
4335 types; CSHIFT and friends will come later. */
4336
6de9cd9a
DN
4337static void
4338gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
4339{
4340 gfc_symbol *sym;
9771b263 4341 vec<tree, va_gc> *append_args;
47d13acb 4342 bool specific_symbol;
6de9cd9a 4343
f98cfd3c 4344 gcc_assert (!se->ss || se->ss->info->expr == expr);
6de9cd9a
DN
4345
4346 if (se->ss)
6e45f57b 4347 gcc_assert (expr->rank > 0);
6de9cd9a 4348 else
6e45f57b 4349 gcc_assert (expr->rank == 0);
6de9cd9a 4350
47d13acb
TK
4351 switch (expr->value.function.isym->id)
4352 {
36ec54aa
TK
4353 case GFC_ISYM_ANY:
4354 case GFC_ISYM_ALL:
47d13acb
TK
4355 case GFC_ISYM_FINDLOC:
4356 case GFC_ISYM_MAXLOC:
4357 case GFC_ISYM_MINLOC:
4358 case GFC_ISYM_MAXVAL:
4359 case GFC_ISYM_MINVAL:
36ec54aa
TK
4360 case GFC_ISYM_NORM2:
4361 case GFC_ISYM_PRODUCT:
4362 case GFC_ISYM_SUM:
47d13acb
TK
4363 specific_symbol = true;
4364 break;
4365 default:
4366 specific_symbol = false;
4367 }
4368
4369 if (specific_symbol)
4370 {
4371 /* Need to copy here because specific_intrinsic_symbol modifies
4372 expr to omit the absent optional arguments. */
4373 expr = gfc_copy_expr (expr);
4374 sym = specific_intrinsic_symbol (expr);
4375 }
4376 else
4377 sym = gfc_get_symbol_for_expr (expr, se->ignore_optional);
5a0aad31
FXC
4378
4379 /* Calls to libgfortran_matmul need to be appended special arguments,
4380 to be able to call the BLAS ?gemm functions if required and possible. */
989ea525 4381 append_args = NULL;
cd5ecab6 4382 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
998511a6 4383 && !expr->external_blas
5a0aad31
FXC
4384 && sym->ts.type != BT_LOGICAL)
4385 {
4386 tree cint = gfc_get_int_type (gfc_c_int_kind);
4387
c61819ff 4388 if (flag_external_blas
5a0aad31 4389 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
3dcdfdc8 4390 && (sym->ts.kind == 4 || sym->ts.kind == 8))
5a0aad31
FXC
4391 {
4392 tree gemm_fndecl;
4393
4394 if (sym->ts.type == BT_REAL)
4395 {
3dcdfdc8 4396 if (sym->ts.kind == 4)
5a0aad31
FXC
4397 gemm_fndecl = gfor_fndecl_sgemm;
4398 else
4399 gemm_fndecl = gfor_fndecl_dgemm;
4400 }
4401 else
4402 {
3dcdfdc8 4403 if (sym->ts.kind == 4)
5a0aad31
FXC
4404 gemm_fndecl = gfor_fndecl_cgemm;
4405 else
4406 gemm_fndecl = gfor_fndecl_zgemm;
4407 }
4408
9771b263
DN
4409 vec_alloc (append_args, 3);
4410 append_args->quick_push (build_int_cst (cint, 1));
4411 append_args->quick_push (build_int_cst (cint,
c61819ff 4412 flag_blas_matmul_limit));
9771b263
DN
4413 append_args->quick_push (gfc_build_addr_expr (NULL_TREE,
4414 gemm_fndecl));
5a0aad31
FXC
4415 }
4416 else
4417 {
9771b263
DN
4418 vec_alloc (append_args, 3);
4419 append_args->quick_push (build_int_cst (cint, 0));
4420 append_args->quick_push (build_int_cst (cint, 0));
4421 append_args->quick_push (null_pointer_node);
5a0aad31
FXC
4422 }
4423 }
4424
713485cc
JW
4425 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
4426 append_args);
47d13acb
TK
4427
4428 if (specific_symbol)
4429 gfc_free_expr (expr);
4430 else
4431 gfc_free_symbol (sym);
6de9cd9a
DN
4432}
4433
4434/* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4435 Implemented as
4436 any(a)
4437 {
4438 forall (i=...)
4439 if (a[i] != 0)
4440 return 1
4441 end forall
4442 return 0
4443 }
4444 all(a)
4445 {
4446 forall (i=...)
4447 if (a[i] == 0)
4448 return 0
4449 end forall
4450 return 1
4451 }
4452 */
4453static void
8fa2df72 4454gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
6de9cd9a
DN
4455{
4456 tree resvar;
4457 stmtblock_t block;
4458 stmtblock_t body;
4459 tree type;
4460 tree tmp;
4461 tree found;
4462 gfc_loopinfo loop;
4463 gfc_actual_arglist *actual;
4464 gfc_ss *arrayss;
4465 gfc_se arrayse;
4466 tree exit_label;
4467
4468 if (se->ss)
4469 {
4470 gfc_conv_intrinsic_funcall (se, expr);
4471 return;
4472 }
4473
4474 actual = expr->value.function.actual;
4475 type = gfc_typenode_for_spec (&expr->ts);
4476 /* Initialize the result. */
4477 resvar = gfc_create_var (type, "test");
4478 if (op == EQ_EXPR)
4479 tmp = convert (type, boolean_true_node);
4480 else
4481 tmp = convert (type, boolean_false_node);
726a989a 4482 gfc_add_modify (&se->pre, resvar, tmp);
6de9cd9a
DN
4483
4484 /* Walk the arguments. */
4485 arrayss = gfc_walk_expr (actual->expr);
6e45f57b 4486 gcc_assert (arrayss != gfc_ss_terminator);
6de9cd9a
DN
4487
4488 /* Initialize the scalarizer. */
4489 gfc_init_loopinfo (&loop);
4490 exit_label = gfc_build_label_decl (NULL_TREE);
4491 TREE_USED (exit_label) = 1;
4492 gfc_add_ss_to_loop (&loop, arrayss);
4493
4494 /* Initialize the loop. */
4495 gfc_conv_ss_startstride (&loop);
bdfd2ff0 4496 gfc_conv_loop_setup (&loop, &expr->where);
6de9cd9a
DN
4497
4498 gfc_mark_ss_chain_used (arrayss, 1);
4499 /* Generate the loop body. */
4500 gfc_start_scalarized_body (&loop, &body);
4501
4502 /* If the condition matches then set the return value. */
4503 gfc_start_block (&block);
4504 if (op == EQ_EXPR)
4505 tmp = convert (type, boolean_false_node);
4506 else
4507 tmp = convert (type, boolean_true_node);
726a989a 4508 gfc_add_modify (&block, resvar, tmp);
6de9cd9a
DN
4509
4510 /* And break out of the loop. */
4511 tmp = build1_v (GOTO_EXPR, exit_label);
4512 gfc_add_expr_to_block (&block, tmp);
4513
4514 found = gfc_finish_block (&block);
4515
4516 /* Check this element. */
4517 gfc_init_se (&arrayse, NULL);
4518 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4519 arrayse.ss = arrayss;
4520 gfc_conv_expr_val (&arrayse, actual->expr);
4521
4522 gfc_add_block_to_block (&body, &arrayse.pre);
63ee5404 4523 tmp = fold_build2_loc (input_location, op, logical_type_node, arrayse.expr,
433ce291 4524 build_int_cst (TREE_TYPE (arrayse.expr), 0));
c2255bc4 4525 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
6de9cd9a
DN
4526 gfc_add_expr_to_block (&body, tmp);
4527 gfc_add_block_to_block (&body, &arrayse.post);
4528
4529 gfc_trans_scalarizing_loops (&loop, &body);
4530
4531 /* Add the exit label. */
4532 tmp = build1_v (LABEL_EXPR, exit_label);
4533 gfc_add_expr_to_block (&loop.pre, tmp);
4534
4535 gfc_add_block_to_block (&se->pre, &loop.pre);
4536 gfc_add_block_to_block (&se->pre, &loop.post);
4537 gfc_cleanup_loop (&loop);
4538
4539 se->expr = resvar;
4540}
4541
57391dda
FR
4542
4543/* Generate the constant 180 / pi, which is used in the conversion
4544 of acosd(), asind(), atand(), atan2d(). */
4545
4546static tree
4547rad2deg (int kind)
4548{
4549 tree retval;
4550 mpfr_t pi, t0;
4551
4552 gfc_set_model_kind (kind);
4553 mpfr_init (pi);
4554 mpfr_init (t0);
4555 mpfr_set_si (t0, 180, GFC_RND_MODE);
4556 mpfr_const_pi (pi, GFC_RND_MODE);
4557 mpfr_div (t0, t0, pi, GFC_RND_MODE);
4558 retval = gfc_conv_mpfr_to_tree (t0, kind, 0);
4559 mpfr_clear (t0);
4560 mpfr_clear (pi);
4561 return retval;
4562}
4563
4564
8fef6f72
HA
4565static gfc_intrinsic_map_t *
4566gfc_lookup_intrinsic (gfc_isym_id id)
4567{
4568 gfc_intrinsic_map_t *m = gfc_intrinsic_map;
4569 for (; m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
4570 if (id == m->id)
4571 break;
4572 gcc_assert (id == m->id);
4573 return m;
4574}
4575
4576
57391dda
FR
4577/* ACOSD(x) is translated into ACOS(x) * 180 / pi.
4578 ASIND(x) is translated into ASIN(x) * 180 / pi.
4579 ATAND(x) is translated into ATAN(x) * 180 / pi. */
4580
4581static void
4582gfc_conv_intrinsic_atrigd (gfc_se * se, gfc_expr * expr, gfc_isym_id id)
4583{
4584 tree arg;
4585 tree atrigd;
4586 tree type;
8fef6f72 4587 gfc_intrinsic_map_t *m;
57391dda
FR
4588
4589 type = gfc_typenode_for_spec (&expr->ts);
4590
4591 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4592
8fef6f72
HA
4593 switch (id)
4594 {
4595 case GFC_ISYM_ACOSD:
4596 m = gfc_lookup_intrinsic (GFC_ISYM_ACOS);
4597 break;
4598 case GFC_ISYM_ASIND:
4599 m = gfc_lookup_intrinsic (GFC_ISYM_ASIN);
4600 break;
4601 case GFC_ISYM_ATAND:
4602 m = gfc_lookup_intrinsic (GFC_ISYM_ATAN);
4603 break;
4604 default:
4605 gcc_unreachable ();
4606 }
4607 atrigd = gfc_get_intrinsic_lib_fndecl (m, expr);
57391dda
FR
4608 atrigd = build_call_expr_loc (input_location, atrigd, 1, arg);
4609
4610 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atrigd,
4611 fold_convert (type, rad2deg (expr->ts.kind)));
4612}
4613
4614
4615/* COTAN(X) is translated into -TAN(X+PI/2) for REAL argument and
4616 COS(X) / SIN(X) for COMPLEX argument. */
4617
4618static void
4619gfc_conv_intrinsic_cotan (gfc_se *se, gfc_expr *expr)
4620{
4621 gfc_intrinsic_map_t *m;
4622 tree arg;
4623 tree type;
4624
4625 type = gfc_typenode_for_spec (&expr->ts);
4626 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4627
4628 if (expr->ts.type == BT_REAL)
4629 {
4630 tree tan;
4631 tree tmp;
4632 mpfr_t pio2;
4633
4634 /* Create pi/2. */
4635 gfc_set_model_kind (expr->ts.kind);
4636 mpfr_init (pio2);
4637 mpfr_const_pi (pio2, GFC_RND_MODE);
4638 mpfr_div_ui (pio2, pio2, 2, GFC_RND_MODE);
4639 tmp = gfc_conv_mpfr_to_tree (pio2, expr->ts.kind, 0);
4640 mpfr_clear (pio2);
4641
4642 /* Find tan builtin function. */
8fef6f72 4643 m = gfc_lookup_intrinsic (GFC_ISYM_TAN);
57391dda 4644 tan = gfc_get_intrinsic_lib_fndecl (m, expr);
8fef6f72 4645 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, arg, tmp);
57391dda
FR
4646 tan = build_call_expr_loc (input_location, tan, 1, tmp);
4647 se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tan);
4648 }
4649 else
4650 {
4651 tree sin;
4652 tree cos;
4653
4654 /* Find cos builtin function. */
8fef6f72 4655 m = gfc_lookup_intrinsic (GFC_ISYM_COS);
57391dda
FR
4656 cos = gfc_get_intrinsic_lib_fndecl (m, expr);
4657 cos = build_call_expr_loc (input_location, cos, 1, arg);
4658
4659 /* Find sin builtin function. */
8fef6f72 4660 m = gfc_lookup_intrinsic (GFC_ISYM_SIN);
57391dda
FR
4661 sin = gfc_get_intrinsic_lib_fndecl (m, expr);
4662 sin = build_call_expr_loc (input_location, sin, 1, arg);
4663
4664 /* Divide cos by sin. */
4665 se->expr = fold_build2_loc (input_location, RDIV_EXPR, type, cos, sin);
4666 }
4667}
4668
4669
4670/* COTAND(X) is translated into -TAND(X+90) for REAL argument. */
4671
4672static void
4673gfc_conv_intrinsic_cotand (gfc_se *se, gfc_expr *expr)
4674{
4675 tree arg;
4676 tree type;
4677 tree ninety_tree;
4678 mpfr_t ninety;
4679
4680 type = gfc_typenode_for_spec (&expr->ts);
4681 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
4682
4683 gfc_set_model_kind (expr->ts.kind);
4684
4685 /* Build the tree for x + 90. */
4686 mpfr_init_set_ui (ninety, 90, GFC_RND_MODE);
4687 ninety_tree = gfc_conv_mpfr_to_tree (ninety, expr->ts.kind, 0);
4688 arg = fold_build2_loc (input_location, PLUS_EXPR, type, arg, ninety_tree);
4689 mpfr_clear (ninety);
4690
4691 /* Find tand. */
8fef6f72 4692 gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_TAND);
57391dda
FR
4693 tree tand = gfc_get_intrinsic_lib_fndecl (m, expr);
4694 tand = build_call_expr_loc (input_location, tand, 1, arg);
4695
4696 se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tand);
4697}
4698
4699
4700/* ATAN2D(Y,X) is translated into ATAN2(Y,X) * 180 / PI. */
4701
4702static void
4703gfc_conv_intrinsic_atan2d (gfc_se *se, gfc_expr *expr)
4704{
4705 tree args[2];
4706 tree atan2d;
4707 tree type;
4708
4709 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4710 type = TREE_TYPE (args[0]);
4711
8fef6f72
HA
4712 gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_ATAN2);
4713 atan2d = gfc_get_intrinsic_lib_fndecl (m, expr);
57391dda
FR
4714 atan2d = build_call_expr_loc (input_location, atan2d, 2, args[0], args[1]);
4715
4716 se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atan2d,
4717 rad2deg (expr->ts.kind));
4718}
4719
4720
6de9cd9a
DN
4721/* COUNT(A) = Number of true elements in A. */
4722static void
4723gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
4724{
4725 tree resvar;
4726 tree type;
4727 stmtblock_t body;
4728 tree tmp;
4729 gfc_loopinfo loop;
4730 gfc_actual_arglist *actual;
4731 gfc_ss *arrayss;
4732 gfc_se arrayse;
4733
4734 if (se->ss)
4735 {
4736 gfc_conv_intrinsic_funcall (se, expr);
4737 return;
4738 }
4739
4740 actual = expr->value.function.actual;
4741
4742 type = gfc_typenode_for_spec (&expr->ts);
4743 /* Initialize the result. */
4744 resvar = gfc_create_var (type, "count");
726a989a 4745 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
6de9cd9a
DN
4746
4747 /* Walk the arguments. */
4748 arrayss = gfc_walk_expr (actual->expr);
6e45f57b 4749 gcc_assert (arrayss != gfc_ss_terminator);
6de9cd9a
DN
4750
4751 /* Initialize the scalarizer. */
4752 gfc_init_loopinfo (&loop);
4753 gfc_add_ss_to_loop (&loop, arrayss);
4754
4755 /* Initialize the loop. */
4756 gfc_conv_ss_startstride (&loop);
bdfd2ff0 4757 gfc_conv_loop_setup (&loop, &expr->where);
6de9cd9a
DN
4758
4759 gfc_mark_ss_chain_used (arrayss, 1);
4760 /* Generate the loop body. */
4761 gfc_start_scalarized_body (&loop, &body);
4762
433ce291
TB
4763 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (resvar),
4764 resvar, build_int_cst (TREE_TYPE (resvar), 1));
923ab88c 4765 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
6de9cd9a
DN
4766
4767 gfc_init_se (&arrayse, NULL);
4768 gfc_copy_loopinfo_to_se (&arrayse, &loop);
4769 arrayse.ss = arrayss;
4770 gfc_conv_expr_val (&arrayse, actual->expr);
c2255bc4
AH
4771 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
4772 build_empty_stmt (input_location));
6de9cd9a
DN
4773
4774 gfc_add_block_to_block (&body, &arrayse.pre);
4775 gfc_add_expr_to_block (&body, tmp);
4776 gfc_add_block_to_block (&body, &arrayse.post);
4777
4778 gfc_trans_scalarizing_loops (&loop, &body);
4779
4780 gfc_add_block_to_block (&se->pre, &loop.pre);
4781 gfc_add_block_to_block (&se->pre, &loop.post);
4782 gfc_cleanup_loop (&loop);
4783
4784 se->expr = resvar;
4785}
4786
0c08de8f
MM
4787
4788/* Update given gfc_se to have ss component pointing to the nested gfc_ss
4789 struct and return the corresponding loopinfo. */
4790
4791static gfc_loopinfo *
4792enter_nested_loop (gfc_se *se)
4793{
4794 se->ss = se->ss->nested_ss;
4795 gcc_assert (se->ss == se->ss->loop->ss);
4796
4797 return se->ss->loop;
4798}
4799
2ea47ee9
TK
4800/* Build the condition for a mask, which may be optional. */
4801
4802static tree
4803conv_mask_condition (gfc_se *maskse, gfc_expr *maskexpr,
4804 bool optional_mask)
4805{
4806 tree present;
4807 tree type;
4808
4809 if (optional_mask)
4810 {
4811 type = TREE_TYPE (maskse->expr);
4812 present = gfc_conv_expr_present (maskexpr->symtree->n.sym);
4813 present = convert (type, present);
4814 present = fold_build1_loc (input_location, TRUTH_NOT_EXPR, type,
4815 present);
4816 return fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
4817 type, present, maskse->expr);
4818 }
4819 else
4820 return maskse->expr;
4821}
0c08de8f 4822
6de9cd9a
DN
4823/* Inline implementation of the sum and product intrinsics. */
4824static void
0cd0559e
TB
4825gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
4826 bool norm2)
6de9cd9a
DN
4827{
4828 tree resvar;
0cd0559e 4829 tree scale = NULL_TREE;
6de9cd9a
DN
4830 tree type;
4831 stmtblock_t body;
4832 stmtblock_t block;
4833 tree tmp;
b1a65f62 4834 gfc_loopinfo loop, *ploop;
bc4b3d2d 4835 gfc_actual_arglist *arg_array, *arg_mask;
0c08de8f
MM
4836 gfc_ss *arrayss = NULL;
4837 gfc_ss *maskss = NULL;
6de9cd9a
DN
4838 gfc_se arrayse;
4839 gfc_se maskse;
44d23d9e 4840 gfc_se *parent_se;
6de9cd9a
DN
4841 gfc_expr *arrayexpr;
4842 gfc_expr *maskexpr;
2ea47ee9 4843 bool optional_mask;
6de9cd9a 4844
0c08de8f 4845 if (expr->rank > 0)
6de9cd9a 4846 {
0c08de8f
MM
4847 gcc_assert (gfc_inline_intrinsic_function_p (expr));
4848 parent_se = se;
6de9cd9a 4849 }
44d23d9e
MM
4850 else
4851 parent_se = NULL;
6de9cd9a
DN
4852
4853 type = gfc_typenode_for_spec (&expr->ts);
4854 /* Initialize the result. */
4855 resvar = gfc_create_var (type, "val");
0cd0559e
TB
4856 if (norm2)
4857 {
4858 /* result = 0.0;
4859 scale = 1.0. */
4860 scale = gfc_create_var (type, "scale");
4861 gfc_add_modify (&se->pre, scale,
4862 gfc_build_const (type, integer_one_node));
4863 tmp = gfc_build_const (type, integer_zero_node);
4864 }
195a95c4 4865 else if (op == PLUS_EXPR || op == BIT_IOR_EXPR || op == BIT_XOR_EXPR)
6de9cd9a 4866 tmp = gfc_build_const (type, integer_zero_node);
0cd0559e
TB
4867 else if (op == NE_EXPR)
4868 /* PARITY. */
4869 tmp = convert (type, boolean_false_node);
195a95c4
TB
4870 else if (op == BIT_AND_EXPR)
4871 tmp = gfc_build_const (type, fold_build1_loc (input_location, NEGATE_EXPR,
4872 type, integer_one_node));
6de9cd9a
DN
4873 else
4874 tmp = gfc_build_const (type, integer_one_node);
4875
726a989a 4876 gfc_add_modify (&se->pre, resvar, tmp);
6de9cd9a 4877
bc4b3d2d
MM
4878 arg_array = expr->value.function.actual;
4879
bc4b3d2d 4880 arrayexpr = arg_array->expr;
6de9cd9a 4881
0cd0559e 4882 if (op == NE_EXPR || norm2)
2ea47ee9
TK
4883 {
4884 /* PARITY and NORM2. */
4885 maskexpr = NULL;
4886 optional_mask = false;
4887 }
0cd0559e
TB
4888 else
4889 {
bc4b3d2d
MM
4890 arg_mask = arg_array->next->next;
4891 gcc_assert (arg_mask != NULL);
4892 maskexpr = arg_mask->expr;
2ea47ee9
TK
4893 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
4894 && maskexpr->symtree->n.sym->attr.dummy
4895 && maskexpr->symtree->n.sym->attr.optional;
0cd0559e
TB
4896 }
4897
0c08de8f 4898 if (expr->rank == 0)
6de9cd9a 4899 {
0c08de8f
MM
4900 /* Walk the arguments. */
4901 arrayss = gfc_walk_expr (arrayexpr);
4902 gcc_assert (arrayss != gfc_ss_terminator);
6de9cd9a 4903
0c08de8f
MM
4904 if (maskexpr && maskexpr->rank > 0)
4905 {
4906 maskss = gfc_walk_expr (maskexpr);
4907 gcc_assert (maskss != gfc_ss_terminator);
4908 }
4909 else
4910 maskss = NULL;
6de9cd9a 4911
0c08de8f
MM
4912 /* Initialize the scalarizer. */
4913 gfc_init_loopinfo (&loop);
2ea47ee9
TK
4914
4915 /* We add the mask first because the number of iterations is
4916 taken from the last ss, and this breaks if an absent
4917 optional argument is used for mask. */
4918
0c08de8f
MM
4919 if (maskexpr && maskexpr->rank > 0)
4920 gfc_add_ss_to_loop (&loop, maskss);
2ea47ee9 4921 gfc_add_ss_to_loop (&loop, arrayss);
6de9cd9a 4922
0c08de8f
MM
4923 /* Initialize the loop. */
4924 gfc_conv_ss_startstride (&loop);
4925 gfc_conv_loop_setup (&loop, &expr->where);
4926
0c08de8f
MM
4927 if (maskexpr && maskexpr->rank > 0)
4928 gfc_mark_ss_chain_used (maskss, 1);
2ea47ee9 4929 gfc_mark_ss_chain_used (arrayss, 1);
0c08de8f
MM
4930
4931 ploop = &loop;
4932 }
4933 else
4934 /* All the work has been done in the parent loops. */
4935 ploop = enter_nested_loop (se);
4936
4937 gcc_assert (ploop);
b1a65f62 4938
6de9cd9a 4939 /* Generate the loop body. */
b1a65f62 4940 gfc_start_scalarized_body (ploop, &body);
6de9cd9a
DN
4941
4942 /* If we have a mask, only add this element if the mask is set. */
a831ffb8 4943 if (maskexpr && maskexpr->rank > 0)
6de9cd9a 4944 {
44d23d9e 4945 gfc_init_se (&maskse, parent_se);
b1a65f62 4946 gfc_copy_loopinfo_to_se (&maskse, ploop);
0c08de8f
MM
4947 if (expr->rank == 0)
4948 maskse.ss = maskss;
6de9cd9a
DN
4949 gfc_conv_expr_val (&maskse, maskexpr);
4950 gfc_add_block_to_block (&body, &maskse.pre);
4951
4952 gfc_start_block (&block);
4953 }
4954 else
4955 gfc_init_block (&block);
4956
4957 /* Do the actual summation/product. */
44d23d9e 4958 gfc_init_se (&arrayse, parent_se);
b1a65f62 4959 gfc_copy_loopinfo_to_se (&arrayse, ploop);
0c08de8f
MM
4960 if (expr->rank == 0)
4961 arrayse.ss = arrayss;
6de9cd9a
DN
4962 gfc_conv_expr_val (&arrayse, arrayexpr);
4963 gfc_add_block_to_block (&block, &arrayse.pre);
4964
0cd0559e
TB
4965 if (norm2)
4966 {
524af0d6 4967 /* if (x (i) != 0.0)
0cd0559e
TB
4968 {
4969 absX = abs(x(i))
4970 if (absX > scale)
4971 {
4972 val = scale/absX;
4973 result = 1.0 + result * val * val;
4974 scale = absX;
4975 }
4976 else
4977 {
4978 val = absX/scale;
4979 result += val * val;
4980 }
4981 } */
4982 tree res1, res2, cond, absX, val;
4983 stmtblock_t ifblock1, ifblock2, ifblock3;
4984
4985 gfc_init_block (&ifblock1);
4986
4987 absX = gfc_create_var (type, "absX");
4988 gfc_add_modify (&ifblock1, absX,
433ce291
TB
4989 fold_build1_loc (input_location, ABS_EXPR, type,
4990 arrayse.expr));
0cd0559e
TB
4991 val = gfc_create_var (type, "val");
4992 gfc_add_expr_to_block (&ifblock1, val);
4993
4994 gfc_init_block (&ifblock2);
4995 gfc_add_modify (&ifblock2, val,
433ce291
TB
4996 fold_build2_loc (input_location, RDIV_EXPR, type, scale,
4997 absX));
029b2d55 4998 res1 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
433ce291
TB
4999 res1 = fold_build2_loc (input_location, MULT_EXPR, type, resvar, res1);
5000 res1 = fold_build2_loc (input_location, PLUS_EXPR, type, res1,
5001 gfc_build_const (type, integer_one_node));
0cd0559e
TB
5002 gfc_add_modify (&ifblock2, resvar, res1);
5003 gfc_add_modify (&ifblock2, scale, absX);
029b2d55 5004 res1 = gfc_finish_block (&ifblock2);
0cd0559e
TB
5005
5006 gfc_init_block (&ifblock3);
5007 gfc_add_modify (&ifblock3, val,
433ce291
TB
5008 fold_build2_loc (input_location, RDIV_EXPR, type, absX,
5009 scale));
029b2d55 5010 res2 = fold_build2_loc (input_location, MULT_EXPR, type, val, val);
433ce291 5011 res2 = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, res2);
0cd0559e
TB
5012 gfc_add_modify (&ifblock3, resvar, res2);
5013 res2 = gfc_finish_block (&ifblock3);
5014
63ee5404 5015 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
433ce291 5016 absX, scale);
0cd0559e 5017 tmp = build3_v (COND_EXPR, cond, res1, res2);
029b2d55 5018 gfc_add_expr_to_block (&ifblock1, tmp);
0cd0559e
TB
5019 tmp = gfc_finish_block (&ifblock1);
5020
63ee5404 5021 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
433ce291
TB
5022 arrayse.expr,
5023 gfc_build_const (type, integer_zero_node));
0cd0559e
TB
5024
5025 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
029b2d55 5026 gfc_add_expr_to_block (&block, tmp);
0cd0559e
TB
5027 }
5028 else
5029 {
433ce291 5030 tmp = fold_build2_loc (input_location, op, type, resvar, arrayse.expr);
0cd0559e
TB
5031 gfc_add_modify (&block, resvar, tmp);
5032 }
5033
6de9cd9a
DN
5034 gfc_add_block_to_block (&block, &arrayse.post);
5035
a831ffb8 5036 if (maskexpr && maskexpr->rank > 0)
6de9cd9a 5037 {
2ea47ee9
TK
5038 /* We enclose the above in if (mask) {...} . If the mask is an
5039 optional argument, generate
5040 IF (.NOT. PRESENT(MASK) .OR. MASK(I)). */
5041 tree ifmask;
0cd0559e 5042 tmp = gfc_finish_block (&block);
2ea47ee9
TK
5043 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5044 tmp = build3_v (COND_EXPR, ifmask, tmp,
c2255bc4 5045 build_empty_stmt (input_location));
6de9cd9a
DN
5046 }
5047 else
5048 tmp = gfc_finish_block (&block);
5049 gfc_add_expr_to_block (&body, tmp);
5050
b1a65f62 5051 gfc_trans_scalarizing_loops (ploop, &body);
eaf618e3
TK
5052
5053 /* For a scalar mask, enclose the loop in an if statement. */
a831ffb8 5054 if (maskexpr && maskexpr->rank == 0)
eaf618e3 5055 {
eaf618e3 5056 gfc_init_block (&block);
b1a65f62
MM
5057 gfc_add_block_to_block (&block, &ploop->pre);
5058 gfc_add_block_to_block (&block, &ploop->post);
eaf618e3
TK
5059 tmp = gfc_finish_block (&block);
5060
0c08de8f
MM
5061 if (expr->rank > 0)
5062 {
5063 tmp = build3_v (COND_EXPR, se->ss->info->data.scalar.value, tmp,
5064 build_empty_stmt (input_location));
5065 gfc_advance_se_ss_chain (se);
5066 }
5067 else
5068 {
2ea47ee9
TK
5069 tree ifmask;
5070
0c08de8f
MM
5071 gcc_assert (expr->rank == 0);
5072 gfc_init_se (&maskse, NULL);
5073 gfc_conv_expr_val (&maskse, maskexpr);
2ea47ee9
TK
5074 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5075 tmp = build3_v (COND_EXPR, ifmask, tmp,
0c08de8f
MM
5076 build_empty_stmt (input_location));
5077 }
5078
eaf618e3
TK
5079 gfc_add_expr_to_block (&block, tmp);
5080 gfc_add_block_to_block (&se->pre, &block);
0c08de8f 5081 gcc_assert (se->post.head == NULL);
eaf618e3
TK
5082 }
5083 else
5084 {
b1a65f62
MM
5085 gfc_add_block_to_block (&se->pre, &ploop->pre);
5086 gfc_add_block_to_block (&se->pre, &ploop->post);
eaf618e3
TK
5087 }
5088
0c08de8f
MM
5089 if (expr->rank == 0)
5090 gfc_cleanup_loop (ploop);
6de9cd9a 5091
0cd0559e
TB
5092 if (norm2)
5093 {
5094 /* result = scale * sqrt(result). */
5095 tree sqrt;
166d08bd 5096 sqrt = gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
0cd0559e
TB
5097 resvar = build_call_expr_loc (input_location,
5098 sqrt, 1, resvar);
433ce291 5099 resvar = fold_build2_loc (input_location, MULT_EXPR, type, scale, resvar);
0cd0559e
TB
5100 }
5101
6de9cd9a
DN
5102 se->expr = resvar;
5103}
5104
61321991
PT
5105
5106/* Inline implementation of the dot_product intrinsic. This function
5107 is based on gfc_conv_intrinsic_arith (the previous function). */
5108static void
5109gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
5110{
5111 tree resvar;
5112 tree type;
5113 stmtblock_t body;
5114 stmtblock_t block;
5115 tree tmp;
5116 gfc_loopinfo loop;
5117 gfc_actual_arglist *actual;
5118 gfc_ss *arrayss1, *arrayss2;
5119 gfc_se arrayse1, arrayse2;
5120 gfc_expr *arrayexpr1, *arrayexpr2;
5121
5122 type = gfc_typenode_for_spec (&expr->ts);
5123
5124 /* Initialize the result. */
5125 resvar = gfc_create_var (type, "val");
5126 if (expr->ts.type == BT_LOGICAL)
19ee2065 5127 tmp = build_int_cst (type, 0);
61321991
PT
5128 else
5129 tmp = gfc_build_const (type, integer_zero_node);
5130
726a989a 5131 gfc_add_modify (&se->pre, resvar, tmp);
61321991
PT
5132
5133 /* Walk argument #1. */
5134 actual = expr->value.function.actual;
5135 arrayexpr1 = actual->expr;
5136 arrayss1 = gfc_walk_expr (arrayexpr1);
5137 gcc_assert (arrayss1 != gfc_ss_terminator);
5138
5139 /* Walk argument #2. */
5140 actual = actual->next;
5141 arrayexpr2 = actual->expr;
5142 arrayss2 = gfc_walk_expr (arrayexpr2);
5143 gcc_assert (arrayss2 != gfc_ss_terminator);
5144
5145 /* Initialize the scalarizer. */
5146 gfc_init_loopinfo (&loop);
5147 gfc_add_ss_to_loop (&loop, arrayss1);
5148 gfc_add_ss_to_loop (&loop, arrayss2);
5149
5150 /* Initialize the loop. */
5151 gfc_conv_ss_startstride (&loop);
bdfd2ff0 5152 gfc_conv_loop_setup (&loop, &expr->where);
61321991
PT
5153
5154 gfc_mark_ss_chain_used (arrayss1, 1);
5155 gfc_mark_ss_chain_used (arrayss2, 1);
5156
5157 /* Generate the loop body. */
5158 gfc_start_scalarized_body (&loop, &body);
5159 gfc_init_block (&block);
5160
5161 /* Make the tree expression for [conjg(]array1[)]. */
5162 gfc_init_se (&arrayse1, NULL);
5163 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
5164 arrayse1.ss = arrayss1;
5165 gfc_conv_expr_val (&arrayse1, arrayexpr1);
5166 if (expr->ts.type == BT_COMPLEX)
433ce291
TB
5167 arrayse1.expr = fold_build1_loc (input_location, CONJ_EXPR, type,
5168 arrayse1.expr);
61321991
PT
5169 gfc_add_block_to_block (&block, &arrayse1.pre);
5170
5171 /* Make the tree expression for array2. */
5172 gfc_init_se (&arrayse2, NULL);
5173 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
5174 arrayse2.ss = arrayss2;
5175 gfc_conv_expr_val (&arrayse2, arrayexpr2);
5176 gfc_add_block_to_block (&block, &arrayse2.pre);
5177
5178 /* Do the actual product and sum. */
5179 if (expr->ts.type == BT_LOGICAL)
5180 {
433ce291
TB
5181 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, type,
5182 arrayse1.expr, arrayse2.expr);
5183 tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, type, resvar, tmp);
61321991
PT
5184 }
5185 else
5186 {
433ce291
TB
5187 tmp = fold_build2_loc (input_location, MULT_EXPR, type, arrayse1.expr,
5188 arrayse2.expr);
5189 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, resvar, tmp);
61321991 5190 }
726a989a 5191 gfc_add_modify (&block, resvar, tmp);
61321991
PT
5192
5193 /* Finish up the loop block and the loop. */
5194 tmp = gfc_finish_block (&block);
5195 gfc_add_expr_to_block (&body, tmp);
5196
5197 gfc_trans_scalarizing_loops (&loop, &body);
5198 gfc_add_block_to_block (&se->pre, &loop.pre);
5199 gfc_add_block_to_block (&se->pre, &loop.post);
5200 gfc_cleanup_loop (&loop);
5201
5202 se->expr = resvar;
5203}
5204
5205
35d2c6b6
HA
5206/* Remove unneeded kind= argument from actual argument list when the
5207 result conversion is dealt with in a different place. */
5208
5209static void
5210strip_kind_from_actual (gfc_actual_arglist * actual)
5211{
5212 for (gfc_actual_arglist *a = actual; a; a = a->next)
5213 {
47d13acb 5214 if (a && a->name && strcmp (a->name, "kind") == 0)
35d2c6b6 5215 {
47d13acb
TK
5216 gfc_free_expr (a->expr);
5217 a->expr = NULL;
35d2c6b6
HA
5218 }
5219 }
5220}
5221
80927a56
JJ
5222/* Emit code for minloc or maxloc intrinsic. There are many different cases
5223 we need to handle. For performance reasons we sometimes create two
5224 loops instead of one, where the second one is much simpler.
5225 Examples for minloc intrinsic:
5226 1) Result is an array, a call is generated
5227 2) Array mask is used and NaNs need to be supported:
5228 limit = Infinity;
5229 pos = 0;
5230 S = from;
5231 while (S <= to) {
5232 if (mask[S]) {
5233 if (pos == 0) pos = S + (1 - from);
5234 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
5235 }
5236 S++;
5237 }
5238 goto lab2;
5239 lab1:;
5240 while (S <= to) {
5241 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
5242 S++;
5243 }
5244 lab2:;
5245 3) NaNs need to be supported, but it is known at compile time or cheaply
5246 at runtime whether array is nonempty or not:
5247 limit = Infinity;
5248 pos = 0;
5249 S = from;
5250 while (S <= to) {
5251 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
5252 S++;
5253 }
5254 if (from <= to) pos = 1;
5255 goto lab2;
5256 lab1:;
5257 while (S <= to) {
5258 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
5259 S++;
5260 }
5261 lab2:;
5262 4) NaNs aren't supported, array mask is used:
5263 limit = infinities_supported ? Infinity : huge (limit);
5264 pos = 0;
5265 S = from;
5266 while (S <= to) {
5267 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
5268 S++;
5269 }
5270 goto lab2;
5271 lab1:;
5272 while (S <= to) {
5273 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
5274 S++;
5275 }
5276 lab2:;
5277 5) Same without array mask:
5278 limit = infinities_supported ? Infinity : huge (limit);
5279 pos = (from <= to) ? 1 : 0;
5280 S = from;
5281 while (S <= to) {
5282 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
5283 S++;
5284 }
5285 For 3) and 5), if mask is scalar, this all goes into a conditional,
b573f931
TK
5286 setting pos = 0; in the else branch.
5287
5288 Since we now also support the BACK argument, instead of using
5289 if (a[S] < limit), we now use
5290
5291 if (back)
5292 cond = a[S] <= limit;
5293 else
5294 cond = a[S] < limit;
5295 if (cond) {
5296 ....
5297
5298 The optimizer is smart enough to move the condition out of the loop.
5299 The are now marked as unlikely to for further speedup. */
80927a56 5300
6de9cd9a 5301static void
8fa2df72 5302gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
6de9cd9a
DN
5303{
5304 stmtblock_t body;
5305 stmtblock_t block;
5306 stmtblock_t ifblock;
8cd25827 5307 stmtblock_t elseblock;
6de9cd9a
DN
5308 tree limit;
5309 tree type;
5310 tree tmp;
80927a56 5311 tree cond;
8cd25827 5312 tree elsetmp;
6de9cd9a 5313 tree ifbody;
f0b3c58d 5314 tree offset;
80927a56
JJ
5315 tree nonempty;
5316 tree lab1, lab2;
b573f931 5317 tree b_if, b_else;
6de9cd9a
DN
5318 gfc_loopinfo loop;
5319 gfc_actual_arglist *actual;
5320 gfc_ss *arrayss;
5321 gfc_ss *maskss;
5322 gfc_se arrayse;
5323 gfc_se maskse;
5324 gfc_expr *arrayexpr;
5325 gfc_expr *maskexpr;
b573f931
TK
5326 gfc_expr *backexpr;
5327 gfc_se backse;
6de9cd9a
DN
5328 tree pos;
5329 int n;
2ea47ee9 5330 bool optional_mask;
6de9cd9a 5331
64b1806b
TK
5332 actual = expr->value.function.actual;
5333
5334 /* The last argument, BACK, is passed by value. Ensure that
5335 by setting its name to %VAL. */
5336 for (gfc_actual_arglist *a = actual; a; a = a->next)
5337 {
5338 if (a->next == NULL)
5339 a->name = "%VAL";
5340 }
5341
6de9cd9a
DN
5342 if (se->ss)
5343 {
5344 gfc_conv_intrinsic_funcall (se, expr);
5345 return;
5346 }
5347
ddc9995b
TK
5348 arrayexpr = actual->expr;
5349
0ac74254 5350 /* Special case for character maxloc. Remove unneeded actual
ddc9995b 5351 arguments, then call a library function. */
f8862a1b 5352
ddc9995b
TK
5353 if (arrayexpr->ts.type == BT_CHARACTER)
5354 {
47d13acb 5355 gfc_actual_arglist *a;
64b1806b 5356 a = actual;
35d2c6b6 5357 strip_kind_from_actual (a);
47d13acb 5358 while (a)
ddc9995b 5359 {
47d13acb 5360 if (a->name && strcmp (a->name, "dim") == 0)
64b1806b 5361 {
47d13acb
TK
5362 gfc_free_expr (a->expr);
5363 a->expr = NULL;
64b1806b 5364 }
47d13acb 5365 a = a->next;
ddc9995b
TK
5366 }
5367 gfc_conv_intrinsic_funcall (se, expr);
5368 return;
5369 }
5370
6de9cd9a
DN
5371 /* Initialize the result. */
5372 pos = gfc_create_var (gfc_array_index_type, "pos");
f0b3c58d 5373 offset = gfc_create_var (gfc_array_index_type, "offset");
6de9cd9a
DN
5374 type = gfc_typenode_for_spec (&expr->ts);
5375
5376 /* Walk the arguments. */
6de9cd9a 5377 arrayss = gfc_walk_expr (arrayexpr);
6e45f57b 5378 gcc_assert (arrayss != gfc_ss_terminator);
6de9cd9a
DN
5379
5380 actual = actual->next->next;
6e45f57b 5381 gcc_assert (actual);
6de9cd9a 5382 maskexpr = actual->expr;
2ea47ee9
TK
5383 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
5384 && maskexpr->symtree->n.sym->attr.dummy
5385 && maskexpr->symtree->n.sym->attr.optional;
b573f931 5386 backexpr = actual->next->next->expr;
80927a56 5387 nonempty = NULL;
8cd25827 5388 if (maskexpr && maskexpr->rank != 0)
6de9cd9a
DN
5389 {
5390 maskss = gfc_walk_expr (maskexpr);
6e45f57b 5391 gcc_assert (maskss != gfc_ss_terminator);
6de9cd9a
DN
5392 }
5393 else
80927a56
JJ
5394 {
5395 mpz_t asize;
524af0d6 5396 if (gfc_array_size (arrayexpr, &asize))
80927a56
JJ
5397 {
5398 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
5399 mpz_clear (asize);
433ce291 5400 nonempty = fold_build2_loc (input_location, GT_EXPR,
63ee5404 5401 logical_type_node, nonempty,
433ce291 5402 gfc_index_zero_node);
80927a56
JJ
5403 }
5404 maskss = NULL;
5405 }
6de9cd9a
DN
5406
5407 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
6de9cd9a
DN
5408 switch (arrayexpr->ts.type)
5409 {
5410 case BT_REAL:
a67189d4 5411 tmp = gfc_build_inf_or_huge (TREE_TYPE (limit), arrayexpr->ts.kind);
6de9cd9a
DN
5412 break;
5413
5414 case BT_INTEGER:
a67189d4 5415 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
6de9cd9a
DN
5416 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
5417 arrayexpr->ts.kind);
5418 break;
5419
5420 default:
6e45f57b 5421 gcc_unreachable ();
6de9cd9a
DN
5422 }
5423
88116029
TB
5424 /* We start with the most negative possible value for MAXLOC, and the most
5425 positive possible value for MINLOC. The most negative possible value is
5426 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
66e4ab31 5427 possible value is HUGE in both cases. */
6de9cd9a 5428 if (op == GT_EXPR)
433ce291 5429 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
e1b7f42e 5430 if (op == GT_EXPR && arrayexpr->ts.type == BT_INTEGER)
433ce291 5431 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp), tmp,
e1b7f42e 5432 build_int_cst (TREE_TYPE (tmp), 1));
88116029 5433
258bd5dc
JJ
5434 gfc_add_modify (&se->pre, limit, tmp);
5435
6de9cd9a
DN
5436 /* Initialize the scalarizer. */
5437 gfc_init_loopinfo (&loop);
2ea47ee9
TK
5438
5439 /* We add the mask first because the number of iterations is taken
5440 from the last ss, and this breaks if an absent optional argument
5441 is used for mask. */
5442
6de9cd9a
DN
5443 if (maskss)
5444 gfc_add_ss_to_loop (&loop, maskss);
5445
2ea47ee9
TK
5446 gfc_add_ss_to_loop (&loop, arrayss);
5447
6de9cd9a
DN
5448 /* Initialize the loop. */
5449 gfc_conv_ss_startstride (&loop);
610f068d
MM
5450
5451 /* The code generated can have more than one loop in sequence (see the
5452 comment at the function header). This doesn't work well with the
5453 scalarizer, which changes arrays' offset when the scalarization loops
5454 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
5455 are currently inlined in the scalar case only (for which loop is of rank
5456 one). As there is no dependency to care about in that case, there is no
5457 temporary, so that we can use the scalarizer temporary code to handle
5458 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
5459 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
5460 to restore offset.
5461 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
5462 should eventually go away. We could either create two loops properly,
5463 or find another way to save/restore the array offsets between the two
5464 loops (without conflicting with temporary management), or use a single
5465 loop minmaxloc implementation. See PR 31067. */
5466 loop.temp_dim = loop.dimen;
bdfd2ff0 5467 gfc_conv_loop_setup (&loop, &expr->where);
6de9cd9a 5468
6e45f57b 5469 gcc_assert (loop.dimen == 1);
80927a56 5470 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
63ee5404 5471 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
433ce291 5472 loop.from[0], loop.to[0]);
6de9cd9a 5473
80927a56
JJ
5474 lab1 = NULL;
5475 lab2 = NULL;
a4b9e93e
PT
5476 /* Initialize the position to zero, following Fortran 2003. We are free
5477 to do this because Fortran 95 allows the result of an entirely false
80927a56
JJ
5478 mask to be processor dependent. If we know at compile time the array
5479 is non-empty and no MASK is used, we can initialize to 1 to simplify
5480 the inner loop. */
5481 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
5482 gfc_add_modify (&loop.pre, pos,
433ce291
TB
5483 fold_build3_loc (input_location, COND_EXPR,
5484 gfc_array_index_type,
5485 nonempty, gfc_index_one_node,
5486 gfc_index_zero_node));
80927a56
JJ
5487 else
5488 {
5489 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
5490 lab1 = gfc_build_label_decl (NULL_TREE);
5491 TREE_USED (lab1) = 1;
5492 lab2 = gfc_build_label_decl (NULL_TREE);
5493 TREE_USED (lab2) = 1;
5494 }
b36cd00b 5495
89d65e2d
MM
5496 /* An offset must be added to the loop
5497 counter to obtain the required position. */
5498 gcc_assert (loop.from[0]);
5499
5500 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5501 gfc_index_one_node, loop.from[0]);
5502 gfc_add_modify (&loop.pre, offset, tmp);
5503
610f068d 5504 gfc_mark_ss_chain_used (arrayss, lab1 ? 3 : 1);
6de9cd9a 5505 if (maskss)
610f068d 5506 gfc_mark_ss_chain_used (maskss, lab1 ? 3 : 1);
6de9cd9a
DN
5507 /* Generate the loop body. */
5508 gfc_start_scalarized_body (&loop, &body);
5509
5510 /* If we have a mask, only check this element if the mask is set. */
5511 if (maskss)
5512 {
5513 gfc_init_se (&maskse, NULL);
5514 gfc_copy_loopinfo_to_se (&maskse, &loop);
5515 maskse.ss = maskss;
5516 gfc_conv_expr_val (&maskse, maskexpr);
5517 gfc_add_block_to_block (&body, &maskse.pre);
5518
5519 gfc_start_block (&block);
5520 }
5521 else
5522 gfc_init_block (&block);
5523
5524 /* Compare with the current limit. */
5525 gfc_init_se (&arrayse, NULL);
5526 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5527 arrayse.ss = arrayss;
5528 gfc_conv_expr_val (&arrayse, arrayexpr);
5529 gfc_add_block_to_block (&block, &arrayse.pre);
5530
b573f931
TK
5531 gfc_init_se (&backse, NULL);
5532 gfc_conv_expr_val (&backse, backexpr);
5533 gfc_add_block_to_block (&block, &backse.pre);
5534
6de9cd9a
DN
5535 /* We do the following if this is a more extreme value. */
5536 gfc_start_block (&ifblock);
5537
5538 /* Assign the value to the limit... */
726a989a 5539 gfc_add_modify (&ifblock, limit, arrayse.expr);
6de9cd9a 5540
80927a56
JJ
5541 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
5542 {
5543 stmtblock_t ifblock2;
5544 tree ifbody2;
5545
5546 gfc_start_block (&ifblock2);
433ce291
TB
5547 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
5548 loop.loopvar[0], offset);
80927a56
JJ
5549 gfc_add_modify (&ifblock2, pos, tmp);
5550 ifbody2 = gfc_finish_block (&ifblock2);
63ee5404 5551 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pos,
433ce291 5552 gfc_index_zero_node);
80927a56
JJ
5553 tmp = build3_v (COND_EXPR, cond, ifbody2,
5554 build_empty_stmt (input_location));
5555 gfc_add_expr_to_block (&block, tmp);
5556 }
5557
433ce291
TB
5558 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
5559 loop.loopvar[0], offset);
726a989a 5560 gfc_add_modify (&ifblock, pos, tmp);
6de9cd9a 5561
80927a56
JJ
5562 if (lab1)
5563 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
5564
6de9cd9a
DN
5565 ifbody = gfc_finish_block (&ifblock);
5566
80927a56
JJ
5567 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
5568 {
5569 if (lab1)
433ce291
TB
5570 cond = fold_build2_loc (input_location,
5571 op == GT_EXPR ? GE_EXPR : LE_EXPR,
63ee5404 5572 logical_type_node, arrayse.expr, limit);
80927a56 5573 else
b573f931
TK
5574 {
5575 tree ifbody2, elsebody2;
f82f425b 5576
b573f931
TK
5577 /* We switch to > or >= depending on the value of the BACK argument. */
5578 cond = gfc_create_var (logical_type_node, "cond");
5579
5580 gfc_start_block (&ifblock);
5581 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5582 logical_type_node, arrayse.expr, limit);
5583
5584 gfc_add_modify (&ifblock, cond, b_if);
5585 ifbody2 = gfc_finish_block (&ifblock);
5586
5587 gfc_start_block (&elseblock);
5588 b_else = fold_build2_loc (input_location, op, logical_type_node,
5589 arrayse.expr, limit);
5590
5591 gfc_add_modify (&elseblock, cond, b_else);
5592 elsebody2 = gfc_finish_block (&elseblock);
5593
5594 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5595 backse.expr, ifbody2, elsebody2);
5596
5597 gfc_add_expr_to_block (&block, tmp);
5598 }
80927a56 5599
b573f931 5600 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
80927a56
JJ
5601 ifbody = build3_v (COND_EXPR, cond, ifbody,
5602 build_empty_stmt (input_location));
5603 }
5604 gfc_add_expr_to_block (&block, ifbody);
6de9cd9a
DN
5605
5606 if (maskss)
5607 {
2ea47ee9
TK
5608 /* We enclose the above in if (mask) {...}. If the mask is an
5609 optional argument, generate IF (.NOT. PRESENT(MASK)
5610 .OR. MASK(I)). */
6de9cd9a 5611
2ea47ee9
TK
5612 tree ifmask;
5613 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5614 tmp = gfc_finish_block (&block);
5615 tmp = build3_v (COND_EXPR, ifmask, tmp,
c2255bc4 5616 build_empty_stmt (input_location));
6de9cd9a
DN
5617 }
5618 else
5619 tmp = gfc_finish_block (&block);
5620 gfc_add_expr_to_block (&body, tmp);
5621
80927a56
JJ
5622 if (lab1)
5623 {
610f068d 5624 gfc_trans_scalarized_loop_boundary (&loop, &body);
80927a56
JJ
5625
5626 if (HONOR_NANS (DECL_MODE (limit)))
5627 {
5628 if (nonempty != NULL)
5629 {
5630 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
5631 tmp = build3_v (COND_EXPR, nonempty, ifbody,
5632 build_empty_stmt (input_location));
5633 gfc_add_expr_to_block (&loop.code[0], tmp);
5634 }
5635 }
5636
5637 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
5638 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
80927a56
JJ
5639
5640 /* If we have a mask, only check this element if the mask is set. */
5641 if (maskss)
5642 {
5643 gfc_init_se (&maskse, NULL);
5644 gfc_copy_loopinfo_to_se (&maskse, &loop);
5645 maskse.ss = maskss;
5646 gfc_conv_expr_val (&maskse, maskexpr);
5647 gfc_add_block_to_block (&body, &maskse.pre);
5648
5649 gfc_start_block (&block);
5650 }
5651 else
5652 gfc_init_block (&block);
5653
5654 /* Compare with the current limit. */
5655 gfc_init_se (&arrayse, NULL);
5656 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5657 arrayse.ss = arrayss;
5658 gfc_conv_expr_val (&arrayse, arrayexpr);
5659 gfc_add_block_to_block (&block, &arrayse.pre);
5660
5661 /* We do the following if this is a more extreme value. */
5662 gfc_start_block (&ifblock);
5663
5664 /* Assign the value to the limit... */
5665 gfc_add_modify (&ifblock, limit, arrayse.expr);
5666
433ce291
TB
5667 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (pos),
5668 loop.loopvar[0], offset);
80927a56
JJ
5669 gfc_add_modify (&ifblock, pos, tmp);
5670
5671 ifbody = gfc_finish_block (&ifblock);
5672
b573f931
TK
5673 /* We switch to > or >= depending on the value of the BACK argument. */
5674 {
5675 tree ifbody2, elsebody2;
5676
5677 cond = gfc_create_var (logical_type_node, "cond");
5678
5679 gfc_start_block (&ifblock);
5680 b_if = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
5681 logical_type_node, arrayse.expr, limit);
5682
5683 gfc_add_modify (&ifblock, cond, b_if);
5684 ifbody2 = gfc_finish_block (&ifblock);
80927a56 5685
b573f931
TK
5686 gfc_start_block (&elseblock);
5687 b_else = fold_build2_loc (input_location, op, logical_type_node,
5688 arrayse.expr, limit);
5689
5690 gfc_add_modify (&elseblock, cond, b_else);
5691 elsebody2 = gfc_finish_block (&elseblock);
5692
5693 tmp = fold_build3_loc (input_location, COND_EXPR, logical_type_node,
5694 backse.expr, ifbody2, elsebody2);
5695 }
5696
5697 gfc_add_expr_to_block (&block, tmp);
5698 cond = gfc_unlikely (cond, PRED_BUILTIN_EXPECT);
80927a56
JJ
5699 tmp = build3_v (COND_EXPR, cond, ifbody,
5700 build_empty_stmt (input_location));
b573f931 5701
80927a56
JJ
5702 gfc_add_expr_to_block (&block, tmp);
5703
5704 if (maskss)
5705 {
2ea47ee9
TK
5706 /* We enclose the above in if (mask) {...}. If the mask is
5707 an optional argument, generate IF (.NOT. PRESENT(MASK)
5708 .OR. MASK(I)).*/
80927a56 5709
2ea47ee9
TK
5710 tree ifmask;
5711 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5712 tmp = gfc_finish_block (&block);
5713 tmp = build3_v (COND_EXPR, ifmask, tmp,
80927a56
JJ
5714 build_empty_stmt (input_location));
5715 }
5716 else
5717 tmp = gfc_finish_block (&block);
5718 gfc_add_expr_to_block (&body, tmp);
5719 /* Avoid initializing loopvar[0] again, it should be left where
5720 it finished by the first loop. */
5721 loop.from[0] = loop.loopvar[0];
5722 }
5723
6de9cd9a
DN
5724 gfc_trans_scalarizing_loops (&loop, &body);
5725
80927a56
JJ
5726 if (lab2)
5727 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
5728
8cd25827
TK
5729 /* For a scalar mask, enclose the loop in an if statement. */
5730 if (maskexpr && maskss == NULL)
5731 {
2ea47ee9
TK
5732 tree ifmask;
5733
8cd25827
TK
5734 gfc_init_se (&maskse, NULL);
5735 gfc_conv_expr_val (&maskse, maskexpr);
5736 gfc_init_block (&block);
5737 gfc_add_block_to_block (&block, &loop.pre);
5738 gfc_add_block_to_block (&block, &loop.post);
5739 tmp = gfc_finish_block (&block);
5740
5741 /* For the else part of the scalar mask, just initialize
5742 the pos variable the same way as above. */
5743
5744 gfc_init_block (&elseblock);
726a989a 5745 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
8cd25827 5746 elsetmp = gfc_finish_block (&elseblock);
2ea47ee9
TK
5747 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5748 tmp = build3_v (COND_EXPR, ifmask, tmp, elsetmp);
8cd25827
TK
5749 gfc_add_expr_to_block (&block, tmp);
5750 gfc_add_block_to_block (&se->pre, &block);
5751 }
5752 else
5753 {
5754 gfc_add_block_to_block (&se->pre, &loop.pre);
5755 gfc_add_block_to_block (&se->pre, &loop.post);
5756 }
6de9cd9a
DN
5757 gfc_cleanup_loop (&loop);
5758
f0b3c58d 5759 se->expr = convert (type, pos);
6de9cd9a
DN
5760}
5761
01ce9e31
TK
5762/* Emit code for findloc. */
5763
5764static void
5765gfc_conv_intrinsic_findloc (gfc_se *se, gfc_expr *expr)
5766{
5767 gfc_actual_arglist *array_arg, *value_arg, *dim_arg, *mask_arg,
5768 *kind_arg, *back_arg;
5769 gfc_expr *value_expr;
5770 int ikind;
5771 tree resvar;
5772 stmtblock_t block;
5773 stmtblock_t body;
5774 stmtblock_t loopblock;
5775 tree type;
5776 tree tmp;
5777 tree found;
cc19f80c 5778 tree forward_branch = NULL_TREE;
01ce9e31
TK
5779 tree back_branch;
5780 gfc_loopinfo loop;
5781 gfc_ss *arrayss;
5782 gfc_ss *maskss;
5783 gfc_se arrayse;
5784 gfc_se valuese;
5785 gfc_se maskse;
5786 gfc_se backse;
5787 tree exit_label;
5788 gfc_expr *maskexpr;
5789 tree offset;
5790 int i;
2ea47ee9 5791 bool optional_mask;
01ce9e31
TK
5792
5793 array_arg = expr->value.function.actual;
5794 value_arg = array_arg->next;
5795 dim_arg = value_arg->next;
5796 mask_arg = dim_arg->next;
5797 kind_arg = mask_arg->next;
5798 back_arg = kind_arg->next;
5799
5800 /* Remove kind and set ikind. */
5801 if (kind_arg->expr)
5802 {
5803 ikind = mpz_get_si (kind_arg->expr->value.integer);
5804 gfc_free_expr (kind_arg->expr);
5805 kind_arg->expr = NULL;
5806 }
5807 else
5808 ikind = gfc_default_integer_kind;
5809
5810 value_expr = value_arg->expr;
5811
5812 /* Unless it's a string, pass VALUE by value. */
5813 if (value_expr->ts.type != BT_CHARACTER)
5814 value_arg->name = "%VAL";
5815
5816 /* Pass BACK argument by value. */
5817 back_arg->name = "%VAL";
5818
5819 /* Call the library if we have a character function or if
5820 rank > 0. */
5821 if (se->ss || array_arg->expr->ts.type == BT_CHARACTER)
5822 {
5823 se->ignore_optional = 1;
5824 if (expr->rank == 0)
5825 {
5826 /* Remove dim argument. */
5827 gfc_free_expr (dim_arg->expr);
5828 dim_arg->expr = NULL;
5829 }
5830 gfc_conv_intrinsic_funcall (se, expr);
5831 return;
5832 }
5833
5834 type = gfc_get_int_type (ikind);
5835
5836 /* Initialize the result. */
5837 resvar = gfc_create_var (gfc_array_index_type, "pos");
5838 gfc_add_modify (&se->pre, resvar, build_int_cst (gfc_array_index_type, 0));
5839 offset = gfc_create_var (gfc_array_index_type, "offset");
5840
5841 maskexpr = mask_arg->expr;
2ea47ee9
TK
5842 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
5843 && maskexpr->symtree->n.sym->attr.dummy
5844 && maskexpr->symtree->n.sym->attr.optional;
01ce9e31
TK
5845
5846 /* Generate two loops, one for BACK=.true. and one for BACK=.false. */
5847
5848 for (i = 0 ; i < 2; i++)
5849 {
5850 /* Walk the arguments. */
5851 arrayss = gfc_walk_expr (array_arg->expr);
5852 gcc_assert (arrayss != gfc_ss_terminator);
5853
5854 if (maskexpr && maskexpr->rank != 0)
5855 {
5856 maskss = gfc_walk_expr (maskexpr);
5857 gcc_assert (maskss != gfc_ss_terminator);
5858 }
5859 else
5860 maskss = NULL;
5861
5862 /* Initialize the scalarizer. */
5863 gfc_init_loopinfo (&loop);
5864 exit_label = gfc_build_label_decl (NULL_TREE);
5865 TREE_USED (exit_label) = 1;
2ea47ee9
TK
5866
5867 /* We add the mask first because the number of iterations is
5868 taken from the last ss, and this breaks if an absent
5869 optional argument is used for mask. */
5870
01ce9e31
TK
5871 if (maskss)
5872 gfc_add_ss_to_loop (&loop, maskss);
2ea47ee9 5873 gfc_add_ss_to_loop (&loop, arrayss);
01ce9e31
TK
5874
5875 /* Initialize the loop. */
5876 gfc_conv_ss_startstride (&loop);
5877 gfc_conv_loop_setup (&loop, &expr->where);
5878
5879 /* Calculate the offset. */
5880 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5881 gfc_index_one_node, loop.from[0]);
5882 gfc_add_modify (&loop.pre, offset, tmp);
5883
5884 gfc_mark_ss_chain_used (arrayss, 1);
5885 if (maskss)
5886 gfc_mark_ss_chain_used (maskss, 1);
5887
5888 /* The first loop is for BACK=.true. */
5889 if (i == 0)
5890 loop.reverse[0] = GFC_REVERSE_SET;
5891
5892 /* Generate the loop body. */
5893 gfc_start_scalarized_body (&loop, &body);
5894
5895 /* If we have an array mask, only add the element if it is
5896 set. */
5897 if (maskss)
5898 {
5899 gfc_init_se (&maskse, NULL);
5900 gfc_copy_loopinfo_to_se (&maskse, &loop);
5901 maskse.ss = maskss;
5902 gfc_conv_expr_val (&maskse, maskexpr);
5903 gfc_add_block_to_block (&body, &maskse.pre);
5904 }
5905
5906 /* If the condition matches then set the return value. */
5907 gfc_start_block (&block);
5908
5909 /* Add the offset. */
5910 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5911 TREE_TYPE (resvar),
5912 loop.loopvar[0], offset);
5913 gfc_add_modify (&block, resvar, tmp);
5914 /* And break out of the loop. */
5915 tmp = build1_v (GOTO_EXPR, exit_label);
5916 gfc_add_expr_to_block (&block, tmp);
5917
5918 found = gfc_finish_block (&block);
5919
5920 /* Check this element. */
5921 gfc_init_se (&arrayse, NULL);
5922 gfc_copy_loopinfo_to_se (&arrayse, &loop);
5923 arrayse.ss = arrayss;
5924 gfc_conv_expr_val (&arrayse, array_arg->expr);
5925 gfc_add_block_to_block (&body, &arrayse.pre);
5926
5927 gfc_init_se (&valuese, NULL);
5928 gfc_conv_expr_val (&valuese, value_arg->expr);
5929 gfc_add_block_to_block (&body, &valuese.pre);
5930
5931 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
5932 arrayse.expr, valuese.expr);
5933
5934 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
5935 if (maskss)
2ea47ee9
TK
5936 {
5937 /* We enclose the above in if (mask) {...}. If the mask is
5938 an optional argument, generate IF (.NOT. PRESENT(MASK)
5939 .OR. MASK(I)). */
5940
5941 tree ifmask;
5942 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5943 tmp = build3_v (COND_EXPR, ifmask, tmp,
5944 build_empty_stmt (input_location));
5945 }
01ce9e31
TK
5946
5947 gfc_add_expr_to_block (&body, tmp);
5948 gfc_add_block_to_block (&body, &arrayse.post);
5949
5950 gfc_trans_scalarizing_loops (&loop, &body);
5951
5952 /* Add the exit label. */
5953 tmp = build1_v (LABEL_EXPR, exit_label);
5954 gfc_add_expr_to_block (&loop.pre, tmp);
5955 gfc_start_block (&loopblock);
5956 gfc_add_block_to_block (&loopblock, &loop.pre);
5957 gfc_add_block_to_block (&loopblock, &loop.post);
5958 if (i == 0)
5959 forward_branch = gfc_finish_block (&loopblock);
5960 else
5961 back_branch = gfc_finish_block (&loopblock);
5962
5963 gfc_cleanup_loop (&loop);
5964 }
5965
5966 /* Enclose the two loops in an IF statement. */
5967
5968 gfc_init_se (&backse, NULL);
5969 gfc_conv_expr_val (&backse, back_arg->expr);
5970 gfc_add_block_to_block (&se->pre, &backse.pre);
5971 tmp = build3_v (COND_EXPR, backse.expr, forward_branch, back_branch);
5972
5973 /* For a scalar mask, enclose the loop in an if statement. */
5974 if (maskexpr && maskss == NULL)
5975 {
2ea47ee9 5976 tree ifmask;
01ce9e31 5977 tree if_stmt;
2ea47ee9 5978
01ce9e31
TK
5979 gfc_init_se (&maskse, NULL);
5980 gfc_conv_expr_val (&maskse, maskexpr);
5981 gfc_init_block (&block);
5982 gfc_add_expr_to_block (&block, maskse.expr);
2ea47ee9
TK
5983 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
5984 if_stmt = build3_v (COND_EXPR, ifmask, tmp,
01ce9e31
TK
5985 build_empty_stmt (input_location));
5986 gfc_add_expr_to_block (&block, if_stmt);
5987 tmp = gfc_finish_block (&block);
5988 }
5989
5990 gfc_add_expr_to_block (&se->pre, tmp);
5991 se->expr = convert (type, resvar);
5992
5993}
5994
80927a56
JJ
5995/* Emit code for minval or maxval intrinsic. There are many different cases
5996 we need to handle. For performance reasons we sometimes create two
5997 loops instead of one, where the second one is much simpler.
5998 Examples for minval intrinsic:
5999 1) Result is an array, a call is generated
6000 2) Array mask is used and NaNs need to be supported, rank 1:
6001 limit = Infinity;
6002 nonempty = false;
6003 S = from;
6004 while (S <= to) {
6005 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
6006 S++;
6007 }
6008 limit = nonempty ? NaN : huge (limit);
6009 lab:
6010 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
6011 3) NaNs need to be supported, but it is known at compile time or cheaply
6012 at runtime whether array is nonempty or not, rank 1:
6013 limit = Infinity;
6014 S = from;
6015 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
6016 limit = (from <= to) ? NaN : huge (limit);
6017 lab:
6018 while (S <= to) { limit = min (a[S], limit); S++; }
6019 4) Array mask is used and NaNs need to be supported, rank > 1:
6020 limit = Infinity;
6021 nonempty = false;
6022 fast = false;
6023 S1 = from1;
6024 while (S1 <= to1) {
6025 S2 = from2;
6026 while (S2 <= to2) {
6027 if (mask[S1][S2]) {
6028 if (fast) limit = min (a[S1][S2], limit);
6029 else {
6030 nonempty = true;
6031 if (a[S1][S2] <= limit) {
6032 limit = a[S1][S2];
6033 fast = true;
6034 }
6035 }
6036 }
6037 S2++;
6038 }
6039 S1++;
6040 }
6041 if (!fast)
6042 limit = nonempty ? NaN : huge (limit);
6043 5) NaNs need to be supported, but it is known at compile time or cheaply
6044 at runtime whether array is nonempty or not, rank > 1:
6045 limit = Infinity;
6046 fast = false;
6047 S1 = from1;
6048 while (S1 <= to1) {
6049 S2 = from2;
6050 while (S2 <= to2) {
6051 if (fast) limit = min (a[S1][S2], limit);
6052 else {
6053 if (a[S1][S2] <= limit) {
6054 limit = a[S1][S2];
6055 fast = true;
6056 }
6057 }
6058 S2++;
6059 }
6060 S1++;
6061 }
6062 if (!fast)
6063 limit = (nonempty_array) ? NaN : huge (limit);
6064 6) NaNs aren't supported, but infinities are. Array mask is used:
6065 limit = Infinity;
6066 nonempty = false;
6067 S = from;
6068 while (S <= to) {
6069 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
6070 S++;
6071 }
6072 limit = nonempty ? limit : huge (limit);
6073 7) Same without array mask:
6074 limit = Infinity;
6075 S = from;
6076 while (S <= to) { limit = min (a[S], limit); S++; }
6077 limit = (from <= to) ? limit : huge (limit);
6078 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
6079 limit = huge (limit);
6080 S = from;
6081 while (S <= to) { limit = min (a[S], limit); S++); }
6082 (or
6083 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
6084 with array mask instead).
6085 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
6086 setting limit = huge (limit); in the else branch. */
6087
6de9cd9a 6088static void
8fa2df72 6089gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
6de9cd9a
DN
6090{
6091 tree limit;
6092 tree type;
6093 tree tmp;
6094 tree ifbody;
80927a56
JJ
6095 tree nonempty;
6096 tree nonempty_var;
6097 tree lab;
6098 tree fast;
6099 tree huge_cst = NULL, nan_cst = NULL;
6de9cd9a 6100 stmtblock_t body;
80927a56 6101 stmtblock_t block, block2;
6de9cd9a
DN
6102 gfc_loopinfo loop;
6103 gfc_actual_arglist *actual;
6104 gfc_ss *arrayss;
6105 gfc_ss *maskss;
6106 gfc_se arrayse;
6107 gfc_se maskse;
6108 gfc_expr *arrayexpr;
6109 gfc_expr *maskexpr;
6110 int n;
2ea47ee9 6111 bool optional_mask;
6de9cd9a
DN
6112
6113 if (se->ss)
6114 {
6115 gfc_conv_intrinsic_funcall (se, expr);
6116 return;
6117 }
6118
0ac74254
TK
6119 actual = expr->value.function.actual;
6120 arrayexpr = actual->expr;
6121
6122 if (arrayexpr->ts.type == BT_CHARACTER)
6123 {
47d13acb
TK
6124 gfc_actual_arglist *dim = actual->next;
6125 if (expr->rank == 0 && dim->expr != 0)
0ac74254 6126 {
47d13acb
TK
6127 gfc_free_expr (dim->expr);
6128 dim->expr = NULL;
0ac74254 6129 }
0ac74254
TK
6130 gfc_conv_intrinsic_funcall (se, expr);
6131 return;
6132 }
47d13acb 6133
6de9cd9a
DN
6134 type = gfc_typenode_for_spec (&expr->ts);
6135 /* Initialize the result. */
6136 limit = gfc_create_var (type, "limit");
e7a2d5fb 6137 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
6de9cd9a
DN
6138 switch (expr->ts.type)
6139 {
6140 case BT_REAL:
80927a56
JJ
6141 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
6142 expr->ts.kind, 0);
6143 if (HONOR_INFINITIES (DECL_MODE (limit)))
6144 {
6145 REAL_VALUE_TYPE real;
6146 real_inf (&real);
6147 tmp = build_real (type, real);
6148 }
6149 else
6150 tmp = huge_cst;
6151 if (HONOR_NANS (DECL_MODE (limit)))
565fad70 6152 nan_cst = gfc_build_nan (type, "");
6de9cd9a
DN
6153 break;
6154
6155 case BT_INTEGER:
6156 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
6157 break;
6158
6159 default:
6e45f57b 6160 gcc_unreachable ();
6de9cd9a
DN
6161 }
6162
88116029
TB
6163 /* We start with the most negative possible value for MAXVAL, and the most
6164 positive possible value for MINVAL. The most negative possible value is
6165 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
66e4ab31 6166 possible value is HUGE in both cases. */
6de9cd9a 6167 if (op == GT_EXPR)
80927a56 6168 {
433ce291 6169 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (tmp), tmp);
80927a56 6170 if (huge_cst)
433ce291
TB
6171 huge_cst = fold_build1_loc (input_location, NEGATE_EXPR,
6172 TREE_TYPE (huge_cst), huge_cst);
80927a56 6173 }
88116029
TB
6174
6175 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
433ce291
TB
6176 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
6177 tmp, build_int_cst (type, 1));
88116029 6178
726a989a 6179 gfc_add_modify (&se->pre, limit, tmp);
6de9cd9a
DN
6180
6181 /* Walk the arguments. */
6de9cd9a 6182 arrayss = gfc_walk_expr (arrayexpr);
6e45f57b 6183 gcc_assert (arrayss != gfc_ss_terminator);
6de9cd9a
DN
6184
6185 actual = actual->next->next;
6e45f57b 6186 gcc_assert (actual);
6de9cd9a 6187 maskexpr = actual->expr;
2ea47ee9
TK
6188 optional_mask = maskexpr && maskexpr->expr_type == EXPR_VARIABLE
6189 && maskexpr->symtree->n.sym->attr.dummy
6190 && maskexpr->symtree->n.sym->attr.optional;
80927a56 6191 nonempty = NULL;
eaf618e3 6192 if (maskexpr && maskexpr->rank != 0)
6de9cd9a
DN
6193 {
6194 maskss = gfc_walk_expr (maskexpr);
6e45f57b 6195 gcc_assert (maskss != gfc_ss_terminator);
6de9cd9a
DN
6196 }
6197 else
80927a56
JJ
6198 {
6199 mpz_t asize;
524af0d6 6200 if (gfc_array_size (arrayexpr, &asize))
80927a56
JJ
6201 {
6202 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
6203 mpz_clear (asize);
433ce291 6204 nonempty = fold_build2_loc (input_location, GT_EXPR,
63ee5404 6205 logical_type_node, nonempty,
433ce291 6206 gfc_index_zero_node);
80927a56
JJ
6207 }
6208 maskss = NULL;
6209 }
6de9cd9a
DN
6210
6211 /* Initialize the scalarizer. */
6212 gfc_init_loopinfo (&loop);
2ea47ee9
TK
6213
6214 /* We add the mask first because the number of iterations is taken
6215 from the last ss, and this breaks if an absent optional argument
6216 is used for mask. */
6217
6de9cd9a
DN
6218 if (maskss)
6219 gfc_add_ss_to_loop (&loop, maskss);
2ea47ee9 6220 gfc_add_ss_to_loop (&loop, arrayss);
6de9cd9a
DN
6221
6222 /* Initialize the loop. */
6223 gfc_conv_ss_startstride (&loop);
aa6ad95c
MM
6224
6225 /* The code generated can have more than one loop in sequence (see the
6226 comment at the function header). This doesn't work well with the
6227 scalarizer, which changes arrays' offset when the scalarization loops
6228 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
6229 are currently inlined in the scalar case only. As there is no dependency
6230 to care about in that case, there is no temporary, so that we can use the
6231 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
6232 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
6233 gfc_trans_scalarized_loop_boundary even later to restore offset.
6234 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
6235 should eventually go away. We could either create two loops properly,
6236 or find another way to save/restore the array offsets between the two
6237 loops (without conflicting with temporary management), or use a single
6238 loop minmaxval implementation. See PR 31067. */
6239 loop.temp_dim = loop.dimen;
bdfd2ff0 6240 gfc_conv_loop_setup (&loop, &expr->where);
6de9cd9a 6241
80927a56
JJ
6242 if (nonempty == NULL && maskss == NULL
6243 && loop.dimen == 1 && loop.from[0] && loop.to[0])
63ee5404 6244 nonempty = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
433ce291 6245 loop.from[0], loop.to[0]);
80927a56
JJ
6246 nonempty_var = NULL;
6247 if (nonempty == NULL
6248 && (HONOR_INFINITIES (DECL_MODE (limit))
6249 || HONOR_NANS (DECL_MODE (limit))))
6250 {
63ee5404
JB
6251 nonempty_var = gfc_create_var (logical_type_node, "nonempty");
6252 gfc_add_modify (&se->pre, nonempty_var, logical_false_node);
80927a56
JJ
6253 nonempty = nonempty_var;
6254 }
6255 lab = NULL;
6256 fast = NULL;
6257 if (HONOR_NANS (DECL_MODE (limit)))
6258 {
6259 if (loop.dimen == 1)
6260 {
6261 lab = gfc_build_label_decl (NULL_TREE);
6262 TREE_USED (lab) = 1;
6263 }
6264 else
6265 {
63ee5404
JB
6266 fast = gfc_create_var (logical_type_node, "fast");
6267 gfc_add_modify (&se->pre, fast, logical_false_node);
80927a56
JJ
6268 }
6269 }
6270
aa6ad95c 6271 gfc_mark_ss_chain_used (arrayss, lab ? 3 : 1);
6de9cd9a 6272 if (maskss)
aa6ad95c 6273 gfc_mark_ss_chain_used (maskss, lab ? 3 : 1);
6de9cd9a
DN
6274 /* Generate the loop body. */
6275 gfc_start_scalarized_body (&loop, &body);
6276
6277 /* If we have a mask, only add this element if the mask is set. */
6278 if (maskss)
6279 {
6280 gfc_init_se (&maskse, NULL);
6281 gfc_copy_loopinfo_to_se (&maskse, &loop);
6282 maskse.ss = maskss;
6283 gfc_conv_expr_val (&maskse, maskexpr);
6284 gfc_add_block_to_block (&body, &maskse.pre);
6285
6286 gfc_start_block (&block);
6287 }
6288 else
6289 gfc_init_block (&block);
6290
6291 /* Compare with the current limit. */
6292 gfc_init_se (&arrayse, NULL);
6293 gfc_copy_loopinfo_to_se (&arrayse, &loop);
6294 arrayse.ss = arrayss;
6295 gfc_conv_expr_val (&arrayse, arrayexpr);
6296 gfc_add_block_to_block (&block, &arrayse.pre);
6297
80927a56
JJ
6298 gfc_init_block (&block2);
6299
6300 if (nonempty_var)
63ee5404 6301 gfc_add_modify (&block2, nonempty_var, logical_true_node);
80927a56
JJ
6302
6303 if (HONOR_NANS (DECL_MODE (limit)))
6304 {
433ce291 6305 tmp = fold_build2_loc (input_location, op == GT_EXPR ? GE_EXPR : LE_EXPR,
63ee5404 6306 logical_type_node, arrayse.expr, limit);
80927a56
JJ
6307 if (lab)
6308 ifbody = build1_v (GOTO_EXPR, lab);
6309 else
6310 {
6311 stmtblock_t ifblock;
6312
6313 gfc_init_block (&ifblock);
6314 gfc_add_modify (&ifblock, limit, arrayse.expr);
63ee5404 6315 gfc_add_modify (&ifblock, fast, logical_true_node);
80927a56
JJ
6316 ifbody = gfc_finish_block (&ifblock);
6317 }
6318 tmp = build3_v (COND_EXPR, tmp, ifbody,
6319 build_empty_stmt (input_location));
6320 gfc_add_expr_to_block (&block2, tmp);
6321 }
6322 else
6323 {
6324 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6325 signed zeros. */
9c44db9f
JB
6326 tmp = fold_build2_loc (input_location,
6327 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
6328 type, arrayse.expr, limit);
6329 gfc_add_modify (&block2, limit, tmp);
80927a56
JJ
6330 }
6331
6332 if (fast)
6333 {
6334 tree elsebody = gfc_finish_block (&block2);
6335
6336 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6337 signed zeros. */
9c44db9f 6338 if (HONOR_NANS (DECL_MODE (limit)))
80927a56 6339 {
63ee5404 6340 tmp = fold_build2_loc (input_location, op, logical_type_node,
433ce291 6341 arrayse.expr, limit);
80927a56
JJ
6342 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
6343 ifbody = build3_v (COND_EXPR, tmp, ifbody,
6344 build_empty_stmt (input_location));
6345 }
6346 else
6347 {
433ce291
TB
6348 tmp = fold_build2_loc (input_location,
6349 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
6350 type, arrayse.expr, limit);
80927a56
JJ
6351 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
6352 }
6353 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
6354 gfc_add_expr_to_block (&block, tmp);
6355 }
6356 else
6357 gfc_add_block_to_block (&block, &block2);
6de9cd9a 6358
6de9cd9a
DN
6359 gfc_add_block_to_block (&block, &arrayse.post);
6360
6361 tmp = gfc_finish_block (&block);
6362 if (maskss)
2ea47ee9
TK
6363 {
6364 /* We enclose the above in if (mask) {...}. If the mask is an
6365 optional argument, generate IF (.NOT. PRESENT(MASK)
6366 .OR. MASK(I)). */
6367 tree ifmask;
6368 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6369 tmp = build3_v (COND_EXPR, ifmask, tmp,
6370 build_empty_stmt (input_location));
6371 }
6de9cd9a
DN
6372 gfc_add_expr_to_block (&body, tmp);
6373
80927a56
JJ
6374 if (lab)
6375 {
aa6ad95c 6376 gfc_trans_scalarized_loop_boundary (&loop, &body);
80927a56 6377
433ce291
TB
6378 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
6379 nan_cst, huge_cst);
80927a56
JJ
6380 gfc_add_modify (&loop.code[0], limit, tmp);
6381 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
6382
80927a56
JJ
6383 /* If we have a mask, only add this element if the mask is set. */
6384 if (maskss)
6385 {
6386 gfc_init_se (&maskse, NULL);
6387 gfc_copy_loopinfo_to_se (&maskse, &loop);
6388 maskse.ss = maskss;
6389 gfc_conv_expr_val (&maskse, maskexpr);
6390 gfc_add_block_to_block (&body, &maskse.pre);
6391
6392 gfc_start_block (&block);
6393 }
6394 else
6395 gfc_init_block (&block);
6396
6397 /* Compare with the current limit. */
6398 gfc_init_se (&arrayse, NULL);
6399 gfc_copy_loopinfo_to_se (&arrayse, &loop);
6400 arrayse.ss = arrayss;
6401 gfc_conv_expr_val (&arrayse, arrayexpr);
6402 gfc_add_block_to_block (&block, &arrayse.pre);
6403
6404 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6405 signed zeros. */
9c44db9f 6406 if (HONOR_NANS (DECL_MODE (limit)))
80927a56 6407 {
63ee5404 6408 tmp = fold_build2_loc (input_location, op, logical_type_node,
433ce291 6409 arrayse.expr, limit);
80927a56
JJ
6410 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
6411 tmp = build3_v (COND_EXPR, tmp, ifbody,
6412 build_empty_stmt (input_location));
6413 gfc_add_expr_to_block (&block, tmp);
6414 }
6415 else
6416 {
433ce291
TB
6417 tmp = fold_build2_loc (input_location,
6418 op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
6419 type, arrayse.expr, limit);
80927a56
JJ
6420 gfc_add_modify (&block, limit, tmp);
6421 }
6422
6423 gfc_add_block_to_block (&block, &arrayse.post);
6424
6425 tmp = gfc_finish_block (&block);
6426 if (maskss)
6427 /* We enclose the above in if (mask) {...}. */
2ea47ee9
TK
6428 {
6429 tree ifmask;
6430 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6431 tmp = build3_v (COND_EXPR, ifmask, tmp,
6432 build_empty_stmt (input_location));
6433 }
6434
80927a56
JJ
6435 gfc_add_expr_to_block (&body, tmp);
6436 /* Avoid initializing loopvar[0] again, it should be left where
6437 it finished by the first loop. */
6438 loop.from[0] = loop.loopvar[0];
6439 }
6de9cd9a
DN
6440 gfc_trans_scalarizing_loops (&loop, &body);
6441
80927a56
JJ
6442 if (fast)
6443 {
433ce291
TB
6444 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty,
6445 nan_cst, huge_cst);
80927a56
JJ
6446 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
6447 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
6448 ifbody);
6449 gfc_add_expr_to_block (&loop.pre, tmp);
6450 }
6451 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
6452 {
433ce291
TB
6453 tmp = fold_build3_loc (input_location, COND_EXPR, type, nonempty, limit,
6454 huge_cst);
80927a56
JJ
6455 gfc_add_modify (&loop.pre, limit, tmp);
6456 }
6457
eaf618e3
TK
6458 /* For a scalar mask, enclose the loop in an if statement. */
6459 if (maskexpr && maskss == NULL)
6460 {
80927a56 6461 tree else_stmt;
2ea47ee9 6462 tree ifmask;
80927a56 6463
eaf618e3
TK
6464 gfc_init_se (&maskse, NULL);
6465 gfc_conv_expr_val (&maskse, maskexpr);
6466 gfc_init_block (&block);
6467 gfc_add_block_to_block (&block, &loop.pre);
6468 gfc_add_block_to_block (&block, &loop.post);
6469 tmp = gfc_finish_block (&block);
6470
80927a56
JJ
6471 if (HONOR_INFINITIES (DECL_MODE (limit)))
6472 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
6473 else
6474 else_stmt = build_empty_stmt (input_location);
2ea47ee9
TK
6475
6476 ifmask = conv_mask_condition (&maskse, maskexpr, optional_mask);
6477 tmp = build3_v (COND_EXPR, ifmask, tmp, else_stmt);
eaf618e3
TK
6478 gfc_add_expr_to_block (&block, tmp);
6479 gfc_add_block_to_block (&se->pre, &block);
6480 }
6481 else
6482 {
6483 gfc_add_block_to_block (&se->pre, &loop.pre);
6484 gfc_add_block_to_block (&se->pre, &loop.post);
6485 }
6486
6de9cd9a
DN
6487 gfc_cleanup_loop (&loop);
6488
6489 se->expr = limit;
6490}
6491
6492/* BTEST (i, pos) = (i & (1 << pos)) != 0. */
6493static void
6494gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
6495{
55637e51 6496 tree args[2];
6de9cd9a
DN
6497 tree type;
6498 tree tmp;
6499
55637e51
LM
6500 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6501 type = TREE_TYPE (args[0]);
6de9cd9a 6502
df1afcca
HA
6503 /* Optionally generate code for runtime argument check. */
6504 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6505 {
6506 tree below = fold_build2_loc (input_location, LT_EXPR,
6507 logical_type_node, args[1],
6508 build_int_cst (TREE_TYPE (args[1]), 0));
6509 tree nbits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6510 tree above = fold_build2_loc (input_location, GE_EXPR,
6511 logical_type_node, args[1], nbits);
6512 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6513 logical_type_node, below, above);
6514 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6515 "POS argument (%ld) out of range 0:%ld "
6516 "in intrinsic BTEST",
6517 fold_convert (long_integer_type_node, args[1]),
6518 fold_convert (long_integer_type_node, nbits));
6519 }
6520
433ce291
TB
6521 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
6522 build_int_cst (type, 1), args[1]);
6523 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp);
63ee5404 6524 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
433ce291 6525 build_int_cst (type, 0));
6de9cd9a
DN
6526 type = gfc_typenode_for_spec (&expr->ts);
6527 se->expr = convert (type, tmp);
6528}
6529
88a95a11
FXC
6530
6531/* Generate code for BGE, BGT, BLE and BLT intrinsics. */
6532static void
6533gfc_conv_intrinsic_bitcomp (gfc_se * se, gfc_expr * expr, enum tree_code op)
6534{
6535 tree args[2];
6536
6537 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6538
6539 /* Convert both arguments to the unsigned type of the same size. */
6540 args[0] = fold_convert (unsigned_type_for (TREE_TYPE (args[0])), args[0]);
6541 args[1] = fold_convert (unsigned_type_for (TREE_TYPE (args[1])), args[1]);
6542
6543 /* If they have unequal type size, convert to the larger one. */
6544 if (TYPE_PRECISION (TREE_TYPE (args[0]))
6545 > TYPE_PRECISION (TREE_TYPE (args[1])))
6546 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
6547 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
6548 > TYPE_PRECISION (TREE_TYPE (args[0])))
6549 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
6550
6551 /* Now, we compare them. */
63ee5404 6552 se->expr = fold_build2_loc (input_location, op, logical_type_node,
88a95a11
FXC
6553 args[0], args[1]);
6554}
6555
6556
6de9cd9a
DN
6557/* Generate code to perform the specified operation. */
6558static void
8fa2df72 6559gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
6de9cd9a 6560{
55637e51 6561 tree args[2];
6de9cd9a 6562
55637e51 6563 gfc_conv_intrinsic_function_args (se, expr, args, 2);
433ce291
TB
6564 se->expr = fold_build2_loc (input_location, op, TREE_TYPE (args[0]),
6565 args[0], args[1]);
6de9cd9a
DN
6566}
6567
6568/* Bitwise not. */
6569static void
6570gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
6571{
6572 tree arg;
6573
55637e51 6574 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
433ce291
TB
6575 se->expr = fold_build1_loc (input_location, BIT_NOT_EXPR,
6576 TREE_TYPE (arg), arg);
6de9cd9a
DN
6577}
6578
6579/* Set or clear a single bit. */
6580static void
6581gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
6582{
55637e51 6583 tree args[2];
6de9cd9a
DN
6584 tree type;
6585 tree tmp;
8fa2df72 6586 enum tree_code op;
6de9cd9a 6587
55637e51
LM
6588 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6589 type = TREE_TYPE (args[0]);
6de9cd9a 6590
df1afcca
HA
6591 /* Optionally generate code for runtime argument check. */
6592 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6593 {
6594 tree below = fold_build2_loc (input_location, LT_EXPR,
6595 logical_type_node, args[1],
6596 build_int_cst (TREE_TYPE (args[1]), 0));
6597 tree nbits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
6598 tree above = fold_build2_loc (input_location, GE_EXPR,
6599 logical_type_node, args[1], nbits);
6600 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6601 logical_type_node, below, above);
6602 size_t len_name = strlen (expr->value.function.isym->name);
6603 char *name = XALLOCAVEC (char, len_name + 1);
6604 for (size_t i = 0; i < len_name; i++)
6605 name[i] = TOUPPER (expr->value.function.isym->name[i]);
6606 name[len_name] = '\0';
6607 tree iname = gfc_build_addr_expr (pchar_type_node,
6608 gfc_build_cstring_const (name));
6609 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6610 "POS argument (%ld) out of range 0:%ld "
6611 "in intrinsic %s",
6612 fold_convert (long_integer_type_node, args[1]),
6613 fold_convert (long_integer_type_node, nbits),
6614 iname);
6615 }
6616
433ce291
TB
6617 tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
6618 build_int_cst (type, 1), args[1]);
6de9cd9a
DN
6619 if (set)
6620 op = BIT_IOR_EXPR;
6621 else
6622 {
6623 op = BIT_AND_EXPR;
433ce291 6624 tmp = fold_build1_loc (input_location, BIT_NOT_EXPR, type, tmp);
6de9cd9a 6625 }
433ce291 6626 se->expr = fold_build2_loc (input_location, op, type, args[0], tmp);
6de9cd9a
DN
6627}
6628
6629/* Extract a sequence of bits.
6630 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
6631static void
6632gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
6633{
55637e51 6634 tree args[3];
6de9cd9a
DN
6635 tree type;
6636 tree tmp;
6637 tree mask;
6638
55637e51
LM
6639 gfc_conv_intrinsic_function_args (se, expr, args, 3);
6640 type = TREE_TYPE (args[0]);
6de9cd9a 6641
df1afcca
HA
6642 /* Optionally generate code for runtime argument check. */
6643 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6644 {
6645 tree tmp1 = fold_convert (long_integer_type_node, args[1]);
6646 tree tmp2 = fold_convert (long_integer_type_node, args[2]);
6647 tree nbits = build_int_cst (long_integer_type_node,
6648 TYPE_PRECISION (type));
6649 tree below = fold_build2_loc (input_location, LT_EXPR,
6650 logical_type_node, args[1],
6651 build_int_cst (TREE_TYPE (args[1]), 0));
6652 tree above = fold_build2_loc (input_location, GT_EXPR,
6653 logical_type_node, tmp1, nbits);
6654 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6655 logical_type_node, below, above);
6656 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6657 "POS argument (%ld) out of range 0:%ld "
6658 "in intrinsic IBITS", tmp1, nbits);
6659 below = fold_build2_loc (input_location, LT_EXPR,
6660 logical_type_node, args[2],
6661 build_int_cst (TREE_TYPE (args[2]), 0));
6662 above = fold_build2_loc (input_location, GT_EXPR,
6663 logical_type_node, tmp2, nbits);
6664 scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6665 logical_type_node, below, above);
6666 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6667 "LEN argument (%ld) out of range 0:%ld "
6668 "in intrinsic IBITS", tmp2, nbits);
6669 above = fold_build2_loc (input_location, PLUS_EXPR,
6670 long_integer_type_node, tmp1, tmp2);
6671 scond = fold_build2_loc (input_location, GT_EXPR,
6672 logical_type_node, above, nbits);
6673 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6674 "POS(%ld)+LEN(%ld)>BIT_SIZE(%ld) "
6675 "in intrinsic IBITS", tmp1, tmp2, nbits);
6676 }
6677
b17a1b93 6678 mask = build_int_cst (type, -1);
433ce291
TB
6679 mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]);
6680 mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask);
6de9cd9a 6681
433ce291 6682 tmp = fold_build2_loc (input_location, RSHIFT_EXPR, type, args[0], args[1]);
6de9cd9a 6683
433ce291 6684 se->expr = fold_build2_loc (input_location, BIT_AND_EXPR, type, tmp, mask);
6de9cd9a
DN
6685}
6686
a119fc1c 6687static void
88a95a11
FXC
6688gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
6689 bool arithmetic)
a119fc1c 6690{
88a95a11 6691 tree args[2], type, num_bits, cond;
d0442491 6692 tree bigshift;
a119fc1c 6693
55637e51 6694 gfc_conv_intrinsic_function_args (se, expr, args, 2);
a119fc1c 6695
88a95a11
FXC
6696 args[0] = gfc_evaluate_now (args[0], &se->pre);
6697 args[1] = gfc_evaluate_now (args[1], &se->pre);
6698 type = TREE_TYPE (args[0]);
6699
6700 if (!arithmetic)
6701 args[0] = fold_convert (unsigned_type_for (type), args[0]);
6702 else
6703 gcc_assert (right_shift);
6704
433ce291
TB
6705 se->expr = fold_build2_loc (input_location,
6706 right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
6707 TREE_TYPE (args[0]), args[0], args[1]);
88a95a11
FXC
6708
6709 if (!arithmetic)
6710 se->expr = fold_convert (type, se->expr);
6711
d0442491
HA
6712 if (!arithmetic)
6713 bigshift = build_int_cst (type, 0);
6714 else
6715 {
6716 tree nonneg = fold_build2_loc (input_location, GE_EXPR,
6717 logical_type_node, args[0],
6718 build_int_cst (TREE_TYPE (args[0]), 0));
6719 bigshift = fold_build3_loc (input_location, COND_EXPR, type, nonneg,
6720 build_int_cst (type, 0),
6721 build_int_cst (type, -1));
6722 }
6723
88a95a11
FXC
6724 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
6725 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
6726 special case. */
6727 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
df1afcca
HA
6728
6729 /* Optionally generate code for runtime argument check. */
6730 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6731 {
6732 tree below = fold_build2_loc (input_location, LT_EXPR,
6733 logical_type_node, args[1],
6734 build_int_cst (TREE_TYPE (args[1]), 0));
6735 tree above = fold_build2_loc (input_location, GT_EXPR,
6736 logical_type_node, args[1], num_bits);
6737 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6738 logical_type_node, below, above);
6739 size_t len_name = strlen (expr->value.function.isym->name);
6740 char *name = XALLOCAVEC (char, len_name + 1);
6741 for (size_t i = 0; i < len_name; i++)
6742 name[i] = TOUPPER (expr->value.function.isym->name[i]);
6743 name[len_name] = '\0';
6744 tree iname = gfc_build_addr_expr (pchar_type_node,
6745 gfc_build_cstring_const (name));
6746 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6747 "SHIFT argument (%ld) out of range 0:%ld "
6748 "in intrinsic %s",
6749 fold_convert (long_integer_type_node, args[1]),
6750 fold_convert (long_integer_type_node, num_bits),
6751 iname);
6752 }
6753
63ee5404 6754 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
88a95a11
FXC
6755 args[1], num_bits);
6756
6757 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
d0442491 6758 bigshift, se->expr);
a119fc1c
FXC
6759}
6760
56746a07
TS
6761/* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
6762 ? 0
6763 : ((shift >= 0) ? i << shift : i >> -shift)
6764 where all shifts are logical shifts. */
6de9cd9a
DN
6765static void
6766gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
6767{
55637e51 6768 tree args[2];
6de9cd9a 6769 tree type;
56746a07 6770 tree utype;
6de9cd9a 6771 tree tmp;
56746a07
TS
6772 tree width;
6773 tree num_bits;
6774 tree cond;
6de9cd9a
DN
6775 tree lshift;
6776 tree rshift;
6777
55637e51 6778 gfc_conv_intrinsic_function_args (se, expr, args, 2);
36d9e52f
FXC
6779
6780 args[0] = gfc_evaluate_now (args[0], &se->pre);
6781 args[1] = gfc_evaluate_now (args[1], &se->pre);
6782
55637e51 6783 type = TREE_TYPE (args[0]);
ca5ba2a3 6784 utype = unsigned_type_for (type);
6de9cd9a 6785
433ce291
TB
6786 width = fold_build1_loc (input_location, ABS_EXPR, TREE_TYPE (args[1]),
6787 args[1]);
6de9cd9a 6788
56746a07 6789 /* Left shift if positive. */
433ce291 6790 lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type, args[0], width);
56746a07 6791
de46b505
TS
6792 /* Right shift if negative.
6793 We convert to an unsigned type because we want a logical shift.
6794 The standard doesn't define the case of shifting negative
6795 numbers, and we try to be compatible with other compilers, most
6796 notably g77, here. */
433ce291
TB
6797 rshift = fold_convert (type, fold_build2_loc (input_location, RSHIFT_EXPR,
6798 utype, convert (utype, args[0]), width));
56746a07 6799
63ee5404 6800 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[1],
433ce291
TB
6801 build_int_cst (TREE_TYPE (args[1]), 0));
6802 tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp, lshift, rshift);
56746a07
TS
6803
6804 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
6805 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
6806 special case. */
8dc9f613 6807 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
df1afcca
HA
6808
6809 /* Optionally generate code for runtime argument check. */
6810 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6811 {
6812 tree outside = fold_build2_loc (input_location, GT_EXPR,
6813 logical_type_node, width, num_bits);
6814 gfc_trans_runtime_check (true, false, outside, &se->pre, &expr->where,
6815 "SHIFT argument (%ld) out of range -%ld:%ld "
6816 "in intrinsic ISHFT",
6817 fold_convert (long_integer_type_node, args[1]),
6818 fold_convert (long_integer_type_node, num_bits),
6819 fold_convert (long_integer_type_node, num_bits));
6820 }
6821
63ee5404 6822 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, width,
433ce291
TB
6823 num_bits);
6824 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
6825 build_int_cst (type, 0), tmp);
6de9cd9a
DN
6826}
6827
14b1261a 6828
6de9cd9a 6829/* Circular shift. AKA rotate or barrel shift. */
14b1261a 6830
6de9cd9a
DN
6831static void
6832gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
6833{
55637e51 6834 tree *args;
6de9cd9a
DN
6835 tree type;
6836 tree tmp;
6837 tree lrot;
6838 tree rrot;
e805a599 6839 tree zero;
df1afcca 6840 tree nbits;
55637e51 6841 unsigned int num_args;
6de9cd9a 6842
55637e51 6843 num_args = gfc_intrinsic_argument_list_length (expr);
1145e690 6844 args = XALLOCAVEC (tree, num_args);
55637e51
LM
6845
6846 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6847
df1afcca
HA
6848 type = TREE_TYPE (args[0]);
6849 nbits = build_int_cst (long_integer_type_node, TYPE_PRECISION (type));
6850
55637e51 6851 if (num_args == 3)
6de9cd9a
DN
6852 {
6853 /* Use a library function for the 3 parameter version. */
56746a07
TS
6854 tree int4type = gfc_get_int_type (4);
6855
56746a07
TS
6856 /* We convert the first argument to at least 4 bytes, and
6857 convert back afterwards. This removes the need for library
6858 functions for all argument sizes, and function will be
6859 aligned to at least 32 bits, so there's no loss. */
6860 if (expr->ts.kind < 4)
55637e51
LM
6861 args[0] = convert (int4type, args[0]);
6862
56746a07
TS
6863 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
6864 need loads of library functions. They cannot have values >
6865 BIT_SIZE (I) so the conversion is safe. */
55637e51
LM
6866 args[1] = convert (int4type, args[1]);
6867 args[2] = convert (int4type, args[2]);
6de9cd9a 6868
df1afcca
HA
6869 /* Optionally generate code for runtime argument check. */
6870 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6871 {
6872 tree size = fold_convert (long_integer_type_node, args[2]);
6873 tree below = fold_build2_loc (input_location, LE_EXPR,
6874 logical_type_node, size,
6875 build_int_cst (TREE_TYPE (args[1]), 0));
6876 tree above = fold_build2_loc (input_location, GT_EXPR,
6877 logical_type_node, size, nbits);
6878 tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
6879 logical_type_node, below, above);
6880 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6881 "SIZE argument (%ld) out of range 1:%ld "
6882 "in intrinsic ISHFTC", size, nbits);
6883 tree width = fold_convert (long_integer_type_node, args[1]);
6884 width = fold_build1_loc (input_location, ABS_EXPR,
6885 long_integer_type_node, width);
6886 scond = fold_build2_loc (input_location, GT_EXPR,
6887 logical_type_node, width, size);
6888 gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where,
6889 "SHIFT argument (%ld) out of range -%ld:%ld "
6890 "in intrinsic ISHFTC",
6891 fold_convert (long_integer_type_node, args[1]),
6892 size, size);
6893 }
6894
6de9cd9a
DN
6895 switch (expr->ts.kind)
6896 {
56746a07
TS
6897 case 1:
6898 case 2:
6de9cd9a
DN
6899 case 4:
6900 tmp = gfor_fndecl_math_ishftc4;
6901 break;
6902 case 8:
6903 tmp = gfor_fndecl_math_ishftc8;
6904 break;
644cb69f
FXC
6905 case 16:
6906 tmp = gfor_fndecl_math_ishftc16;
6907 break;
6de9cd9a 6908 default:
6e45f57b 6909 gcc_unreachable ();
6de9cd9a 6910 }
db3927fb 6911 se->expr = build_call_expr_loc (input_location,
36d9e52f 6912 tmp, 3, args[0], args[1], args[2]);
56746a07
TS
6913 /* Convert the result back to the original type, if we extended
6914 the first argument's width above. */
6915 if (expr->ts.kind < 4)
6916 se->expr = convert (type, se->expr);
6917
6de9cd9a
DN
6918 return;
6919 }
6de9cd9a 6920
36d9e52f
FXC
6921 /* Evaluate arguments only once. */
6922 args[0] = gfc_evaluate_now (args[0], &se->pre);
6923 args[1] = gfc_evaluate_now (args[1], &se->pre);
6924
df1afcca
HA
6925 /* Optionally generate code for runtime argument check. */
6926 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
6927 {
6928 tree width = fold_convert (long_integer_type_node, args[1]);
6929 width = fold_build1_loc (input_location, ABS_EXPR,
6930 long_integer_type_node, width);
6931 tree outside = fold_build2_loc (input_location, GT_EXPR,
6932 logical_type_node, width, nbits);
6933 gfc_trans_runtime_check (true, false, outside, &se->pre, &expr->where,
6934 "SHIFT argument (%ld) out of range -%ld:%ld "
6935 "in intrinsic ISHFTC",
6936 fold_convert (long_integer_type_node, args[1]),
6937 nbits, nbits);
6938 }
6939
6de9cd9a 6940 /* Rotate left if positive. */
433ce291 6941 lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]);
6de9cd9a
DN
6942
6943 /* Rotate right if negative. */
433ce291
TB
6944 tmp = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (args[1]),
6945 args[1]);
6946 rrot = fold_build2_loc (input_location,RROTATE_EXPR, type, args[0], tmp);
6de9cd9a 6947
55637e51 6948 zero = build_int_cst (TREE_TYPE (args[1]), 0);
63ee5404 6949 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, args[1],
433ce291
TB
6950 zero);
6951 rrot = fold_build3_loc (input_location, COND_EXPR, type, tmp, lrot, rrot);
6de9cd9a
DN
6952
6953 /* Do nothing if shift == 0. */
63ee5404 6954 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, args[1],
433ce291
TB
6955 zero);
6956 se->expr = fold_build3_loc (input_location, COND_EXPR, type, tmp, args[0],
6957 rrot);
6de9cd9a
DN
6958}
6959
16c0e295 6960
414f00e9
SB
6961/* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
6962 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
6963
6964 The conditional expression is necessary because the result of LEADZ(0)
6965 is defined, but the result of __builtin_clz(0) is undefined for most
6966 targets.
6967
6968 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
6969 difference in bit size between the argument of LEADZ and the C int. */
029b2d55 6970
414f00e9
SB
6971static void
6972gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
6973{
6974 tree arg;
6975 tree arg_type;
6976 tree cond;
6977 tree result_type;
6978 tree leadz;
6979 tree bit_size;
6980 tree tmp;
0a05c536
FXC
6981 tree func;
6982 int s, argsize;
414f00e9
SB
6983
6984 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
0a05c536 6985 argsize = TYPE_PRECISION (TREE_TYPE (arg));
414f00e9
SB
6986
6987 /* Which variant of __builtin_clz* should we call? */
0a05c536
FXC
6988 if (argsize <= INT_TYPE_SIZE)
6989 {
6990 arg_type = unsigned_type_node;
e79983f4 6991 func = builtin_decl_explicit (BUILT_IN_CLZ);
0a05c536
FXC
6992 }
6993 else if (argsize <= LONG_TYPE_SIZE)
6994 {
6995 arg_type = long_unsigned_type_node;
e79983f4 6996 func = builtin_decl_explicit (BUILT_IN_CLZL);
0a05c536
FXC
6997 }
6998 else if (argsize <= LONG_LONG_TYPE_SIZE)
6999 {
7000 arg_type = long_long_unsigned_type_node;
e79983f4 7001 func = builtin_decl_explicit (BUILT_IN_CLZLL);
0a05c536
FXC
7002 }
7003 else
7004 {
16c0e295 7005 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
0a05c536 7006 arg_type = gfc_build_uint_type (argsize);
16c0e295 7007 func = NULL_TREE;
414f00e9
SB
7008 }
7009
0a05c536
FXC
7010 /* Convert the actual argument twice: first, to the unsigned type of the
7011 same size; then, to the proper argument type for the built-in
414f00e9 7012 function. But the return type is of the default INTEGER kind. */
0a05c536 7013 arg = fold_convert (gfc_build_uint_type (argsize), arg);
414f00e9 7014 arg = fold_convert (arg_type, arg);
16c0e295 7015 arg = gfc_evaluate_now (arg, &se->pre);
414f00e9
SB
7016 result_type = gfc_get_int_type (gfc_default_integer_kind);
7017
7018 /* Compute LEADZ for the case i .ne. 0. */
16c0e295
FXC
7019 if (func)
7020 {
7021 s = TYPE_PRECISION (arg_type) - argsize;
7022 tmp = fold_convert (result_type,
7023 build_call_expr_loc (input_location, func,
7024 1, arg));
7025 leadz = fold_build2_loc (input_location, MINUS_EXPR, result_type,
7026 tmp, build_int_cst (result_type, s));
7027 }
7028 else
7029 {
7030 /* We end up here if the argument type is larger than 'long long'.
7031 We generate this code:
029b2d55 7032
16c0e295
FXC
7033 if (x & (ULL_MAX << ULL_SIZE) != 0)
7034 return clzll ((unsigned long long) (x >> ULLSIZE));
7035 else
7036 return ULL_SIZE + clzll ((unsigned long long) x);
16c0e295
FXC
7037 where ULL_MAX is the largest value that a ULL_MAX can hold
7038 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
7039 is the bit-size of the long long type (64 in this example). */
e79983f4 7040 tree ullsize, ullmax, tmp1, tmp2, btmp;
16c0e295
FXC
7041
7042 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
7043 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
7044 long_long_unsigned_type_node,
7045 build_int_cst (long_long_unsigned_type_node,
7046 0));
7047
7048 cond = fold_build2_loc (input_location, LSHIFT_EXPR, arg_type,
7049 fold_convert (arg_type, ullmax), ullsize);
7050 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type,
7051 arg, cond);
63ee5404 7052 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
16c0e295
FXC
7053 cond, build_int_cst (arg_type, 0));
7054
7055 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
7056 arg, ullsize);
7057 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
e79983f4 7058 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
16c0e295 7059 tmp1 = fold_convert (result_type,
e79983f4 7060 build_call_expr_loc (input_location, btmp, 1, tmp1));
16c0e295
FXC
7061
7062 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
e79983f4 7063 btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
16c0e295 7064 tmp2 = fold_convert (result_type,
e79983f4 7065 build_call_expr_loc (input_location, btmp, 1, tmp2));
16c0e295
FXC
7066 tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
7067 tmp2, ullsize);
7068
7069 leadz = fold_build3_loc (input_location, COND_EXPR, result_type,
7070 cond, tmp1, tmp2);
7071 }
414f00e9
SB
7072
7073 /* Build BIT_SIZE. */
0a05c536 7074 bit_size = build_int_cst (result_type, argsize);
414f00e9 7075
63ee5404 7076 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
433ce291
TB
7077 arg, build_int_cst (arg_type, 0));
7078 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
7079 bit_size, leadz);
414f00e9
SB
7080}
7081
16c0e295 7082
414f00e9
SB
7083/* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
7084
7085 The conditional expression is necessary because the result of TRAILZ(0)
7086 is defined, but the result of __builtin_ctz(0) is undefined for most
7087 targets. */
029b2d55 7088
414f00e9
SB
7089static void
7090gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
7091{
7092 tree arg;
7093 tree arg_type;
7094 tree cond;
7095 tree result_type;
7096 tree trailz;
7097 tree bit_size;
0a05c536
FXC
7098 tree func;
7099 int argsize;
414f00e9
SB
7100
7101 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
0a05c536 7102 argsize = TYPE_PRECISION (TREE_TYPE (arg));
414f00e9 7103
0a05c536
FXC
7104 /* Which variant of __builtin_ctz* should we call? */
7105 if (argsize <= INT_TYPE_SIZE)
7106 {
7107 arg_type = unsigned_type_node;
e79983f4 7108 func = builtin_decl_explicit (BUILT_IN_CTZ);
0a05c536
FXC
7109 }
7110 else if (argsize <= LONG_TYPE_SIZE)
7111 {
7112 arg_type = long_unsigned_type_node;
e79983f4 7113 func = builtin_decl_explicit (BUILT_IN_CTZL);
0a05c536
FXC
7114 }
7115 else if (argsize <= LONG_LONG_TYPE_SIZE)
7116 {
7117 arg_type = long_long_unsigned_type_node;
e79983f4 7118 func = builtin_decl_explicit (BUILT_IN_CTZLL);
0a05c536
FXC
7119 }
7120 else
7121 {
16c0e295 7122 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
0a05c536 7123 arg_type = gfc_build_uint_type (argsize);
16c0e295 7124 func = NULL_TREE;
414f00e9
SB
7125 }
7126
0a05c536
FXC
7127 /* Convert the actual argument twice: first, to the unsigned type of the
7128 same size; then, to the proper argument type for the built-in
414f00e9 7129 function. But the return type is of the default INTEGER kind. */
0a05c536 7130 arg = fold_convert (gfc_build_uint_type (argsize), arg);
414f00e9 7131 arg = fold_convert (arg_type, arg);
16c0e295 7132 arg = gfc_evaluate_now (arg, &se->pre);
414f00e9
SB
7133 result_type = gfc_get_int_type (gfc_default_integer_kind);
7134
7135 /* Compute TRAILZ for the case i .ne. 0. */
16c0e295
FXC
7136 if (func)
7137 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
7138 func, 1, arg));
7139 else
7140 {
7141 /* We end up here if the argument type is larger than 'long long'.
7142 We generate this code:
029b2d55 7143
16c0e295
FXC
7144 if ((x & ULL_MAX) == 0)
7145 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
7146 else
7147 return ctzll ((unsigned long long) x);
7148
7149 where ULL_MAX is the largest value that a ULL_MAX can hold
7150 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
7151 is the bit-size of the long long type (64 in this example). */
e79983f4 7152 tree ullsize, ullmax, tmp1, tmp2, btmp;
16c0e295
FXC
7153
7154 ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
7155 ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
7156 long_long_unsigned_type_node,
7157 build_int_cst (long_long_unsigned_type_node, 0));
7158
7159 cond = fold_build2_loc (input_location, BIT_AND_EXPR, arg_type, arg,
7160 fold_convert (arg_type, ullmax));
63ee5404 7161 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, cond,
16c0e295
FXC
7162 build_int_cst (arg_type, 0));
7163
7164 tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
7165 arg, ullsize);
7166 tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
e79983f4 7167 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
16c0e295 7168 tmp1 = fold_convert (result_type,
e79983f4 7169 build_call_expr_loc (input_location, btmp, 1, tmp1));
16c0e295
FXC
7170 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
7171 tmp1, ullsize);
7172
7173 tmp2 = fold_convert (long_long_unsigned_type_node, arg);
e79983f4 7174 btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
16c0e295 7175 tmp2 = fold_convert (result_type,
e79983f4 7176 build_call_expr_loc (input_location, btmp, 1, tmp2));
16c0e295
FXC
7177
7178 trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
7179 cond, tmp1, tmp2);
7180 }
414f00e9
SB
7181
7182 /* Build BIT_SIZE. */
0a05c536 7183 bit_size = build_int_cst (result_type, argsize);
414f00e9 7184
63ee5404 7185 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
433ce291
TB
7186 arg, build_int_cst (arg_type, 0));
7187 se->expr = fold_build3_loc (input_location, COND_EXPR, result_type, cond,
7188 bit_size, trailz);
414f00e9 7189}
1fbfb0e2 7190
ad5f4de2
FXC
7191/* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
7192 for types larger than "long long", we call the long long built-in for
7193 the lower and higher bits and combine the result. */
029b2d55 7194
ad5f4de2
FXC
7195static void
7196gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
7197{
7198 tree arg;
7199 tree arg_type;
7200 tree result_type;
7201 tree func;
7202 int argsize;
7203
7204 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7205 argsize = TYPE_PRECISION (TREE_TYPE (arg));
7206 result_type = gfc_get_int_type (gfc_default_integer_kind);
7207
7208 /* Which variant of the builtin should we call? */
7209 if (argsize <= INT_TYPE_SIZE)
7210 {
7211 arg_type = unsigned_type_node;
e79983f4
MM
7212 func = builtin_decl_explicit (parity
7213 ? BUILT_IN_PARITY
7214 : BUILT_IN_POPCOUNT);
ad5f4de2
FXC
7215 }
7216 else if (argsize <= LONG_TYPE_SIZE)
7217 {
7218 arg_type = long_unsigned_type_node;
e79983f4
MM
7219 func = builtin_decl_explicit (parity
7220 ? BUILT_IN_PARITYL
7221 : BUILT_IN_POPCOUNTL);
ad5f4de2
FXC
7222 }
7223 else if (argsize <= LONG_LONG_TYPE_SIZE)
7224 {
7225 arg_type = long_long_unsigned_type_node;
e79983f4
MM
7226 func = builtin_decl_explicit (parity
7227 ? BUILT_IN_PARITYLL
7228 : BUILT_IN_POPCOUNTLL);
ad5f4de2
FXC
7229 }
7230 else
7231 {
7232 /* Our argument type is larger than 'long long', which mean none
7233 of the POPCOUNT builtins covers it. We thus call the 'long long'
7234 variant multiple times, and add the results. */
7235 tree utype, arg2, call1, call2;
7236
7237 /* For now, we only cover the case where argsize is twice as large
7238 as 'long long'. */
7239 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
7240
e79983f4
MM
7241 func = builtin_decl_explicit (parity
7242 ? BUILT_IN_PARITYLL
7243 : BUILT_IN_POPCOUNTLL);
ad5f4de2
FXC
7244
7245 /* Convert it to an integer, and store into a variable. */
7246 utype = gfc_build_uint_type (argsize);
7247 arg = fold_convert (utype, arg);
7248 arg = gfc_evaluate_now (arg, &se->pre);
7249
7250 /* Call the builtin twice. */
7251 call1 = build_call_expr_loc (input_location, func, 1,
7252 fold_convert (long_long_unsigned_type_node,
7253 arg));
7254
433ce291
TB
7255 arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
7256 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
ad5f4de2
FXC
7257 call2 = build_call_expr_loc (input_location, func, 1,
7258 fold_convert (long_long_unsigned_type_node,
7259 arg2));
029b2d55 7260
ad5f4de2
FXC
7261 /* Combine the results. */
7262 if (parity)
7eb61a45
HA
7263 se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR,
7264 integer_type_node, call1, call2);
ad5f4de2 7265 else
7eb61a45
HA
7266 se->expr = fold_build2_loc (input_location, PLUS_EXPR,
7267 integer_type_node, call1, call2);
ad5f4de2 7268
7eb61a45 7269 se->expr = convert (result_type, se->expr);
ad5f4de2
FXC
7270 return;
7271 }
7272
7273 /* Convert the actual argument twice: first, to the unsigned type of the
7274 same size; then, to the proper argument type for the built-in
7275 function. */
7276 arg = fold_convert (gfc_build_uint_type (argsize), arg);
7277 arg = fold_convert (arg_type, arg);
7278
7279 se->expr = fold_convert (result_type,
7280 build_call_expr_loc (input_location, func, 1, arg));
7281}
7282
7283
1fbfb0e2
DK
7284/* Process an intrinsic with unspecified argument-types that has an optional
7285 argument (which could be of type character), e.g. EOSHIFT. For those, we
7286 need to append the string length of the optional argument if it is not
7287 present and the type is really character.
7288 primary specifies the position (starting at 1) of the non-optional argument
7289 specifying the type and optional gives the position of the optional
7290 argument in the arglist. */
7291
7292static void
7293conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
7294 unsigned primary, unsigned optional)
7295{
7296 gfc_actual_arglist* prim_arg;
7297 gfc_actual_arglist* opt_arg;
7298 unsigned cur_pos;
7299 gfc_actual_arglist* arg;
7300 gfc_symbol* sym;
9771b263 7301 vec<tree, va_gc> *append_args;
1fbfb0e2
DK
7302
7303 /* Find the two arguments given as position. */
7304 cur_pos = 0;
7305 prim_arg = NULL;
7306 opt_arg = NULL;
7307 for (arg = expr->value.function.actual; arg; arg = arg->next)
7308 {
7309 ++cur_pos;
7310
7311 if (cur_pos == primary)
7312 prim_arg = arg;
7313 if (cur_pos == optional)
7314 opt_arg = arg;
7315
7316 if (cur_pos >= primary && cur_pos >= optional)
7317 break;
7318 }
7319 gcc_assert (prim_arg);
7320 gcc_assert (prim_arg->expr);
7321 gcc_assert (opt_arg);
7322
7323 /* If we do have type CHARACTER and the optional argument is really absent,
7324 append a dummy 0 as string length. */
989ea525 7325 append_args = NULL;
1fbfb0e2
DK
7326 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
7327 {
7328 tree dummy;
7329
7330 dummy = build_int_cst (gfc_charlen_type_node, 0);
9771b263
DN
7331 vec_alloc (append_args, 1);
7332 append_args->quick_push (dummy);
1fbfb0e2
DK
7333 }
7334
7335 /* Build the call itself. */
8fdcb6a9
TB
7336 gcc_assert (!se->ignore_optional);
7337 sym = gfc_get_symbol_for_expr (expr, false);
713485cc
JW
7338 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
7339 append_args);
15a611c0 7340 gfc_free_symbol (sym);
1fbfb0e2
DK
7341}
7342
6de9cd9a
DN
7343/* The length of a character string. */
7344static void
7345gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
7346{
7347 tree len;
7348 tree type;
7349 tree decl;
7350 gfc_symbol *sym;
7351 gfc_se argse;
7352 gfc_expr *arg;
7353
6e45f57b 7354 gcc_assert (!se->ss);
6de9cd9a
DN
7355
7356 arg = expr->value.function.actual->expr;
7357
7358 type = gfc_typenode_for_spec (&expr->ts);
7359 switch (arg->expr_type)
7360 {
7361 case EXPR_CONSTANT:
df09d1d5 7362 len = build_int_cst (gfc_charlen_type_node, arg->value.character.length);
6de9cd9a
DN
7363 break;
7364
636da744
PT
7365 case EXPR_ARRAY:
7366 /* Obtain the string length from the function used by
e53b6e56 7367 trans-array.cc(gfc_trans_array_constructor). */
636da744 7368 len = NULL_TREE;
0ee8e250 7369 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
636da744
PT
7370 break;
7371
dd5797cc
PT
7372 case EXPR_VARIABLE:
7373 if (arg->ref == NULL
7374 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
7375 {
7376 /* This doesn't catch all cases.
7377 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
7378 and the surrounding thread. */
7379 sym = arg->symtree->n.sym;
7380 decl = gfc_get_symbol_decl (sym);
7381 if (decl == current_function_decl && sym->attr.function
6de9cd9a 7382 && (sym->result == sym))
dd5797cc
PT
7383 decl = gfc_get_fake_result_decl (sym, 0);
7384
bc21d315 7385 len = sym->ts.u.cl->backend_decl;
dd5797cc
PT
7386 gcc_assert (len);
7387 break;
6de9cd9a 7388 }
dd5797cc 7389
191816a3 7390 /* Fall through. */
dd5797cc
PT
7391
7392 default:
dd5797cc 7393 gfc_init_se (&argse, se);
2960a368 7394 if (arg->rank == 0)
dd5797cc
PT
7395 gfc_conv_expr (&argse, arg);
7396 else
2960a368 7397 gfc_conv_expr_descriptor (&argse, arg);
dd5797cc
PT
7398 gfc_add_block_to_block (&se->pre, &argse.pre);
7399 gfc_add_block_to_block (&se->post, &argse.post);
7400 len = argse.string_length;
6de9cd9a
DN
7401 break;
7402 }
7403 se->expr = convert (type, len);
7404}
7405
7406/* The length of a character string not including trailing blanks. */
7407static void
7408gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
7409{
374929b2
FXC
7410 int kind = expr->value.function.actual->expr->ts.kind;
7411 tree args[2], type, fndecl;
6de9cd9a 7412
55637e51 7413 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6de9cd9a 7414 type = gfc_typenode_for_spec (&expr->ts);
374929b2
FXC
7415
7416 if (kind == 1)
7417 fndecl = gfor_fndecl_string_len_trim;
7418 else if (kind == 4)
7419 fndecl = gfor_fndecl_string_len_trim_char4;
7420 else
7421 gcc_unreachable ();
7422
db3927fb
AH
7423 se->expr = build_call_expr_loc (input_location,
7424 fndecl, 2, args[0], args[1]);
6de9cd9a
DN
7425 se->expr = convert (type, se->expr);
7426}
7427
7428
7429/* Returns the starting position of a substring within a string. */
7430
7431static void
5cda5098
FXC
7432gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
7433 tree function)
6de9cd9a 7434{
0da87370 7435 tree logical4_type_node = gfc_get_logical_type (4);
6de9cd9a 7436 tree type;
55637e51
LM
7437 tree fndecl;
7438 tree *args;
7439 unsigned int num_args;
6de9cd9a 7440
1145e690 7441 args = XALLOCAVEC (tree, 5);
55637e51 7442
f5dce797 7443 /* Get number of arguments; characters count double due to the
df2fba9e 7444 string length argument. Kind= is not passed to the library
f5dce797
TB
7445 and thus ignored. */
7446 if (expr->value.function.actual->next->next->expr == NULL)
7447 num_args = 4;
7448 else
7449 num_args = 5;
7450
7451 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6de9cd9a 7452 type = gfc_typenode_for_spec (&expr->ts);
55637e51
LM
7453
7454 if (num_args == 4)
7455 args[4] = build_int_cst (logical4_type_node, 0);
6de9cd9a 7456 else
5cda5098 7457 args[4] = convert (logical4_type_node, args[4]);
6de9cd9a 7458
aa00059c 7459 fndecl = build_addr (function);
db3927fb
AH
7460 se->expr = build_call_array_loc (input_location,
7461 TREE_TYPE (TREE_TYPE (function)), fndecl,
5cda5098 7462 5, args);
6de9cd9a 7463 se->expr = convert (type, se->expr);
55637e51 7464
6de9cd9a
DN
7465}
7466
7467/* The ascii value for a single character. */
7468static void
7469gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
7470{
f6b80ca0 7471 tree args[3], type, pchartype;
f0cbaeb8 7472 int nargs;
6de9cd9a 7473
f0cbaeb8
MM
7474 nargs = gfc_intrinsic_argument_list_length (expr);
7475 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
55637e51 7476 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
374929b2 7477 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
433ce291 7478 args[1] = fold_build1_loc (input_location, NOP_EXPR, pchartype, args[1]);
6de9cd9a
DN
7479 type = gfc_typenode_for_spec (&expr->ts);
7480
db3927fb
AH
7481 se->expr = build_fold_indirect_ref_loc (input_location,
7482 args[1]);
6de9cd9a
DN
7483 se->expr = convert (type, se->expr);
7484}
7485
7486
3d97b1af
FXC
7487/* Intrinsic ISNAN calls __builtin_isnan. */
7488
7489static void
7490gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
7491{
7492 tree arg;
7493
7494 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
db3927fb 7495 se->expr = build_call_expr_loc (input_location,
e79983f4
MM
7496 builtin_decl_explicit (BUILT_IN_ISNAN),
7497 1, arg);
e1332188 7498 STRIP_TYPE_NOPS (se->expr);
3d97b1af
FXC
7499 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
7500}
7501
bae89173
FXC
7502
7503/* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
7504 their argument against a constant integer value. */
7505
7506static void
7507gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
7508{
7509 tree arg;
7510
7511 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
433ce291
TB
7512 se->expr = fold_build2_loc (input_location, EQ_EXPR,
7513 gfc_typenode_for_spec (&expr->ts),
7514 arg, build_int_cst (TREE_TYPE (arg), value));
bae89173
FXC
7515}
7516
7517
7518
6de9cd9a
DN
7519/* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
7520
7521static void
7522gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
7523{
6de9cd9a
DN
7524 tree tsource;
7525 tree fsource;
7526 tree mask;
7527 tree type;
8c13133c 7528 tree len, len2;
55637e51
LM
7529 tree *args;
7530 unsigned int num_args;
7531
7532 num_args = gfc_intrinsic_argument_list_length (expr);
1145e690 7533 args = XALLOCAVEC (tree, num_args);
6de9cd9a 7534
55637e51 7535 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
c3d0559d
TS
7536 if (expr->ts.type != BT_CHARACTER)
7537 {
55637e51
LM
7538 tsource = args[0];
7539 fsource = args[1];
7540 mask = args[2];
c3d0559d
TS
7541 }
7542 else
7543 {
7544 /* We do the same as in the non-character case, but the argument
7545 list is different because of the string length arguments. We
7546 also have to set the string length for the result. */
55637e51
LM
7547 len = args[0];
7548 tsource = args[1];
8c13133c 7549 len2 = args[2];
55637e51
LM
7550 fsource = args[3];
7551 mask = args[4];
c3d0559d 7552
fb5bc08b
DK
7553 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
7554 &se->pre);
c3d0559d
TS
7555 se->string_length = len;
7556 }
6de9cd9a 7557 type = TREE_TYPE (tsource);
433ce291
TB
7558 se->expr = fold_build3_loc (input_location, COND_EXPR, type, mask, tsource,
7559 fold_convert (type, fsource));
6de9cd9a
DN
7560}
7561
7562
88a95a11
FXC
7563/* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
7564
7565static void
7566gfc_conv_intrinsic_merge_bits (gfc_se * se, gfc_expr * expr)
7567{
7568 tree args[3], mask, type;
7569
7570 gfc_conv_intrinsic_function_args (se, expr, args, 3);
7571 mask = gfc_evaluate_now (args[2], &se->pre);
7572
7573 type = TREE_TYPE (args[0]);
7574 gcc_assert (TREE_TYPE (args[1]) == type);
7575 gcc_assert (TREE_TYPE (mask) == type);
7576
7577 args[0] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], mask);
7578 args[1] = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[1],
7579 fold_build1_loc (input_location, BIT_NOT_EXPR,
7580 type, mask));
7581 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
7582 args[0], args[1]);
7583}
7584
7585
7586/* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
7587 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
7588
7589static void
7590gfc_conv_intrinsic_mask (gfc_se * se, gfc_expr * expr, int left)
7591{
7592 tree arg, allones, type, utype, res, cond, bitsize;
7593 int i;
029b2d55 7594
88a95a11
FXC
7595 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7596 arg = gfc_evaluate_now (arg, &se->pre);
7597
7598 type = gfc_get_int_type (expr->ts.kind);
7599 utype = unsigned_type_for (type);
7600
7601 i = gfc_validate_kind (BT_INTEGER, expr->ts.kind, false);
7602 bitsize = build_int_cst (TREE_TYPE (arg), gfc_integer_kinds[i].bit_size);
7603
7604 allones = fold_build1_loc (input_location, BIT_NOT_EXPR, utype,
7605 build_int_cst (utype, 0));
7606
7607 if (left)
7608 {
7609 /* Left-justified mask. */
7610 res = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (arg),
7611 bitsize, arg);
7612 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
7613 fold_convert (utype, res));
7614
7615 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
7616 smaller than type width. */
63ee5404 7617 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
88a95a11
FXC
7618 build_int_cst (TREE_TYPE (arg), 0));
7619 res = fold_build3_loc (input_location, COND_EXPR, utype, cond,
7620 build_int_cst (utype, 0), res);
7621 }
7622 else
7623 {
7624 /* Right-justified mask. */
7625 res = fold_build2_loc (input_location, LSHIFT_EXPR, utype, allones,
7626 fold_convert (utype, arg));
7627 res = fold_build1_loc (input_location, BIT_NOT_EXPR, utype, res);
7628
7629 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
7630 strictly smaller than type width. */
63ee5404 7631 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
88a95a11
FXC
7632 arg, bitsize);
7633 res = fold_build3_loc (input_location, COND_EXPR, utype,
7634 cond, allones, res);
7635 }
7636
7637 se->expr = fold_convert (type, res);
7638}
7639
7640
565fad70
FXC
7641/* FRACTION (s) is translated into:
7642 isfinite (s) ? frexp (s, &dummy_int) : NaN */
b5a4419c
FXC
7643static void
7644gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
7645{
565fad70 7646 tree arg, type, tmp, res, frexp, cond;
b5a4419c 7647
166d08bd 7648 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
b5a4419c
FXC
7649
7650 type = gfc_typenode_for_spec (&expr->ts);
7651 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
565fad70
FXC
7652 arg = gfc_evaluate_now (arg, &se->pre);
7653
7654 cond = build_call_expr_loc (input_location,
7655 builtin_decl_explicit (BUILT_IN_ISFINITE),
7656 1, arg);
7657
b5a4419c 7658 tmp = gfc_create_var (integer_type_node, NULL);
565fad70
FXC
7659 res = build_call_expr_loc (input_location, frexp, 2,
7660 fold_convert (type, arg),
7661 gfc_build_addr_expr (NULL_TREE, tmp));
7662 res = fold_convert (type, res);
7663
7664 se->expr = fold_build3_loc (input_location, COND_EXPR, type,
7665 cond, res, gfc_build_nan (type, ""));
b5a4419c
FXC
7666}
7667
7668
7669/* NEAREST (s, dir) is translated into
f6d53468 7670 tmp = copysign (HUGE_VAL, dir);
b5a4419c
FXC
7671 return nextafter (s, tmp);
7672 */
7673static void
7674gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
7675{
2921157d 7676 tree args[2], type, tmp, nextafter, copysign, huge_val;
b5a4419c 7677
166d08bd
FXC
7678 nextafter = gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
7679 copysign = gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
b5a4419c
FXC
7680
7681 type = gfc_typenode_for_spec (&expr->ts);
7682 gfc_conv_intrinsic_function_args (se, expr, args, 2);
a67189d4
FXC
7683
7684 huge_val = gfc_build_inf_or_huge (type, expr->ts.kind);
7685 tmp = build_call_expr_loc (input_location, copysign, 2, huge_val,
2921157d
FXC
7686 fold_convert (type, args[1]));
7687 se->expr = build_call_expr_loc (input_location, nextafter, 2,
7688 fold_convert (type, args[0]), tmp);
b5a4419c
FXC
7689 se->expr = fold_convert (type, se->expr);
7690}
7691
7692
7693/* SPACING (s) is translated into
7694 int e;
565fad70
FXC
7695 if (!isfinite (s))
7696 res = NaN;
7697 else if (s == 0)
b5a4419c
FXC
7698 res = tiny;
7699 else
7700 {
7701 frexp (s, &e);
7702 e = e - prec;
7703 e = MAX_EXPR (e, emin);
7704 res = scalbn (1., e);
7705 }
7706 return res;
7707
7708 where prec is the precision of s, gfc_real_kinds[k].digits,
7709 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
7710 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
7711
7712static void
7713gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
7714{
7715 tree arg, type, prec, emin, tiny, res, e;
565fad70 7716 tree cond, nan, tmp, frexp, scalbn;
2921157d 7717 int k;
b5a4419c
FXC
7718 stmtblock_t block;
7719
7720 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
df09d1d5
RG
7721 prec = build_int_cst (integer_type_node, gfc_real_kinds[k].digits);
7722 emin = build_int_cst (integer_type_node, gfc_real_kinds[k].min_exponent - 1);
346a77d1 7723 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
b5a4419c 7724
166d08bd
FXC
7725 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
7726 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
b5a4419c
FXC
7727
7728 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7729 arg = gfc_evaluate_now (arg, &se->pre);
7730
7731 type = gfc_typenode_for_spec (&expr->ts);
7732 e = gfc_create_var (integer_type_node, NULL);
7733 res = gfc_create_var (type, NULL);
7734
7735
7736 /* Build the block for s /= 0. */
7737 gfc_start_block (&block);
2921157d
FXC
7738 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
7739 gfc_build_addr_expr (NULL_TREE, e));
b5a4419c
FXC
7740 gfc_add_expr_to_block (&block, tmp);
7741
433ce291
TB
7742 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node, e,
7743 prec);
7744 gfc_add_modify (&block, e, fold_build2_loc (input_location, MAX_EXPR,
7745 integer_type_node, tmp, emin));
b5a4419c 7746
2921157d 7747 tmp = build_call_expr_loc (input_location, scalbn, 2,
b5a4419c 7748 build_real_from_int_cst (type, integer_one_node), e);
726a989a 7749 gfc_add_modify (&block, res, tmp);
b5a4419c 7750
565fad70 7751 /* Finish by building the IF statement for value zero. */
63ee5404 7752 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
433ce291 7753 build_real_from_int_cst (type, integer_zero_node));
b5a4419c
FXC
7754 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
7755 gfc_finish_block (&block));
7756
565fad70
FXC
7757 /* And deal with infinities and NaNs. */
7758 cond = build_call_expr_loc (input_location,
7759 builtin_decl_explicit (BUILT_IN_ISFINITE),
7760 1, arg);
7761 nan = gfc_build_nan (type, "");
7762 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, res, nan));
7763
b5a4419c
FXC
7764 gfc_add_expr_to_block (&se->pre, tmp);
7765 se->expr = res;
7766}
7767
7768
7769/* RRSPACING (s) is translated into
7770 int e;
7771 real x;
7772 x = fabs (s);
565fad70 7773 if (isfinite (x))
b5a4419c 7774 {
565fad70
FXC
7775 if (x != 0)
7776 {
7777 frexp (s, &e);
7778 x = scalbn (x, precision - e);
7779 }
b5a4419c 7780 }
565fad70
FXC
7781 else
7782 x = NaN;
b5a4419c
FXC
7783 return x;
7784
7785 where precision is gfc_real_kinds[k].digits. */
7786
7787static void
7788gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
7789{
565fad70 7790 tree arg, type, e, x, cond, nan, stmt, tmp, frexp, scalbn, fabs;
2921157d 7791 int prec, k;
b5a4419c
FXC
7792 stmtblock_t block;
7793
7794 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
7795 prec = gfc_real_kinds[k].digits;
2921157d 7796
166d08bd
FXC
7797 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
7798 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
7799 fabs = gfc_builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
b5a4419c
FXC
7800
7801 type = gfc_typenode_for_spec (&expr->ts);
7802 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
7803 arg = gfc_evaluate_now (arg, &se->pre);
7804
7805 e = gfc_create_var (integer_type_node, NULL);
7806 x = gfc_create_var (type, NULL);
726a989a 7807 gfc_add_modify (&se->pre, x,
2921157d 7808 build_call_expr_loc (input_location, fabs, 1, arg));
b5a4419c
FXC
7809
7810
7811 gfc_start_block (&block);
2921157d
FXC
7812 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
7813 gfc_build_addr_expr (NULL_TREE, e));
b5a4419c
FXC
7814 gfc_add_expr_to_block (&block, tmp);
7815
433ce291 7816 tmp = fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
df09d1d5 7817 build_int_cst (integer_type_node, prec), e);
2921157d 7818 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
726a989a 7819 gfc_add_modify (&block, x, tmp);
b5a4419c
FXC
7820 stmt = gfc_finish_block (&block);
7821
565fad70 7822 /* if (x != 0) */
63ee5404 7823 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, x,
433ce291 7824 build_real_from_int_cst (type, integer_zero_node));
c2255bc4 7825 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
b5a4419c 7826
565fad70
FXC
7827 /* And deal with infinities and NaNs. */
7828 cond = build_call_expr_loc (input_location,
7829 builtin_decl_explicit (BUILT_IN_ISFINITE),
7830 1, x);
7831 nan = gfc_build_nan (type, "");
7832 tmp = build3_v (COND_EXPR, cond, tmp, build2_v (MODIFY_EXPR, x, nan));
7833
7834 gfc_add_expr_to_block (&se->pre, tmp);
b5a4419c
FXC
7835 se->expr = fold_convert (type, x);
7836}
7837
7838
7839/* SCALE (s, i) is translated into scalbn (s, i). */
7840static void
7841gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
7842{
2921157d 7843 tree args[2], type, scalbn;
b5a4419c 7844
166d08bd 7845 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
b5a4419c
FXC
7846
7847 type = gfc_typenode_for_spec (&expr->ts);
7848 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2921157d
FXC
7849 se->expr = build_call_expr_loc (input_location, scalbn, 2,
7850 fold_convert (type, args[0]),
7851 fold_convert (integer_type_node, args[1]));
b5a4419c
FXC
7852 se->expr = fold_convert (type, se->expr);
7853}
7854
7855
7856/* SET_EXPONENT (s, i) is translated into
565fad70 7857 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
b5a4419c
FXC
7858static void
7859gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
7860{
565fad70 7861 tree args[2], type, tmp, frexp, scalbn, cond, nan, res;
b5a4419c 7862
166d08bd
FXC
7863 frexp = gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
7864 scalbn = gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
b5a4419c
FXC
7865
7866 type = gfc_typenode_for_spec (&expr->ts);
7867 gfc_conv_intrinsic_function_args (se, expr, args, 2);
565fad70 7868 args[0] = gfc_evaluate_now (args[0], &se->pre);
b5a4419c
FXC
7869
7870 tmp = gfc_create_var (integer_type_node, NULL);
2921157d
FXC
7871 tmp = build_call_expr_loc (input_location, frexp, 2,
7872 fold_convert (type, args[0]),
7873 gfc_build_addr_expr (NULL_TREE, tmp));
565fad70
FXC
7874 res = build_call_expr_loc (input_location, scalbn, 2, tmp,
7875 fold_convert (integer_type_node, args[1]));
7876 res = fold_convert (type, res);
7877
7878 /* Call to isfinite */
7879 cond = build_call_expr_loc (input_location,
7880 builtin_decl_explicit (BUILT_IN_ISFINITE),
7881 1, args[0]);
7882 nan = gfc_build_nan (type, "");
7883
7884 se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
7885 res, nan);
b5a4419c
FXC
7886}
7887
7888
6de9cd9a
DN
7889static void
7890gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
7891{
7892 gfc_actual_arglist *actual;
88f206a4 7893 tree arg1;
6de9cd9a 7894 tree type;
00f6de9c 7895 tree size;
6de9cd9a 7896 gfc_se argse;
16a51cf5
PT
7897 gfc_expr *e;
7898 gfc_symbol *sym = NULL;
6de9cd9a
DN
7899
7900 gfc_init_se (&argse, NULL);
7901 actual = expr->value.function.actual;
7902
c49ea23d
PT
7903 if (actual->expr->ts.type == BT_CLASS)
7904 gfc_add_class_array_ref (actual->expr);
7905
16a51cf5
PT
7906 e = actual->expr;
7907
7908 /* These are emerging from the interface mapping, when a class valued
7909 function appears as the rhs in a realloc on assign statement, where
7910 the size of the result is that of one of the actual arguments. */
7911 if (e->expr_type == EXPR_VARIABLE
7912 && e->symtree->n.sym->ns == NULL /* This is distinctive! */
7913 && e->symtree->n.sym->ts.type == BT_CLASS
7914 && e->ref && e->ref->type == REF_COMPONENT
7915 && strcmp (e->ref->u.c.component->name, "_data") == 0)
7916 sym = e->symtree->n.sym;
7917
0c81ccc3
HA
7918 if ((gfc_option.rtcheck & GFC_RTCHECK_POINTER)
7919 && e
7920 && (e->expr_type == EXPR_VARIABLE || e->expr_type == EXPR_FUNCTION))
7921 {
7922 symbol_attribute attr;
7923 char *msg;
c2d7c39f
HA
7924 tree temp;
7925 tree cond;
0c81ccc3 7926
71d7dc6c
HA
7927 if (e->symtree->n.sym && IS_CLASS_ARRAY (e->symtree->n.sym))
7928 {
7929 attr = CLASS_DATA (e->symtree->n.sym)->attr;
7930 attr.pointer = attr.class_pointer;
7931 }
7932 else
7933 attr = gfc_expr_attr (e);
7934
0c81ccc3
HA
7935 if (attr.allocatable)
7936 msg = xasprintf ("Allocatable argument '%s' is not allocated",
7937 e->symtree->n.sym->name);
7938 else if (attr.pointer)
7939 msg = xasprintf ("Pointer argument '%s' is not associated",
7940 e->symtree->n.sym->name);
7941 else
7942 goto end_arg_check;
7943
c2d7c39f
HA
7944 if (sym)
7945 {
7946 temp = gfc_class_data_get (sym->backend_decl);
7947 temp = gfc_conv_descriptor_data_get (temp);
7948 }
7949 else
7950 {
7951 argse.descriptor_only = 1;
7952 gfc_conv_expr_descriptor (&argse, actual->expr);
7953 temp = gfc_conv_descriptor_data_get (argse.expr);
7954 }
7955
7956 cond = fold_build2_loc (input_location, EQ_EXPR,
7957 logical_type_node, temp,
7958 fold_convert (TREE_TYPE (temp),
7959 null_pointer_node));
0c81ccc3 7960 gfc_trans_runtime_check (true, false, cond, &argse.pre, &e->where, msg);
c2d7c39f 7961
0c81ccc3
HA
7962 free (msg);
7963 }
7964 end_arg_check:
7965
ad5dd90d 7966 argse.data_not_needed = 1;
16a51cf5 7967 if (gfc_is_class_array_function (e))
92c5266b
AV
7968 {
7969 /* For functions that return a class array conv_expr_descriptor is not
7970 able to get the descriptor right. Therefore this special case. */
16a51cf5 7971 gfc_conv_expr_reference (&argse, e);
00f6de9c 7972 argse.expr = gfc_class_data_get (argse.expr);
16a51cf5
PT
7973 }
7974 else if (sym && sym->backend_decl)
7975 {
7976 gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (sym->backend_decl)));
00f6de9c 7977 argse.expr = gfc_class_data_get (sym->backend_decl);
92c5266b
AV
7978 }
7979 else
00f6de9c 7980 gfc_conv_expr_descriptor (&argse, actual->expr);
6de9cd9a
DN
7981 gfc_add_block_to_block (&se->pre, &argse.pre);
7982 gfc_add_block_to_block (&se->post, &argse.post);
00f6de9c 7983 arg1 = argse.expr;
6de9cd9a
DN
7984
7985 actual = actual->next;
7986 if (actual->expr)
7987 {
00f6de9c
TB
7988 stmtblock_t block;
7989 gfc_init_block (&block);
6de9cd9a 7990 gfc_init_se (&argse, NULL);
88f206a4
TK
7991 gfc_conv_expr_type (&argse, actual->expr,
7992 gfc_array_index_type);
00f6de9c
TB
7993 gfc_add_block_to_block (&block, &argse.pre);
7994 tree tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7995 argse.expr, gfc_index_one_node);
7996 size = gfc_tree_array_size (&block, arg1, e, tmp);
88f206a4 7997
88f206a4 7998 /* Unusually, for an intrinsic, size does not exclude
029b2d55 7999 an optional arg2, so we must test for it. */
88f206a4
TK
8000 if (actual->expr->expr_type == EXPR_VARIABLE
8001 && actual->expr->symtree->n.sym->attr.dummy
8002 && actual->expr->symtree->n.sym->attr.optional)
8003 {
00f6de9c
TB
8004 tree cond;
8005 stmtblock_t block2;
8006 gfc_init_block (&block2);
9c3e90e3
TB
8007 gfc_init_se (&argse, NULL);
8008 argse.want_pointer = 1;
8009 argse.data_not_needed = 1;
8010 gfc_conv_expr (&argse, actual->expr);
8011 gfc_add_block_to_block (&se->pre, &argse.pre);
00f6de9c
TB
8012 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8013 argse.expr, null_pointer_node);
8014 cond = gfc_evaluate_now (cond, &se->pre);
8015 /* 'block2' contains the arg2 absent case, 'block' the arg2 present
8016 case; size_var can be used in both blocks. */
55385f12 8017 tree size_var = gfc_create_var (TREE_TYPE (size), "size");
00f6de9c
TB
8018 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8019 TREE_TYPE (size_var), size_var, size);
8020 gfc_add_expr_to_block (&block, tmp);
55385f12
SL
8021 size = gfc_tree_array_size (&block2, arg1, e, NULL_TREE);
8022 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8023 TREE_TYPE (size_var), size_var, size);
8024 gfc_add_expr_to_block (&block2, tmp);
00f6de9c
TB
8025 tmp = build3_v (COND_EXPR, cond, gfc_finish_block (&block),
8026 gfc_finish_block (&block2));
8027 gfc_add_expr_to_block (&se->pre, tmp);
8028 size = size_var;
88f206a4
TK
8029 }
8030 else
00f6de9c 8031 gfc_add_block_to_block (&se->pre, &block);
6de9cd9a
DN
8032 }
8033 else
00f6de9c 8034 size = gfc_tree_array_size (&se->pre, arg1, e, NULL_TREE);
6de9cd9a 8035 type = gfc_typenode_for_spec (&expr->ts);
00f6de9c 8036 se->expr = convert (type, size);
6de9cd9a
DN
8037}
8038
8039
691da334
FXC
8040/* Helper function to compute the size of a character variable,
8041 excluding the terminating null characters. The result has
8042 gfc_array_index_type type. */
8043
2b3dc0db 8044tree
691da334
FXC
8045size_of_string_in_bytes (int kind, tree string_length)
8046{
8047 tree bytesize;
8048 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
029b2d55 8049
691da334
FXC
8050 bytesize = build_int_cst (gfc_array_index_type,
8051 gfc_character_kinds[i].bit_size / 8);
8052
433ce291
TB
8053 return fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8054 bytesize,
8055 fold_convert (gfc_array_index_type, string_length));
691da334
FXC
8056}
8057
8058
fd2157ce
TS
8059static void
8060gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
8061{
8062 gfc_expr *arg;
fd2157ce 8063 gfc_se argse;
fd2157ce 8064 tree source_bytes;
fd2157ce
TS
8065 tree tmp;
8066 tree lower;
8067 tree upper;
69c3654c 8068 tree byte_size;
7fb43006 8069 tree field;
fd2157ce
TS
8070 int n;
8071
fd2157ce 8072 gfc_init_se (&argse, NULL);
69c3654c 8073 arg = expr->value.function.actual->expr;
fd2157ce 8074
69c3654c
TB
8075 if (arg->rank || arg->ts.type == BT_ASSUMED)
8076 gfc_conv_expr_descriptor (&argse, arg);
8077 else
8078 gfc_conv_expr_reference (&argse, arg);
8079
8080 if (arg->ts.type == BT_ASSUMED)
8081 {
8082 /* This only works if an array descriptor has been passed; thus, extract
2c69df3b 8083 the size from the descriptor. */
69c3654c
TB
8084 gcc_assert (TYPE_PRECISION (gfc_array_index_type)
8085 == TYPE_PRECISION (size_type_node));
8086 tmp = arg->symtree->n.sym->backend_decl;
8087 tmp = DECL_LANG_SPECIFIC (tmp)
8088 && GFC_DECL_SAVED_DESCRIPTOR (tmp) != NULL_TREE
8089 ? GFC_DECL_SAVED_DESCRIPTOR (tmp) : tmp;
8090 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
8091 tmp = build_fold_indirect_ref_loc (input_location, tmp);
7fb43006
PT
8092
8093 tmp = gfc_conv_descriptor_dtype (tmp);
8094 field = gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
8095 GFC_DTYPE_ELEM_LEN);
8096 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
8097 tmp, field, NULL_TREE);
8098
69c3654c
TB
8099 byte_size = fold_convert (gfc_array_index_type, tmp);
8100 }
8101 else if (arg->ts.type == BT_CLASS)
8102 {
b0ae33ba
AV
8103 /* Conv_expr_descriptor returns a component_ref to _data component of the
8104 class object. The class object may be a non-pointer object, e.g.
8105 located on the stack, or a memory location pointed to, e.g. a
8106 parameter, i.e., an indirect_ref. */
a5c9b7c4
TB
8107 if (POINTER_TYPE_P (TREE_TYPE (argse.expr))
8108 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (argse.expr))))
8109 byte_size
8110 = gfc_class_vtab_size_get (build_fold_indirect_ref (argse.expr));
8111 else if (GFC_CLASS_TYPE_P (TREE_TYPE (argse.expr)))
8112 byte_size = gfc_class_vtab_size_get (argse.expr);
8113 else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (argse.expr))
8114 && TREE_CODE (argse.expr) == COMPONENT_REF)
34d9d749 8115 byte_size = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
fe14572b
SK
8116 else if (arg->rank > 0
8117 || (arg->rank == 0
8118 && arg->ref && arg->ref->type == REF_COMPONENT))
f3b0bb7a
AV
8119 /* The scalarizer added an additional temp. To get the class' vptr
8120 one has to look at the original backend_decl. */
8121 byte_size = gfc_class_vtab_size_get (
8122 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
69c3654c 8123 else
a5c9b7c4 8124 gcc_unreachable ();
69c3654c
TB
8125 }
8126 else
fd2157ce 8127 {
fd2157ce 8128 if (arg->ts.type == BT_CHARACTER)
69c3654c 8129 byte_size = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
fd2157ce 8130 else
69c3654c
TB
8131 {
8132 if (arg->rank == 0)
8133 byte_size = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
8134 argse.expr));
8135 else
8136 byte_size = gfc_get_element_type (TREE_TYPE (argse.expr));
8137 byte_size = fold_convert (gfc_array_index_type,
8138 size_in_bytes (byte_size));
8139 }
fd2157ce 8140 }
69c3654c
TB
8141
8142 if (arg->rank == 0)
8143 se->expr = byte_size;
fd2157ce
TS
8144 else
8145 {
8d82b242 8146 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
69c3654c 8147 gfc_add_modify (&argse.pre, source_bytes, byte_size);
fd2157ce 8148
69c3654c 8149 if (arg->rank == -1)
fd2157ce 8150 {
69c3654c
TB
8151 tree cond, loop_var, exit_label;
8152 stmtblock_t body;
8153
8154 tmp = fold_convert (gfc_array_index_type,
8155 gfc_conv_descriptor_rank (argse.expr));
8156 loop_var = gfc_create_var (gfc_array_index_type, "i");
8157 gfc_add_modify (&argse.pre, loop_var, gfc_index_zero_node);
8158 exit_label = gfc_build_label_decl (NULL_TREE);
8159
8160 /* Create loop:
8161 for (;;)
8162 {
8163 if (i >= rank)
8164 goto exit;
8165 source_bytes = source_bytes * array.dim[i].extent;
8166 i = i + 1;
8167 }
8168 exit: */
8169 gfc_start_block (&body);
63ee5404 8170 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
69c3654c
TB
8171 loop_var, tmp);
8172 tmp = build1_v (GOTO_EXPR, exit_label);
8173 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
8174 cond, tmp, build_empty_stmt (input_location));
8175 gfc_add_expr_to_block (&body, tmp);
8176
8177 lower = gfc_conv_descriptor_lbound_get (argse.expr, loop_var);
8178 upper = gfc_conv_descriptor_ubound_get (argse.expr, loop_var);
8179 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
433ce291
TB
8180 tmp = fold_build2_loc (input_location, MULT_EXPR,
8181 gfc_array_index_type, tmp, source_bytes);
69c3654c
TB
8182 gfc_add_modify (&body, source_bytes, tmp);
8183
8184 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8185 gfc_array_index_type, loop_var,
8186 gfc_index_one_node);
8187 gfc_add_modify_loc (input_location, &body, loop_var, tmp);
8188
8189 tmp = gfc_finish_block (&body);
8190
8191 tmp = fold_build1_loc (input_location, LOOP_EXPR, void_type_node,
8192 tmp);
8193 gfc_add_expr_to_block (&argse.pre, tmp);
8194
8195 tmp = build1_v (LABEL_EXPR, exit_label);
8196 gfc_add_expr_to_block (&argse.pre, tmp);
8197 }
8198 else
8199 {
8200 /* Obtain the size of the array in bytes. */
8201 for (n = 0; n < arg->rank; n++)
8202 {
8203 tree idx;
8204 idx = gfc_rank_cst[n];
8205 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
8206 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
8207 tmp = gfc_conv_array_extent_dim (lower, upper, NULL);
8208 tmp = fold_build2_loc (input_location, MULT_EXPR,
8209 gfc_array_index_type, tmp, source_bytes);
8210 gfc_add_modify (&argse.pre, source_bytes, tmp);
8211 }
fd2157ce 8212 }
8d82b242 8213 se->expr = source_bytes;
fd2157ce
TS
8214 }
8215
8216 gfc_add_block_to_block (&se->pre, &argse.pre);
fd2157ce
TS
8217}
8218
8219
048510c8
JW
8220static void
8221gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
8222{
8223 gfc_expr *arg;
cc6be82e 8224 gfc_se argse;
048510c8
JW
8225 tree type, result_type, tmp;
8226
8227 arg = expr->value.function.actual->expr;
029b2d55 8228
048510c8 8229 gfc_init_se (&argse, NULL);
048510c8
JW
8230 result_type = gfc_get_int_type (expr->ts.kind);
8231
2960a368 8232 if (arg->rank == 0)
048510c8
JW
8233 {
8234 if (arg->ts.type == BT_CLASS)
69c3654c
TB
8235 {
8236 gfc_add_vptr_component (arg);
8237 gfc_add_size_component (arg);
8238 gfc_conv_expr (&argse, arg);
8239 tmp = fold_convert (result_type, argse.expr);
8240 goto done;
8241 }
048510c8
JW
8242
8243 gfc_conv_expr_reference (&argse, arg);
029b2d55 8244 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
048510c8
JW
8245 argse.expr));
8246 }
8247 else
8248 {
8249 argse.want_pointer = 0;
2960a368 8250 gfc_conv_expr_descriptor (&argse, arg);
69c3654c
TB
8251 if (arg->ts.type == BT_CLASS)
8252 {
f3b0bb7a
AV
8253 if (arg->rank > 0)
8254 tmp = gfc_class_vtab_size_get (
8255 GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl));
8256 else
8257 tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0));
69c3654c
TB
8258 tmp = fold_convert (result_type, tmp);
8259 goto done;
8260 }
048510c8
JW
8261 type = gfc_get_element_type (TREE_TYPE (argse.expr));
8262 }
029b2d55 8263
048510c8
JW
8264 /* Obtain the argument's word length. */
8265 if (arg->ts.type == BT_CHARACTER)
8266 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
8267 else
029b2d55 8268 tmp = size_in_bytes (type);
cc6be82e 8269 tmp = fold_convert (result_type, tmp);
048510c8
JW
8270
8271done:
433ce291 8272 se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp,
cc6be82e 8273 build_int_cst (result_type, BITS_PER_UNIT));
048510c8
JW
8274 gfc_add_block_to_block (&se->pre, &argse.pre);
8275}
8276
8277
6de9cd9a
DN
8278/* Intrinsic string comparison functions. */
8279
fd2157ce 8280static void
8fa2df72 8281gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
6de9cd9a 8282{
55637e51 8283 tree args[4];
2dbc83d9 8284
55637e51 8285 gfc_conv_intrinsic_function_args (se, expr, args, 4);
6de9cd9a 8286
374929b2
FXC
8287 se->expr
8288 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
23b10420
JJ
8289 expr->value.function.actual->expr->ts.kind,
8290 op);
433ce291
TB
8291 se->expr = fold_build2_loc (input_location, op,
8292 gfc_typenode_for_spec (&expr->ts), se->expr,
8293 build_int_cst (TREE_TYPE (se->expr), 0));
6de9cd9a
DN
8294}
8295
8296/* Generate a call to the adjustl/adjustr library function. */
8297static void
8298gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
8299{
55637e51 8300 tree args[3];
6de9cd9a
DN
8301 tree len;
8302 tree type;
8303 tree var;
8304 tree tmp;
8305
55637e51
LM
8306 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
8307 len = args[1];
6de9cd9a 8308
55637e51 8309 type = TREE_TYPE (args[2]);
6de9cd9a 8310 var = gfc_conv_string_tmp (se, type, len);
55637e51 8311 args[0] = var;
6de9cd9a 8312
db3927fb
AH
8313 tmp = build_call_expr_loc (input_location,
8314 fndecl, 3, args[0], args[1], args[2]);
6de9cd9a
DN
8315 gfc_add_expr_to_block (&se->pre, tmp);
8316 se->expr = var;
8317 se->string_length = len;
8318}
8319
8320
c41fea4a
PT
8321/* Generate code for the TRANSFER intrinsic:
8322 For scalar results:
8323 DEST = TRANSFER (SOURCE, MOLD)
8324 where:
8325 typeof<DEST> = typeof<MOLD>
8326 and:
8327 MOLD is scalar.
8328
8329 For array results:
8330 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
8331 where:
8332 typeof<DEST> = typeof<MOLD>
8333 and:
8334 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
0c5a42a6 8335 sizeof (DEST(0) * SIZE). */
0c5a42a6 8336static void
c41fea4a 8337gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
0c5a42a6
PT
8338{
8339 tree tmp;
c41fea4a
PT
8340 tree tmpdecl;
8341 tree ptr;
0c5a42a6
PT
8342 tree extent;
8343 tree source;
1efd1a2f 8344 tree source_type;
0c5a42a6 8345 tree source_bytes;
1efd1a2f 8346 tree mold_type;
0c5a42a6
PT
8347 tree dest_word_len;
8348 tree size_words;
8349 tree size_bytes;
8350 tree upper;
8351 tree lower;
0c5a42a6 8352 tree stmt;
9a8013d1 8353 tree class_ref = NULL_TREE;
0c5a42a6
PT
8354 gfc_actual_arglist *arg;
8355 gfc_se argse;
6d63e468 8356 gfc_array_info *info;
0c5a42a6
PT
8357 stmtblock_t block;
8358 int n;
c41fea4a 8359 bool scalar_mold;
9a8013d1 8360 gfc_expr *source_expr, *mold_expr, *class_expr;
0c5a42a6 8361
c41fea4a
PT
8362 info = NULL;
8363 if (se->loop)
1838afec 8364 info = &se->ss->info->data.array;
0c5a42a6
PT
8365
8366 /* Convert SOURCE. The output from this stage is:-
8367 source_bytes = length of the source in bytes
8368 source = pointer to the source data. */
8369 arg = expr->value.function.actual;
fa1ed658 8370 source_expr = arg->expr;
c41fea4a
PT
8371
8372 /* Ensure double transfer through LOGICAL preserves all
8373 the needed bits. */
8374 if (arg->expr->expr_type == EXPR_FUNCTION
8375 && arg->expr->value.function.esym == NULL
8376 && arg->expr->value.function.isym != NULL
8377 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
8378 && arg->expr->ts.type == BT_LOGICAL
8379 && expr->ts.type != arg->expr->ts.type)
8380 arg->expr->value.function.name = "__transfer_in_transfer";
8381
0c5a42a6 8382 gfc_init_se (&argse, NULL);
0c5a42a6
PT
8383
8384 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
8385
8386 /* Obtain the pointer to source and the length of source in bytes. */
2960a368 8387 if (arg->expr->rank == 0)
0c5a42a6
PT
8388 {
8389 gfc_conv_expr_reference (&argse, arg->expr);
fa1ed658 8390 if (arg->expr->ts.type == BT_CLASS)
9a8013d1
PT
8391 {
8392 tmp = build_fold_indirect_ref_loc (input_location, argse.expr);
8393 if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
8394 source = gfc_class_data_get (tmp);
8395 else
8396 {
8397 /* Array elements are evaluated as a reference to the data.
8398 To obtain the vptr for the element size, the argument
8399 expression must be stripped to the class reference and
8400 re-evaluated. The pre and post blocks are not needed. */
8401 gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
8402 source = argse.expr;
8403 class_expr = gfc_find_and_cut_at_last_class_ref (arg->expr);
8404 gfc_init_se (&argse, NULL);
8405 gfc_conv_expr (&argse, class_expr);
8406 class_ref = argse.expr;
8407 }
8408 }
fa1ed658
JW
8409 else
8410 source = argse.expr;
1efd1a2f 8411
0c5a42a6 8412 /* Obtain the source word length. */
fa1ed658
JW
8413 switch (arg->expr->ts.type)
8414 {
8415 case BT_CHARACTER:
8416 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
8417 argse.string_length);
8418 break;
8419 case BT_CLASS:
9a8013d1
PT
8420 if (class_ref != NULL_TREE)
8421 tmp = gfc_class_vtab_size_get (class_ref);
8422 else
8423 tmp = gfc_class_vtab_size_get (argse.expr);
fa1ed658
JW
8424 break;
8425 default:
8426 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
8427 source));
8428 tmp = fold_convert (gfc_array_index_type,
8429 size_in_bytes (source_type));
8430 break;
8431 }
0c5a42a6
PT
8432 }
8433 else
8434 {
0c5a42a6 8435 argse.want_pointer = 0;
2960a368 8436 gfc_conv_expr_descriptor (&argse, arg->expr);
0c5a42a6 8437 source = gfc_conv_descriptor_data_get (argse.expr);
1efd1a2f 8438 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
0c5a42a6 8439
4b4a1012 8440 /* Repack the source if not simply contiguous. */
460263d0 8441 if (!gfc_is_simply_contiguous (arg->expr, false, true))
0c5a42a6 8442 {
628c189e 8443 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
bdfd2ff0 8444
73e42eef 8445 if (warn_array_temporaries)
48749dbc
MLI
8446 gfc_warning (OPT_Warray_temporaries,
8447 "Creating array temporary at %L", &expr->where);
bdfd2ff0 8448
db3927fb
AH
8449 source = build_call_expr_loc (input_location,
8450 gfor_fndecl_in_pack, 1, tmp);
0c5a42a6
PT
8451 source = gfc_evaluate_now (source, &argse.pre);
8452
8453 /* Free the temporary. */
8454 gfc_start_block (&block);
107051a5 8455 tmp = gfc_call_free (source);
0c5a42a6
PT
8456 gfc_add_expr_to_block (&block, tmp);
8457 stmt = gfc_finish_block (&block);
8458
8459 /* Clean up if it was repacked. */
8460 gfc_init_block (&block);
8461 tmp = gfc_conv_array_data (argse.expr);
63ee5404 8462 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
433ce291 8463 source, tmp);
c2255bc4
AH
8464 tmp = build3_v (COND_EXPR, tmp, stmt,
8465 build_empty_stmt (input_location));
0c5a42a6
PT
8466 gfc_add_expr_to_block (&block, tmp);
8467 gfc_add_block_to_block (&block, &se->post);
8468 gfc_init_block (&se->post);
8469 gfc_add_block_to_block (&se->post, &block);
8470 }
8471
8472 /* Obtain the source word length. */
1efd1a2f 8473 if (arg->expr->ts.type == BT_CHARACTER)
691da334
FXC
8474 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
8475 argse.string_length);
1efd1a2f
PT
8476 else
8477 tmp = fold_convert (gfc_array_index_type,
029b2d55 8478 size_in_bytes (source_type));
0c5a42a6
PT
8479
8480 /* Obtain the size of the array in bytes. */
8481 extent = gfc_create_var (gfc_array_index_type, NULL);
8482 for (n = 0; n < arg->expr->rank; n++)
8483 {
8484 tree idx;
8485 idx = gfc_rank_cst[n];
726a989a 8486 gfc_add_modify (&argse.pre, source_bytes, tmp);
568e8e1e
PT
8487 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
8488 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
433ce291
TB
8489 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8490 gfc_array_index_type, upper, lower);
726a989a 8491 gfc_add_modify (&argse.pre, extent, tmp);
433ce291
TB
8492 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8493 gfc_array_index_type, extent,
8494 gfc_index_one_node);
8495 tmp = fold_build2_loc (input_location, MULT_EXPR,
8496 gfc_array_index_type, tmp, source_bytes);
0c5a42a6
PT
8497 }
8498 }
8499
726a989a 8500 gfc_add_modify (&argse.pre, source_bytes, tmp);
0c5a42a6
PT
8501 gfc_add_block_to_block (&se->pre, &argse.pre);
8502 gfc_add_block_to_block (&se->post, &argse.post);
8503
1efd1a2f
PT
8504 /* Now convert MOLD. The outputs are:
8505 mold_type = the TREE type of MOLD
0c5a42a6
PT
8506 dest_word_len = destination word length in bytes. */
8507 arg = arg->next;
fa1ed658 8508 mold_expr = arg->expr;
0c5a42a6
PT
8509
8510 gfc_init_se (&argse, NULL);
0c5a42a6 8511
c41fea4a
PT
8512 scalar_mold = arg->expr->rank == 0;
8513
2960a368 8514 if (arg->expr->rank == 0)
0c5a42a6
PT
8515 {
8516 gfc_conv_expr_reference (&argse, arg->expr);
db3927fb 8517 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
fa1ed658 8518 argse.expr));
0c5a42a6
PT
8519 }
8520 else
8521 {
8522 gfc_init_se (&argse, NULL);
8523 argse.want_pointer = 0;
2960a368 8524 gfc_conv_expr_descriptor (&argse, arg->expr);
1efd1a2f 8525 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
0c5a42a6
PT
8526 }
8527
c41fea4a
PT
8528 gfc_add_block_to_block (&se->pre, &argse.pre);
8529 gfc_add_block_to_block (&se->post, &argse.post);
8530
27a4e072
JJ
8531 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
8532 {
8533 /* If this TRANSFER is nested in another TRANSFER, use a type
8534 that preserves all bits. */
8535 if (arg->expr->ts.type == BT_LOGICAL)
8536 mold_type = gfc_get_int_type (arg->expr->ts.kind);
8537 }
8538
fa1ed658
JW
8539 /* Obtain the destination word length. */
8540 switch (arg->expr->ts.type)
1efd1a2f 8541 {
fa1ed658 8542 case BT_CHARACTER:
691da334 8543 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
29401b7b
HA
8544 mold_type = gfc_get_character_type_len (arg->expr->ts.kind,
8545 argse.string_length);
fa1ed658
JW
8546 break;
8547 case BT_CLASS:
34d9d749 8548 tmp = gfc_class_vtab_size_get (argse.expr);
fa1ed658
JW
8549 break;
8550 default:
8551 tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type));
8552 break;
1efd1a2f 8553 }
0c5a42a6 8554 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
726a989a 8555 gfc_add_modify (&se->pre, dest_word_len, tmp);
0c5a42a6
PT
8556
8557 /* Finally convert SIZE, if it is present. */
8558 arg = arg->next;
8559 size_words = gfc_create_var (gfc_array_index_type, NULL);
8560
8561 if (arg->expr)
8562 {
8563 gfc_init_se (&argse, NULL);
8564 gfc_conv_expr_reference (&argse, arg->expr);
8565 tmp = convert (gfc_array_index_type,
db3927fb
AH
8566 build_fold_indirect_ref_loc (input_location,
8567 argse.expr));
0c5a42a6
PT
8568 gfc_add_block_to_block (&se->pre, &argse.pre);
8569 gfc_add_block_to_block (&se->post, &argse.post);
8570 }
8571 else
8572 tmp = NULL_TREE;
8573
c41fea4a
PT
8574 /* Separate array and scalar results. */
8575 if (scalar_mold && tmp == NULL_TREE)
8576 goto scalar_transfer;
8577
0c5a42a6
PT
8578 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
8579 if (tmp != NULL_TREE)
433ce291
TB
8580 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8581 tmp, dest_word_len);
0c5a42a6
PT
8582 else
8583 tmp = source_bytes;
8584
726a989a
RB
8585 gfc_add_modify (&se->pre, size_bytes, tmp);
8586 gfc_add_modify (&se->pre, size_words,
433ce291
TB
8587 fold_build2_loc (input_location, CEIL_DIV_EXPR,
8588 gfc_array_index_type,
8589 size_bytes, dest_word_len));
0c5a42a6
PT
8590
8591 /* Evaluate the bounds of the result. If the loop range exists, we have
8592 to check if it is too large. If so, we modify loop->to be consistent
8593 with min(size, size(source)). Otherwise, size is made consistent with
8594 the loop range, so that the right number of bytes is transferred.*/
8595 n = se->loop->order[0];
8596 if (se->loop->to[n] != NULL_TREE)
8597 {
433ce291
TB
8598 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8599 se->loop->to[n], se->loop->from[n]);
8600 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8601 tmp, gfc_index_one_node);
8602 tmp = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
fd2157ce 8603 tmp, size_words);
726a989a
RB
8604 gfc_add_modify (&se->pre, size_words, tmp);
8605 gfc_add_modify (&se->pre, size_bytes,
433ce291
TB
8606 fold_build2_loc (input_location, MULT_EXPR,
8607 gfc_array_index_type,
8608 size_words, dest_word_len));
8609 upper = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8610 size_words, se->loop->from[n]);
8611 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8612 upper, gfc_index_one_node);
0c5a42a6
PT
8613 }
8614 else
8615 {
433ce291
TB
8616 upper = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8617 size_words, gfc_index_one_node);
0c5a42a6
PT
8618 se->loop->from[n] = gfc_index_zero_node;
8619 }
8620
8621 se->loop->to[n] = upper;
8622
8623 /* Build a destination descriptor, using the pointer, source, as the
c41fea4a 8624 data field. */
41645793
MM
8625 gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
8626 NULL_TREE, false, true, false, &expr->where);
1efd1a2f
PT
8627
8628 /* Cast the pointer to the result. */
8629 tmp = gfc_conv_descriptor_data_get (info->descriptor);
8630 tmp = fold_convert (pvoid_type_node, tmp);
0c5a42a6 8631
014057c5 8632 /* Use memcpy to do the transfer. */
ee4b6b52
JJ
8633 tmp
8634 = build_call_expr_loc (input_location,
8635 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, tmp,
8636 fold_convert (pvoid_type_node, source),
8637 fold_convert (size_type_node,
8638 fold_build2_loc (input_location,
8639 MIN_EXPR,
8640 gfc_array_index_type,
8641 size_bytes,
8642 source_bytes)));
014057c5
PT
8643 gfc_add_expr_to_block (&se->pre, tmp);
8644
0c5a42a6
PT
8645 se->expr = info->descriptor;
8646 if (expr->ts.type == BT_CHARACTER)
29401b7b
HA
8647 {
8648 tmp = fold_convert (gfc_charlen_type_node,
8649 TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind)));
8650 se->string_length = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
8651 gfc_charlen_type_node,
8652 dest_word_len, tmp);
8653 }
0c5a42a6 8654
c41fea4a 8655 return;
0c5a42a6 8656
c41fea4a
PT
8657/* Deal with scalar results. */
8658scalar_transfer:
433ce291
TB
8659 extent = fold_build2_loc (input_location, MIN_EXPR, gfc_array_index_type,
8660 dest_word_len, source_bytes);
8661 extent = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
8662 extent, gfc_index_zero_node);
6de9cd9a 8663
c41fea4a
PT
8664 if (expr->ts.type == BT_CHARACTER)
8665 {
36849c21 8666 tree direct, indirect, free;
6de9cd9a 8667
c41fea4a
PT
8668 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
8669 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
8670 "transfer");
6de9cd9a 8671
c41fea4a
PT
8672 /* If source is longer than the destination, use a pointer to
8673 the source directly. */
8674 gfc_init_block (&block);
8675 gfc_add_modify (&block, tmpdecl, ptr);
8676 direct = gfc_finish_block (&block);
85d6cbd3 8677
c41fea4a
PT
8678 /* Otherwise, allocate a string with the length of the destination
8679 and copy the source into it. */
8680 gfc_init_block (&block);
8681 tmp = gfc_get_pchar_type (expr->ts.kind);
8682 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
8683 gfc_add_modify (&block, tmpdecl,
8684 fold_convert (TREE_TYPE (ptr), tmp));
db3927fb 8685 tmp = build_call_expr_loc (input_location,
e79983f4 8686 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
c41fea4a
PT
8687 fold_convert (pvoid_type_node, tmpdecl),
8688 fold_convert (pvoid_type_node, ptr),
ee4b6b52 8689 fold_convert (size_type_node, extent));
c41fea4a
PT
8690 gfc_add_expr_to_block (&block, tmp);
8691 indirect = gfc_finish_block (&block);
8692
8693 /* Wrap it up with the condition. */
63ee5404 8694 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
433ce291 8695 dest_word_len, source_bytes);
c41fea4a
PT
8696 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
8697 gfc_add_expr_to_block (&se->pre, tmp);
8698
36849c21
JW
8699 /* Free the temporary string, if necessary. */
8700 free = gfc_call_free (tmpdecl);
63ee5404 8701 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
36849c21
JW
8702 dest_word_len, source_bytes);
8703 tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
8704 gfc_add_expr_to_block (&se->post, tmp);
8705
c41fea4a 8706 se->expr = tmpdecl;
29401b7b
HA
8707 tmp = fold_convert (gfc_charlen_type_node,
8708 TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind)));
8709 se->string_length = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
8710 gfc_charlen_type_node,
8711 dest_word_len, tmp);
6de9cd9a
DN
8712 }
8713 else
8714 {
c41fea4a
PT
8715 tmpdecl = gfc_create_var (mold_type, "transfer");
8716
8717 ptr = convert (build_pointer_type (mold_type), source);
85d6cbd3 8718
fa1ed658
JW
8719 /* For CLASS results, allocate the needed memory first. */
8720 if (mold_expr->ts.type == BT_CLASS)
8721 {
8722 tree cdata;
8723 cdata = gfc_class_data_get (tmpdecl);
8724 tmp = gfc_call_malloc (&se->pre, TREE_TYPE (cdata), dest_word_len);
8725 gfc_add_modify (&se->pre, cdata, tmp);
8726 }
8727
85d6cbd3 8728 /* Use memcpy to do the transfer. */
fa1ed658
JW
8729 if (mold_expr->ts.type == BT_CLASS)
8730 tmp = gfc_class_data_get (tmpdecl);
8731 else
8732 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
8733
db3927fb 8734 tmp = build_call_expr_loc (input_location,
e79983f4 8735 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
5039610b
SL
8736 fold_convert (pvoid_type_node, tmp),
8737 fold_convert (pvoid_type_node, ptr),
ee4b6b52 8738 fold_convert (size_type_node, extent));
85d6cbd3
AP
8739 gfc_add_expr_to_block (&se->pre, tmp);
8740
fa1ed658
JW
8741 /* For CLASS results, set the _vptr. */
8742 if (mold_expr->ts.type == BT_CLASS)
8743 {
8744 tree vptr;
8745 gfc_symbol *vtab;
8746 vptr = gfc_class_vptr_get (tmpdecl);
8747 vtab = gfc_find_derived_vtab (source_expr->ts.u.derived);
8748 gcc_assert (vtab);
8749 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
8750 gfc_add_modify (&se->pre, vptr, fold_convert (TREE_TYPE (vptr), tmp));
8751 }
8752
85d6cbd3 8753 se->expr = tmpdecl;
6de9cd9a
DN
8754 }
8755}
8756
8757
ba85c8c3
AV
8758/* Generate a call to caf_is_present. */
8759
8760static tree
8761trans_caf_is_present (gfc_se *se, gfc_expr *expr)
8762{
8763 tree caf_reference, caf_decl, token, image_index;
8764
8765 /* Compile the reference chain. */
8766 caf_reference = conv_expr_ref_to_caf_ref (&se->pre, expr);
8767 gcc_assert (caf_reference != NULL_TREE);
8768
8769 caf_decl = gfc_get_tree_for_caf_expr (expr);
8770 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
8771 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
8772 image_index = gfc_caf_get_image_index (&se->pre, expr, caf_decl);
8773 gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
8774 expr);
8775
8776 return build_call_expr_loc (input_location, gfor_fndecl_caf_is_present,
8777 3, token, image_index, caf_reference);
8778}
8779
8780
8781/* Test whether this ref-chain refs this image only. */
8782
8783static bool
8784caf_this_image_ref (gfc_ref *ref)
8785{
8786 for ( ; ref; ref = ref->next)
8787 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
8788 return ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE;
8789
8790 return false;
8791}
8792
8793
6de9cd9a
DN
8794/* Generate code for the ALLOCATED intrinsic.
8795 Generate inline code that directly check the address of the argument. */
8796
8797static void
8798gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
8799{
6de9cd9a 8800 gfc_se arg1se;
6de9cd9a 8801 tree tmp;
1b07d9dc
TB
8802 bool coindexed_caf_comp = false;
8803 gfc_expr *e = expr->value.function.actual->expr;
6de9cd9a
DN
8804
8805 gfc_init_se (&arg1se, NULL);
1b07d9dc 8806 if (e->ts.type == BT_CLASS)
c49ea23d
PT
8807 {
8808 /* Make sure that class array expressions have both a _data
8809 component reference and an array reference.... */
1b07d9dc
TB
8810 if (CLASS_DATA (e)->attr.dimension)
8811 gfc_add_class_array_ref (e);
c49ea23d
PT
8812 /* .... whilst scalars only need the _data component. */
8813 else
1b07d9dc 8814 gfc_add_data_component (e);
c49ea23d
PT
8815 }
8816
1b07d9dc 8817 /* When 'e' references an allocatable component in a coarray, then call
ba85c8c3 8818 the caf-library function caf_is_present (). */
1b07d9dc
TB
8819 if (flag_coarray == GFC_FCOARRAY_LIB && e->expr_type == EXPR_FUNCTION
8820 && e->value.function.isym
8821 && e->value.function.isym->id == GFC_ISYM_CAF_GET)
8822 {
8823 e = e->value.function.actual->expr;
8824 if (gfc_expr_attr (e).codimension)
8825 {
8826 /* Last partref is the coindexed coarray. As coarrays are collectively
8827 (de)allocated, the allocation status must be the same as the one of
8828 the local allocation. Convert to local access. */
8829 for (gfc_ref *ref = e->ref; ref; ref = ref->next)
8830 if (ref->type == REF_ARRAY && ref->u.ar.codimen)
8831 {
8832 for (int i = ref->u.ar.dimen;
8833 i < ref->u.ar.dimen + ref->u.ar.codimen; ++i)
8834 ref->u.ar.dimen_type[i] = DIMEN_THIS_IMAGE;
8835 break;
8836 }
8837 }
8838 else if (!caf_this_image_ref (e->ref))
8839 coindexed_caf_comp = true;
8840 }
8841 if (coindexed_caf_comp)
8842 tmp = trans_caf_is_present (se, e);
2fbd4117
JW
8843 else
8844 {
1b07d9dc 8845 if (e->rank == 0)
ba85c8c3
AV
8846 {
8847 /* Allocatable scalar. */
8848 arg1se.want_pointer = 1;
1b07d9dc 8849 gfc_conv_expr (&arg1se, e);
ba85c8c3
AV
8850 tmp = arg1se.expr;
8851 }
8852 else
8853 {
8854 /* Allocatable array. */
8855 arg1se.descriptor_only = 1;
1b07d9dc 8856 gfc_conv_expr_descriptor (&arg1se, e);
ba85c8c3
AV
8857 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
8858 }
2fbd4117 8859
63ee5404 8860 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
ba85c8c3
AV
8861 fold_convert (TREE_TYPE (tmp), null_pointer_node));
8862 }
8fba26f4
PT
8863
8864 /* Components of pointer array references sometimes come back with a pre block. */
8865 if (arg1se.pre.head)
8866 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8867
6de9cd9a
DN
8868 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
8869}
8870
8871
8872/* Generate code for the ASSOCIATED intrinsic.
8873 If both POINTER and TARGET are arrays, generate a call to library function
8874 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
8875 In other cases, generate inline code that directly compare the address of
8876 POINTER with the address of TARGET. */
8877
8878static void
8879gfc_conv_associated (gfc_se *se, gfc_expr *expr)
8880{
8881 gfc_actual_arglist *arg1;
8882 gfc_actual_arglist *arg2;
8883 gfc_se arg1se;
8884 gfc_se arg2se;
8885 tree tmp2;
8886 tree tmp;
fe2771b2 8887 tree nonzero_arraylen = NULL_TREE;
2960a368
TB
8888 gfc_ss *ss;
8889 bool scalar;
6de9cd9a
DN
8890
8891 gfc_init_se (&arg1se, NULL);
8892 gfc_init_se (&arg2se, NULL);
8893 arg1 = expr->value.function.actual;
8894 arg2 = arg1->next;
2960a368
TB
8895
8896 /* Check whether the expression is a scalar or not; we cannot use
8897 arg1->expr->rank as it can be nonzero for proc pointers. */
8898 ss = gfc_walk_expr (arg1->expr);
8899 scalar = ss == gfc_ss_terminator;
8900 if (!scalar)
8901 gfc_free_ss_chain (ss);
6de9cd9a
DN
8902
8903 if (!arg2->expr)
8904 {
8905 /* No optional target. */
2960a368 8906 if (scalar)
6de9cd9a 8907 {
4dc86aa8
TB
8908 /* A pointer to a scalar. */
8909 arg1se.want_pointer = 1;
8910 gfc_conv_expr (&arg1se, arg1->expr);
8911 if (arg1->expr->symtree->n.sym->attr.proc_pointer
8912 && arg1->expr->symtree->n.sym->attr.dummy)
8913 arg1se.expr = build_fold_indirect_ref_loc (input_location,
8914 arg1se.expr);
029b2d55
PT
8915 if (arg1->expr->ts.type == BT_CLASS)
8916 {
fca04db3 8917 tmp2 = gfc_class_data_get (arg1se.expr);
029b2d55
PT
8918 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
8919 tmp2 = gfc_conv_descriptor_data_get (tmp2);
8920 }
fca04db3
JW
8921 else
8922 tmp2 = arg1se.expr;
6de9cd9a
DN
8923 }
8924 else
8925 {
8926 /* A pointer to an array. */
2960a368 8927 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
4c73896d 8928 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
6de9cd9a 8929 }
98efaf34
FXC
8930 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8931 gfc_add_block_to_block (&se->post, &arg1se.post);
63ee5404 8932 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp2,
433ce291 8933 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
6de9cd9a
DN
8934 se->expr = tmp;
8935 }
8936 else
8937 {
8938 /* An optional target. */
bf8ee9e4
PT
8939 if (arg2->expr->ts.type == BT_CLASS
8940 && arg2->expr->expr_type != EXPR_FUNCTION)
b04533af 8941 gfc_add_data_component (arg2->expr);
699fa7aa 8942
2960a368 8943 if (scalar)
6de9cd9a 8944 {
4dc86aa8 8945 /* A pointer to a scalar. */
4dc86aa8
TB
8946 arg1se.want_pointer = 1;
8947 gfc_conv_expr (&arg1se, arg1->expr);
8948 if (arg1->expr->symtree->n.sym->attr.proc_pointer
8949 && arg1->expr->symtree->n.sym->attr.dummy)
8950 arg1se.expr = build_fold_indirect_ref_loc (input_location,
8951 arg1se.expr);
fca04db3
JW
8952 if (arg1->expr->ts.type == BT_CLASS)
8953 arg1se.expr = gfc_class_data_get (arg1se.expr);
4dc86aa8
TB
8954
8955 arg2se.want_pointer = 1;
8956 gfc_conv_expr (&arg2se, arg2->expr);
8957 if (arg2->expr->symtree->n.sym->attr.proc_pointer
8958 && arg2->expr->symtree->n.sym->attr.dummy)
8959 arg2se.expr = build_fold_indirect_ref_loc (input_location,
8960 arg2se.expr);
bf8ee9e4
PT
8961 if (arg2->expr->ts.type == BT_CLASS)
8962 {
8963 arg2se.expr = gfc_evaluate_now (arg2se.expr, &arg2se.pre);
8964 arg2se.expr = gfc_class_data_get (arg2se.expr);
8965 }
98efaf34
FXC
8966 gfc_add_block_to_block (&se->pre, &arg1se.pre);
8967 gfc_add_block_to_block (&se->post, &arg1se.post);
28ed8364
PT
8968 gfc_add_block_to_block (&se->pre, &arg2se.pre);
8969 gfc_add_block_to_block (&se->post, &arg2se.post);
63ee5404 8970 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
433ce291 8971 arg1se.expr, arg2se.expr);
63ee5404 8972 tmp2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
433ce291
TB
8973 arg1se.expr, null_pointer_node);
8974 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 8975 logical_type_node, tmp, tmp2);
6de9cd9a
DN
8976 }
8977 else
8978 {
699fa7aa
PT
8979 /* An array pointer of zero length is not associated if target is
8980 present. */
8981 arg1se.descriptor_only = 1;
8982 gfc_conv_expr_lhs (&arg1se, arg1->expr);
c62c6622
TB
8983 if (arg1->expr->rank == -1)
8984 {
17aa6ab6 8985 tmp = gfc_conv_descriptor_rank (arg1se.expr);
c62c6622 8986 tmp = fold_build2_loc (input_location, MINUS_EXPR,
fe2771b2
TB
8987 TREE_TYPE (tmp), tmp,
8988 build_int_cst (TREE_TYPE (tmp), 1));
c62c6622
TB
8989 }
8990 else
8991 tmp = gfc_rank_cst[arg1->expr->rank - 1];
8992 tmp = gfc_conv_descriptor_stride_get (arg1se.expr, tmp);
fe2771b2
TB
8993 if (arg2->expr->rank != 0)
8994 nonzero_arraylen = fold_build2_loc (input_location, NE_EXPR,
8995 logical_type_node, tmp,
8996 build_int_cst (TREE_TYPE (tmp), 0));
699fa7aa 8997
f82f425b
PT
8998 /* A pointer to an array, call library function _gfor_associated. */
8999 arg1se.want_pointer = 1;
9000 gfc_conv_expr_descriptor (&arg1se, arg1->expr);
9001 gfc_add_block_to_block (&se->pre, &arg1se.pre);
9002 gfc_add_block_to_block (&se->post, &arg1se.post);
699fa7aa 9003
f82f425b 9004 arg2se.want_pointer = 1;
d514626e 9005 arg2se.force_no_tmp = 1;
fe2771b2
TB
9006 if (arg2->expr->rank != 0)
9007 gfc_conv_expr_descriptor (&arg2se, arg2->expr);
9008 else
9009 {
9010 gfc_conv_expr (&arg2se, arg2->expr);
9011 arg2se.expr
9012 = gfc_conv_scalar_to_descriptor (&arg2se, arg2se.expr,
9013 gfc_expr_attr (arg2->expr));
9014 arg2se.expr = gfc_build_addr_expr (NULL_TREE, arg2se.expr);
9015 }
f82f425b
PT
9016 gfc_add_block_to_block (&se->pre, &arg2se.pre);
9017 gfc_add_block_to_block (&se->post, &arg2se.post);
9018 se->expr = build_call_expr_loc (input_location,
db3927fb 9019 gfor_fndecl_associated, 2,
8a09ef91 9020 arg1se.expr, arg2se.expr);
63ee5404 9021 se->expr = convert (logical_type_node, se->expr);
fe2771b2
TB
9022 if (arg2->expr->rank != 0)
9023 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9024 logical_type_node, se->expr,
9025 nonzero_arraylen);
6de9cd9a 9026 }
699fa7aa
PT
9027
9028 /* If target is present zero character length pointers cannot
9029 be associated. */
7067f8c8
PT
9030 if (arg1->expr->ts.type == BT_CHARACTER)
9031 {
9032 tmp = arg1se.string_length;
9033 tmp = fold_build2_loc (input_location, NE_EXPR,
9034 logical_type_node, tmp,
9035 build_zero_cst (TREE_TYPE (tmp)));
9036 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9037 logical_type_node, se->expr, tmp);
9038 }
699fa7aa
PT
9039 }
9040
6de9cd9a
DN
9041 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9042}
9043
9044
cf2b3c22
TB
9045/* Generate code for the SAME_TYPE_AS intrinsic.
9046 Generate inline code that directly checks the vindices. */
9047
9048static void
9049gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
9050{
9051 gfc_expr *a, *b;
9052 gfc_se se1, se2;
9053 tree tmp;
8b704316 9054 tree conda = NULL_TREE, condb = NULL_TREE;
cf2b3c22
TB
9055
9056 gfc_init_se (&se1, NULL);
9057 gfc_init_se (&se2, NULL);
9058
9059 a = expr->value.function.actual->expr;
9060 b = expr->value.function.actual->next->expr;
9061
643e8f4e
TB
9062 bool unlimited_poly_a = UNLIMITED_POLY (a);
9063 bool unlimited_poly_b = UNLIMITED_POLY (b);
9064 if (unlimited_poly_a)
8b704316 9065 {
643e8f4e
TB
9066 se1.want_pointer = 1;
9067 gfc_add_vptr_component (a);
8b704316 9068 }
643e8f4e 9069 else if (a->ts.type == BT_CLASS)
7c1dab0d 9070 {
b04533af
JW
9071 gfc_add_vptr_component (a);
9072 gfc_add_hash_component (a);
7c1dab0d 9073 }
cf2b3c22 9074 else if (a->ts.type == BT_DERIVED)
b7e75771
JD
9075 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
9076 a->ts.u.derived->hash_value);
cf2b3c22 9077
643e8f4e
TB
9078 if (unlimited_poly_b)
9079 {
9080 se2.want_pointer = 1;
9081 gfc_add_vptr_component (b);
9082 }
9083 else if (b->ts.type == BT_CLASS)
7c1dab0d 9084 {
b04533af
JW
9085 gfc_add_vptr_component (b);
9086 gfc_add_hash_component (b);
7c1dab0d 9087 }
cf2b3c22 9088 else if (b->ts.type == BT_DERIVED)
b7e75771
JD
9089 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
9090 b->ts.u.derived->hash_value);
cf2b3c22
TB
9091
9092 gfc_conv_expr (&se1, a);
9093 gfc_conv_expr (&se2, b);
9094
643e8f4e
TB
9095 if (unlimited_poly_a)
9096 {
9097 conda = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9098 se1.expr,
9099 build_int_cst (TREE_TYPE (se1.expr), 0));
9100 se1.expr = gfc_vptr_hash_get (se1.expr);
9101 }
9102
9103 if (unlimited_poly_b)
9104 {
9105 condb = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9106 se2.expr,
9107 build_int_cst (TREE_TYPE (se2.expr), 0));
9108 se2.expr = gfc_vptr_hash_get (se2.expr);
9109 }
9110
8b704316 9111 tmp = fold_build2_loc (input_location, EQ_EXPR,
63ee5404 9112 logical_type_node, se1.expr,
8b704316
PT
9113 fold_convert (TREE_TYPE (se1.expr), se2.expr));
9114
9115 if (conda)
9116 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
63ee5404 9117 logical_type_node, conda, tmp);
8b704316
PT
9118
9119 if (condb)
9120 tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
63ee5404 9121 logical_type_node, condb, tmp);
8b704316 9122
cf2b3c22
TB
9123 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
9124}
9125
9126
a39fafac
FXC
9127/* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
9128
9129static void
9130gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
9131{
9132 tree args[2];
9133
9134 gfc_conv_intrinsic_function_args (se, expr, args, 2);
db3927fb
AH
9135 se->expr = build_call_expr_loc (input_location,
9136 gfor_fndecl_sc_kind, 2, args[0], args[1]);
a39fafac
FXC
9137 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9138}
9139
9140
6de9cd9a
DN
9141/* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
9142
9143static void
26ef8a2c 9144gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
6de9cd9a 9145{
26ef8a2c 9146 tree arg, type;
6de9cd9a 9147
55637e51 9148 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
26ef8a2c
SK
9149
9150 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
029b2d55 9151 type = gfc_get_int_type (4);
628c189e 9152 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
26ef8a2c
SK
9153
9154 /* Convert it to the required type. */
9155 type = gfc_typenode_for_spec (&expr->ts);
db3927fb
AH
9156 se->expr = build_call_expr_loc (input_location,
9157 gfor_fndecl_si_kind, 1, arg);
26ef8a2c 9158 se->expr = fold_convert (type, se->expr);
6de9cd9a
DN
9159}
9160
26ef8a2c 9161
e0516b05 9162/* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
6de9cd9a
DN
9163
9164static void
26ef8a2c 9165gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
6de9cd9a
DN
9166{
9167 gfc_actual_arglist *actual;
3bb06db4 9168 tree type;
6de9cd9a 9169 gfc_se argse;
9771b263 9170 vec<tree, va_gc> *args = NULL;
6de9cd9a 9171
6de9cd9a
DN
9172 for (actual = expr->value.function.actual; actual; actual = actual->next)
9173 {
9174 gfc_init_se (&argse, se);
9175
9176 /* Pass a NULL pointer for an absent arg. */
9177 if (actual->expr == NULL)
9178 argse.expr = null_pointer_node;
9179 else
26ef8a2c
SK
9180 {
9181 gfc_typespec ts;
44000dbb
JD
9182 gfc_clear_ts (&ts);
9183
26ef8a2c
SK
9184 if (actual->expr->ts.kind != gfc_c_int_kind)
9185 {
9186 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
9187 ts.type = BT_INTEGER;
9188 ts.kind = gfc_c_int_kind;
9189 gfc_convert_type (actual->expr, &ts, 2);
9190 }
9191 gfc_conv_expr_reference (&argse, actual->expr);
029b2d55 9192 }
6de9cd9a
DN
9193
9194 gfc_add_block_to_block (&se->pre, &argse.pre);
9195 gfc_add_block_to_block (&se->post, &argse.post);
9771b263 9196 vec_safe_push (args, argse.expr);
6de9cd9a 9197 }
26ef8a2c
SK
9198
9199 /* Convert it to the required type. */
9200 type = gfc_typenode_for_spec (&expr->ts);
3bb06db4
NF
9201 se->expr = build_call_expr_loc_vec (input_location,
9202 gfor_fndecl_sr_kind, args);
26ef8a2c 9203 se->expr = fold_convert (type, se->expr);
6de9cd9a
DN
9204}
9205
9206
9207/* Generate code for TRIM (A) intrinsic function. */
9208
9209static void
9210gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
9211{
9212 tree var;
9213 tree len;
9214 tree addr;
9215 tree tmp;
6de9cd9a 9216 tree cond;
55637e51 9217 tree fndecl;
374929b2 9218 tree function;
55637e51
LM
9219 tree *args;
9220 unsigned int num_args;
6de9cd9a 9221
55637e51 9222 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1145e690 9223 args = XALLOCAVEC (tree, num_args);
6de9cd9a 9224
691da334 9225 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
6de9cd9a 9226 addr = gfc_build_addr_expr (ppvoid_type_node, var);
6cd8d93a 9227 len = gfc_create_var (gfc_charlen_type_node, "len");
6de9cd9a 9228
55637e51 9229 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
628c189e 9230 args[0] = gfc_build_addr_expr (NULL_TREE, len);
55637e51 9231 args[1] = addr;
b36cd00b 9232
374929b2
FXC
9233 if (expr->ts.kind == 1)
9234 function = gfor_fndecl_string_trim;
9235 else if (expr->ts.kind == 4)
9236 function = gfor_fndecl_string_trim_char4;
9237 else
9238 gcc_unreachable ();
9239
aa00059c 9240 fndecl = build_addr (function);
db3927fb
AH
9241 tmp = build_call_array_loc (input_location,
9242 TREE_TYPE (TREE_TYPE (function)), fndecl,
374929b2 9243 num_args, args);
6de9cd9a
DN
9244 gfc_add_expr_to_block (&se->pre, tmp);
9245
9246 /* Free the temporary afterwards, if necessary. */
63ee5404 9247 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
433ce291 9248 len, build_int_cst (TREE_TYPE (len), 0));
1529b8d9 9249 tmp = gfc_call_free (var);
c2255bc4 9250 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
6de9cd9a
DN
9251 gfc_add_expr_to_block (&se->post, tmp);
9252
9253 se->expr = var;
9254 se->string_length = len;
9255}
9256
9257
9258/* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
9259
9260static void
9261gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
9262{
55637e51 9263 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
f1412ca5 9264 tree type, cond, tmp, count, exit_label, n, max, largest;
d393bbd7 9265 tree size;
f1412ca5
FXC
9266 stmtblock_t block, body;
9267 int i;
6de9cd9a 9268
691da334 9269 /* We store in charsize the size of a character. */
d393bbd7 9270 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
f622221a 9271 size = build_int_cst (sizetype, gfc_character_kinds[i].bit_size / 8);
d393bbd7 9272
f1412ca5 9273 /* Get the arguments. */
55637e51 9274 gfc_conv_intrinsic_function_args (se, expr, args, 3);
f622221a 9275 slen = fold_convert (sizetype, gfc_evaluate_now (args[0], &se->pre));
55637e51
LM
9276 src = args[1];
9277 ncopies = gfc_evaluate_now (args[2], &se->pre);
f1412ca5
FXC
9278 ncopies_type = TREE_TYPE (ncopies);
9279
9280 /* Check that NCOPIES is not negative. */
63ee5404 9281 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node, ncopies,
433ce291 9282 build_int_cst (ncopies_type, 0));
0d52899f 9283 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
c8fe94c7 9284 "Argument NCOPIES of REPEAT intrinsic is negative "
be94c034 9285 "(its value is %ld)",
c8fe94c7 9286 fold_convert (long_integer_type_node, ncopies));
a14fb6fa 9287
f1412ca5
FXC
9288 /* If the source length is zero, any non negative value of NCOPIES
9289 is valid, and nothing happens. */
9290 n = gfc_create_var (ncopies_type, "ncopies");
63ee5404 9291 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
f622221a 9292 size_zero_node);
433ce291
TB
9293 tmp = fold_build3_loc (input_location, COND_EXPR, ncopies_type, cond,
9294 build_int_cst (ncopies_type, 0), ncopies);
726a989a 9295 gfc_add_modify (&se->pre, n, tmp);
f1412ca5
FXC
9296 ncopies = n;
9297
9298 /* Check that ncopies is not too large: ncopies should be less than
9299 (or equal to) MAX / slen, where MAX is the maximal integer of
9300 the gfc_charlen_type_node type. If slen == 0, we need a special
9301 case to avoid the division by zero. */
f622221a
JB
9302 max = fold_build2_loc (input_location, TRUNC_DIV_EXPR, sizetype,
9303 fold_convert (sizetype,
9304 TYPE_MAX_VALUE (gfc_charlen_type_node)),
9305 slen);
9306 largest = TYPE_PRECISION (sizetype) > TYPE_PRECISION (ncopies_type)
9307 ? sizetype : ncopies_type;
63ee5404 9308 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
433ce291
TB
9309 fold_convert (largest, ncopies),
9310 fold_convert (largest, max));
63ee5404 9311 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, slen,
f622221a 9312 size_zero_node);
63ee5404
JB
9313 cond = fold_build3_loc (input_location, COND_EXPR, logical_type_node, tmp,
9314 logical_false_node, cond);
0d52899f 9315 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
c8fe94c7 9316 "Argument NCOPIES of REPEAT intrinsic is too large");
f1412ca5 9317
a14fb6fa 9318 /* Compute the destination length. */
433ce291
TB
9319 dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_charlen_type_node,
9320 fold_convert (gfc_charlen_type_node, slen),
9321 fold_convert (gfc_charlen_type_node, ncopies));
bc21d315 9322 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
f1412ca5
FXC
9323 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
9324
9325 /* Generate the code to do the repeat operation:
9326 for (i = 0; i < ncopies; i++)
d393bbd7 9327 memmove (dest + (i * slen * size), src, slen*size); */
f1412ca5 9328 gfc_start_block (&block);
f622221a
JB
9329 count = gfc_create_var (sizetype, "count");
9330 gfc_add_modify (&block, count, size_zero_node);
f1412ca5
FXC
9331 exit_label = gfc_build_label_decl (NULL_TREE);
9332
9333 /* Start the loop body. */
9334 gfc_start_block (&body);
6de9cd9a 9335
f1412ca5 9336 /* Exit the loop if count >= ncopies. */
63ee5404 9337 cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, count,
f622221a 9338 fold_convert (sizetype, ncopies));
f1412ca5
FXC
9339 tmp = build1_v (GOTO_EXPR, exit_label);
9340 TREE_USED (exit_label) = 1;
433ce291
TB
9341 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
9342 build_empty_stmt (input_location));
f1412ca5
FXC
9343 gfc_add_expr_to_block (&body, tmp);
9344
d393bbd7 9345 /* Call memmove (dest + (i*slen*size), src, slen*size). */
f622221a
JB
9346 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, slen,
9347 count);
9348 tmp = fold_build2_loc (input_location, MULT_EXPR, sizetype, tmp,
9349 size);
5d49b6a7
RG
9350 tmp = fold_build_pointer_plus_loc (input_location,
9351 fold_convert (pvoid_type_node, dest), tmp);
db3927fb 9352 tmp = build_call_expr_loc (input_location,
e79983f4
MM
9353 builtin_decl_explicit (BUILT_IN_MEMMOVE),
9354 3, tmp, src,
433ce291 9355 fold_build2_loc (input_location, MULT_EXPR,
f622221a 9356 size_type_node, slen, size));
f1412ca5
FXC
9357 gfc_add_expr_to_block (&body, tmp);
9358
9359 /* Increment count. */
f622221a
JB
9360 tmp = fold_build2_loc (input_location, PLUS_EXPR, sizetype,
9361 count, size_one_node);
726a989a 9362 gfc_add_modify (&body, count, tmp);
f1412ca5
FXC
9363
9364 /* Build the loop. */
9365 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
9366 gfc_add_expr_to_block (&block, tmp);
9367
9368 /* Add the exit label. */
9369 tmp = build1_v (LABEL_EXPR, exit_label);
9370 gfc_add_expr_to_block (&block, tmp);
9371
9372 /* Finish the block. */
9373 tmp = gfc_finish_block (&block);
6de9cd9a
DN
9374 gfc_add_expr_to_block (&se->pre, tmp);
9375
f1412ca5
FXC
9376 /* Set the result value. */
9377 se->expr = dest;
9378 se->string_length = dlen;
6de9cd9a
DN
9379}
9380
9381
d436d3de 9382/* Generate code for the IARGC intrinsic. */
b41b2534
JB
9383
9384static void
d436d3de 9385gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
b41b2534
JB
9386{
9387 tree tmp;
9388 tree fndecl;
9389 tree type;
9390
9391 /* Call the library function. This always returns an INTEGER(4). */
9392 fndecl = gfor_fndecl_iargc;
db3927fb
AH
9393 tmp = build_call_expr_loc (input_location,
9394 fndecl, 0);
b41b2534
JB
9395
9396 /* Convert it to the required type. */
9397 type = gfc_typenode_for_spec (&expr->ts);
9398 tmp = fold_convert (type, tmp);
9399
b41b2534
JB
9400 se->expr = tmp;
9401}
9402
83d890b9 9403
17164de4
SK
9404/* Generate code for the KILL intrinsic. */
9405
9406static void
9407conv_intrinsic_kill (gfc_se *se, gfc_expr *expr)
9408{
9409 tree *args;
9410 tree int4_type_node = gfc_get_int_type (4);
9411 tree pid;
9412 tree sig;
9413 tree tmp;
9414 unsigned int num_args;
9415
9416 num_args = gfc_intrinsic_argument_list_length (expr);
9417 args = XALLOCAVEC (tree, num_args);
9418 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
9419
9420 /* Convert PID to a INTEGER(4) entity. */
9421 pid = convert (int4_type_node, args[0]);
9422
9423 /* Convert SIG to a INTEGER(4) entity. */
9424 sig = convert (int4_type_node, args[1]);
9425
9426 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill, 2, pid, sig);
9427
9428 se->expr = fold_convert (TREE_TYPE (args[0]), tmp);
9429}
9430
9431
9432static tree
9433conv_intrinsic_kill_sub (gfc_code *code)
9434{
9435 stmtblock_t block;
9436 gfc_se se, se_stat;
9437 tree int4_type_node = gfc_get_int_type (4);
9438 tree pid;
9439 tree sig;
9440 tree statp;
9441 tree tmp;
9442
9443 /* Make the function call. */
9444 gfc_init_block (&block);
9445 gfc_init_se (&se, NULL);
9446
9447 /* Convert PID to a INTEGER(4) entity. */
9448 gfc_conv_expr (&se, code->ext.actual->expr);
9449 gfc_add_block_to_block (&block, &se.pre);
9450 pid = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
9451 gfc_add_block_to_block (&block, &se.post);
9452
9453 /* Convert SIG to a INTEGER(4) entity. */
9454 gfc_conv_expr (&se, code->ext.actual->next->expr);
9455 gfc_add_block_to_block (&block, &se.pre);
9456 sig = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
9457 gfc_add_block_to_block (&block, &se.post);
9458
9459 /* Deal with an optional STATUS. */
9460 if (code->ext.actual->next->next->expr)
9461 {
9462 gfc_init_se (&se_stat, NULL);
9463 gfc_conv_expr (&se_stat, code->ext.actual->next->next->expr);
9464 statp = gfc_create_var (gfc_get_int_type (4), "_statp");
9465 }
9466 else
9467 statp = NULL_TREE;
9468
9469 tmp = build_call_expr_loc (input_location, gfor_fndecl_kill_sub, 3, pid, sig,
9470 statp ? gfc_build_addr_expr (NULL_TREE, statp) : null_pointer_node);
9471
9472 gfc_add_expr_to_block (&block, tmp);
9473
9474 if (statp && statp != se_stat.expr)
9475 gfc_add_modify (&block, se_stat.expr,
9476 fold_convert (TREE_TYPE (se_stat.expr), statp));
9477
9478 return gfc_finish_block (&block);
9479}
9480
9481
9482
83d890b9
AL
9483/* The loc intrinsic returns the address of its argument as
9484 gfc_index_integer_kind integer. */
9485
9486static void
0f8bc3e1 9487gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
83d890b9
AL
9488{
9489 tree temp_var;
9490 gfc_expr *arg_expr;
83d890b9
AL
9491
9492 gcc_assert (!se->ss);
9493
9494 arg_expr = expr->value.function.actual->expr;
2960a368 9495 if (arg_expr->rank == 0)
f3b0bb7a
AV
9496 {
9497 if (arg_expr->ts.type == BT_CLASS)
d42844f1 9498 gfc_add_data_component (arg_expr);
f3b0bb7a
AV
9499 gfc_conv_expr_reference (se, arg_expr);
9500 }
83d890b9 9501 else
2960a368 9502 gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
42a8246d 9503 se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
029b2d55
PT
9504
9505 /* Create a temporary variable for loc return value. Without this,
e53b6e56 9506 we get an error an ICE in gcc/expr.cc(expand_expr_addr_expr_1). */
0f8bc3e1 9507 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
726a989a 9508 gfc_add_modify (&se->pre, temp_var, se->expr);
83d890b9
AL
9509 se->expr = temp_var;
9510}
9511
cadddfdd
TB
9512
9513/* The following routine generates code for the intrinsic
9514 functions from the ISO_C_BINDING module:
9515 * C_LOC
9516 * C_FUNLOC
9517 * C_ASSOCIATED */
9518
9519static void
9520conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
9521{
9522 gfc_actual_arglist *arg = expr->value.function.actual;
9523
9524 if (expr->value.function.isym->id == GFC_ISYM_C_LOC)
9525 {
9526 if (arg->expr->rank == 0)
9527 gfc_conv_expr_reference (se, arg->expr);
460263d0 9528 else if (gfc_is_simply_contiguous (arg->expr, false, false))
cadddfdd 9529 gfc_conv_array_parameter (se, arg->expr, true, NULL, NULL, NULL);
6fbcd309
TB
9530 else
9531 {
9532 gfc_conv_expr_descriptor (se, arg->expr);
9533 se->expr = gfc_conv_descriptor_data_get (se->expr);
9534 }
cadddfdd
TB
9535
9536 /* TODO -- the following two lines shouldn't be necessary, but if
9537 they're removed, a bug is exposed later in the code path.
9538 This workaround was thus introduced, but will have to be
9539 removed; please see PR 35150 for details about the issue. */
9540 se->expr = convert (pvoid_type_node, se->expr);
9541 se->expr = gfc_evaluate_now (se->expr, &se->pre);
9542 }
9543 else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
9544 gfc_conv_expr_reference (se, arg->expr);
9545 else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
9546 {
9547 gfc_se arg1se;
9548 gfc_se arg2se;
9549
9550 /* Build the addr_expr for the first argument. The argument is
9551 already an *address* so we don't need to set want_pointer in
9552 the gfc_se. */
9553 gfc_init_se (&arg1se, NULL);
9554 gfc_conv_expr (&arg1se, arg->expr);
9555 gfc_add_block_to_block (&se->pre, &arg1se.pre);
9556 gfc_add_block_to_block (&se->post, &arg1se.post);
9557
9558 /* See if we were given two arguments. */
9559 if (arg->next->expr == NULL)
9560 /* Only given one arg so generate a null and do a
9561 not-equal comparison against the first arg. */
63ee5404 9562 se->expr = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
cadddfdd
TB
9563 arg1se.expr,
9564 fold_convert (TREE_TYPE (arg1se.expr),
9565 null_pointer_node));
9566 else
9567 {
9568 tree eq_expr;
9569 tree not_null_expr;
9570
9571 /* Given two arguments so build the arg2se from second arg. */
9572 gfc_init_se (&arg2se, NULL);
9573 gfc_conv_expr (&arg2se, arg->next->expr);
9574 gfc_add_block_to_block (&se->pre, &arg2se.pre);
9575 gfc_add_block_to_block (&se->post, &arg2se.post);
9576
9577 /* Generate test to compare that the two args are equal. */
63ee5404 9578 eq_expr = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
cadddfdd
TB
9579 arg1se.expr, arg2se.expr);
9580 /* Generate test to ensure that the first arg is not null. */
9581 not_null_expr = fold_build2_loc (input_location, NE_EXPR,
63ee5404 9582 logical_type_node,
cadddfdd
TB
9583 arg1se.expr, null_pointer_node);
9584
9585 /* Finally, the generated test must check that both arg1 is not
9586 NULL and that it is equal to the second arg. */
9587 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 9588 logical_type_node,
cadddfdd
TB
9589 not_null_expr, eq_expr);
9590 }
9591 }
9592 else
9593 gcc_unreachable ();
9594}
9595
9596
9597/* The following routine generates code for the intrinsic
9598 subroutines from the ISO_C_BINDING module:
9599 * C_F_POINTER
9600 * C_F_PROCPOINTER. */
9601
9602static tree
9603conv_isocbinding_subroutine (gfc_code *code)
9604{
9605 gfc_se se;
9606 gfc_se cptrse;
9607 gfc_se fptrse;
9608 gfc_se shapese;
9609 gfc_ss *shape_ss;
9610 tree desc, dim, tmp, stride, offset;
9611 stmtblock_t body, block;
9612 gfc_loopinfo loop;
9613 gfc_actual_arglist *arg = code->ext.actual;
9614
9615 gfc_init_se (&se, NULL);
9616 gfc_init_se (&cptrse, NULL);
9617 gfc_conv_expr (&cptrse, arg->expr);
9618 gfc_add_block_to_block (&se.pre, &cptrse.pre);
9619 gfc_add_block_to_block (&se.post, &cptrse.post);
9620
9621 gfc_init_se (&fptrse, NULL);
9622 if (arg->next->expr->rank == 0)
9623 {
9624 fptrse.want_pointer = 1;
9625 gfc_conv_expr (&fptrse, arg->next->expr);
9626 gfc_add_block_to_block (&se.pre, &fptrse.pre);
9627 gfc_add_block_to_block (&se.post, &fptrse.post);
9628 if (arg->next->expr->symtree->n.sym->attr.proc_pointer
9629 && arg->next->expr->symtree->n.sym->attr.dummy)
9630 fptrse.expr = build_fold_indirect_ref_loc (input_location,
9631 fptrse.expr);
9632 se.expr = fold_build2_loc (input_location, MODIFY_EXPR,
9633 TREE_TYPE (fptrse.expr),
9634 fptrse.expr,
9635 fold_convert (TREE_TYPE (fptrse.expr),
9636 cptrse.expr));
9637 gfc_add_expr_to_block (&se.pre, se.expr);
9638 gfc_add_block_to_block (&se.pre, &se.post);
9639 return gfc_finish_block (&se.pre);
9640 }
9641
9642 gfc_start_block (&block);
9643
9644 /* Get the descriptor of the Fortran pointer. */
9645 fptrse.descriptor_only = 1;
9646 gfc_conv_expr_descriptor (&fptrse, arg->next->expr);
9647 gfc_add_block_to_block (&block, &fptrse.pre);
9648 desc = fptrse.expr;
9649
ff3598bc
PT
9650 /* Set the span field. */
9651 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
9652 tmp = fold_convert (gfc_array_index_type, tmp);
9653 gfc_conv_descriptor_span_set (&block, desc, tmp);
9654
cadddfdd
TB
9655 /* Set data value, dtype, and offset. */
9656 tmp = GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc));
9657 gfc_conv_descriptor_data_set (&block, desc, fold_convert (tmp, cptrse.expr));
9658 gfc_add_modify (&block, gfc_conv_descriptor_dtype (desc),
9659 gfc_get_dtype (TREE_TYPE (desc)));
9660
9661 /* Start scalarization of the bounds, using the shape argument. */
9662
9663 shape_ss = gfc_walk_expr (arg->next->next->expr);
9664 gcc_assert (shape_ss != gfc_ss_terminator);
9665 gfc_init_se (&shapese, NULL);
9666
9667 gfc_init_loopinfo (&loop);
9668 gfc_add_ss_to_loop (&loop, shape_ss);
9669 gfc_conv_ss_startstride (&loop);
9670 gfc_conv_loop_setup (&loop, &arg->next->expr->where);
9671 gfc_mark_ss_chain_used (shape_ss, 1);
9672
9673 gfc_copy_loopinfo_to_se (&shapese, &loop);
9674 shapese.ss = shape_ss;
9675
9676 stride = gfc_create_var (gfc_array_index_type, "stride");
9677 offset = gfc_create_var (gfc_array_index_type, "offset");
9678 gfc_add_modify (&block, stride, gfc_index_one_node);
9679 gfc_add_modify (&block, offset, gfc_index_zero_node);
9680
9681 /* Loop body. */
9682 gfc_start_scalarized_body (&loop, &body);
9683
9684 dim = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
9685 loop.loopvar[0], loop.from[0]);
9686
1cc0e193 9687 /* Set bounds and stride. */
cadddfdd
TB
9688 gfc_conv_descriptor_lbound_set (&body, desc, dim, gfc_index_one_node);
9689 gfc_conv_descriptor_stride_set (&body, desc, dim, stride);
9690
9691 gfc_conv_expr (&shapese, arg->next->next->expr);
9692 gfc_add_block_to_block (&body, &shapese.pre);
9693 gfc_conv_descriptor_ubound_set (&body, desc, dim, shapese.expr);
9694 gfc_add_block_to_block (&body, &shapese.post);
9695
1cc0e193 9696 /* Calculate offset. */
cadddfdd
TB
9697 gfc_add_modify (&body, offset,
9698 fold_build2_loc (input_location, PLUS_EXPR,
9699 gfc_array_index_type, offset, stride));
9700 /* Update stride. */
9701 gfc_add_modify (&body, stride,
9702 fold_build2_loc (input_location, MULT_EXPR,
9703 gfc_array_index_type, stride,
9704 fold_convert (gfc_array_index_type,
9705 shapese.expr)));
9706 /* Finish scalarization loop. */
9707 gfc_trans_scalarizing_loops (&loop, &body);
9708 gfc_add_block_to_block (&block, &loop.pre);
9709 gfc_add_block_to_block (&block, &loop.post);
9710 gfc_add_block_to_block (&block, &fptrse.post);
9711 gfc_cleanup_loop (&loop);
9712
9713 gfc_add_modify (&block, offset,
9714 fold_build1_loc (input_location, NEGATE_EXPR,
9715 gfc_array_index_type, offset));
9716 gfc_conv_descriptor_offset_set (&block, desc, offset);
9717
9718 gfc_add_expr_to_block (&se.pre, gfc_finish_block (&block));
9719 gfc_add_block_to_block (&se.pre, &se.post);
9720 return gfc_finish_block (&se.pre);
9721}
9722
9723
3b7ea188
FXC
9724/* Save and restore floating-point state. */
9725
9726tree
9727gfc_save_fp_state (stmtblock_t *block)
9728{
9729 tree type, fpstate, tmp;
9730
9731 type = build_array_type (char_type_node,
9732 build_range_type (size_type_node, size_zero_node,
9733 size_int (GFC_FPE_STATE_BUFFER_SIZE)));
9734 fpstate = gfc_create_var (type, "fpstate");
9735 fpstate = gfc_build_addr_expr (pvoid_type_node, fpstate);
9736
9737 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_entry,
9738 1, fpstate);
9739 gfc_add_expr_to_block (block, tmp);
9740
9741 return fpstate;
9742}
9743
9744
9745void
9746gfc_restore_fp_state (stmtblock_t *block, tree fpstate)
9747{
9748 tree tmp;
9749
9750 tmp = build_call_expr_loc (input_location, gfor_fndecl_ieee_procedure_exit,
9751 1, fpstate);
9752 gfc_add_expr_to_block (block, tmp);
9753}
9754
9755
9756/* Generate code for arguments of IEEE functions. */
9757
9758static void
9759conv_ieee_function_args (gfc_se *se, gfc_expr *expr, tree *argarray,
9760 int nargs)
9761{
9762 gfc_actual_arglist *actual;
9763 gfc_expr *e;
9764 gfc_se argse;
9765 int arg;
9766
9767 actual = expr->value.function.actual;
9768 for (arg = 0; arg < nargs; arg++, actual = actual->next)
9769 {
9770 gcc_assert (actual);
9771 e = actual->expr;
9772
9773 gfc_init_se (&argse, se);
9774 gfc_conv_expr_val (&argse, e);
9775
9776 gfc_add_block_to_block (&se->pre, &argse.pre);
9777 gfc_add_block_to_block (&se->post, &argse.post);
9778 argarray[arg] = argse.expr;
9779 }
9780}
9781
9782
9783/* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
9784 and IEEE_UNORDERED, which translate directly to GCC type-generic
9785 built-ins. */
9786
9787static void
9788conv_intrinsic_ieee_builtin (gfc_se * se, gfc_expr * expr,
9789 enum built_in_function code, int nargs)
9790{
9791 tree args[2];
ca32b29e 9792 gcc_assert ((unsigned) nargs <= ARRAY_SIZE (args));
3b7ea188
FXC
9793
9794 conv_ieee_function_args (se, expr, args, nargs);
9795 se->expr = build_call_expr_loc_array (input_location,
9796 builtin_decl_explicit (code),
9797 nargs, args);
9798 STRIP_TYPE_NOPS (se->expr);
9799 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9800}
9801
9802
9803/* Generate code for IEEE_IS_NORMAL intrinsic:
9804 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
9805
9806static void
9807conv_intrinsic_ieee_is_normal (gfc_se * se, gfc_expr * expr)
9808{
9809 tree arg, isnormal, iszero;
9810
9811 /* Convert arg, evaluate it only once. */
9812 conv_ieee_function_args (se, expr, &arg, 1);
9813 arg = gfc_evaluate_now (arg, &se->pre);
9814
9815 isnormal = build_call_expr_loc (input_location,
9816 builtin_decl_explicit (BUILT_IN_ISNORMAL),
9817 1, arg);
63ee5404 9818 iszero = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, arg,
3b7ea188
FXC
9819 build_real_from_int_cst (TREE_TYPE (arg),
9820 integer_zero_node));
9821 se->expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
63ee5404 9822 logical_type_node, isnormal, iszero);
3b7ea188
FXC
9823 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9824}
9825
9826
9827/* Generate code for IEEE_IS_NEGATIVE intrinsic:
9828 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
9829
9830static void
9831conv_intrinsic_ieee_is_negative (gfc_se * se, gfc_expr * expr)
9832{
c541d521 9833 tree arg, signbit, isnan;
3b7ea188
FXC
9834
9835 /* Convert arg, evaluate it only once. */
9836 conv_ieee_function_args (se, expr, &arg, 1);
9837 arg = gfc_evaluate_now (arg, &se->pre);
9838
9839 isnan = build_call_expr_loc (input_location,
9840 builtin_decl_explicit (BUILT_IN_ISNAN),
9841 1, arg);
9842 STRIP_TYPE_NOPS (isnan);
9843
c541d521
FXC
9844 signbit = build_call_expr_loc (input_location,
9845 builtin_decl_explicit (BUILT_IN_SIGNBIT),
9846 1, arg);
63ee5404 9847 signbit = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3b7ea188
FXC
9848 signbit, integer_zero_node);
9849
9850 se->expr = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 9851 logical_type_node, signbit,
3b7ea188
FXC
9852 fold_build1_loc (input_location, TRUTH_NOT_EXPR,
9853 TREE_TYPE(isnan), isnan));
9854
9855 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
9856}
9857
9858
9859/* Generate code for IEEE_LOGB and IEEE_RINT. */
9860
9861static void
9862conv_intrinsic_ieee_logb_rint (gfc_se * se, gfc_expr * expr,
9863 enum built_in_function code)
9864{
9865 tree arg, decl, call, fpstate;
9866 int argprec;
9867
9868 conv_ieee_function_args (se, expr, &arg, 1);
9869 argprec = TYPE_PRECISION (TREE_TYPE (arg));
9870 decl = builtin_decl_for_precision (code, argprec);
9871
9872 /* Save floating-point state. */
9873 fpstate = gfc_save_fp_state (&se->pre);
9874
9875 /* Make the function call. */
9876 call = build_call_expr_loc (input_location, decl, 1, arg);
9877 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), call);
9878
9879 /* Restore floating-point state. */
9880 gfc_restore_fp_state (&se->post, fpstate);
9881}
9882
9883
9884/* Generate code for IEEE_REM. */
9885
9886static void
9887conv_intrinsic_ieee_rem (gfc_se * se, gfc_expr * expr)
9888{
9889 tree args[2], decl, call, fpstate;
9890 int argprec;
9891
9892 conv_ieee_function_args (se, expr, args, 2);
9893
9894 /* If arguments have unequal size, convert them to the larger. */
9895 if (TYPE_PRECISION (TREE_TYPE (args[0]))
9896 > TYPE_PRECISION (TREE_TYPE (args[1])))
9897 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
9898 else if (TYPE_PRECISION (TREE_TYPE (args[1]))
9899 > TYPE_PRECISION (TREE_TYPE (args[0])))
9900 args[0] = fold_convert (TREE_TYPE (args[1]), args[0]);
9901
9902 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
9903 decl = builtin_decl_for_precision (BUILT_IN_REMAINDER, argprec);
9904
9905 /* Save floating-point state. */
9906 fpstate = gfc_save_fp_state (&se->pre);
9907
9908 /* Make the function call. */
9909 call = build_call_expr_loc_array (input_location, decl, 2, args);
9910 se->expr = fold_convert (TREE_TYPE (args[0]), call);
9911
9912 /* Restore floating-point state. */
9913 gfc_restore_fp_state (&se->post, fpstate);
9914}
9915
9916
9917/* Generate code for IEEE_NEXT_AFTER. */
9918
9919static void
9920conv_intrinsic_ieee_next_after (gfc_se * se, gfc_expr * expr)
9921{
9922 tree args[2], decl, call, fpstate;
9923 int argprec;
9924
9925 conv_ieee_function_args (se, expr, args, 2);
9926
9927 /* Result has the characteristics of first argument. */
9928 args[1] = fold_convert (TREE_TYPE (args[0]), args[1]);
9929 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
9930 decl = builtin_decl_for_precision (BUILT_IN_NEXTAFTER, argprec);
9931
9932 /* Save floating-point state. */
9933 fpstate = gfc_save_fp_state (&se->pre);
9934
9935 /* Make the function call. */
9936 call = build_call_expr_loc_array (input_location, decl, 2, args);
9937 se->expr = fold_convert (TREE_TYPE (args[0]), call);
9938
9939 /* Restore floating-point state. */
9940 gfc_restore_fp_state (&se->post, fpstate);
9941}
9942
9943
9944/* Generate code for IEEE_SCALB. */
9945
9946static void
9947conv_intrinsic_ieee_scalb (gfc_se * se, gfc_expr * expr)
9948{
9949 tree args[2], decl, call, huge, type;
9950 int argprec, n;
9951
9952 conv_ieee_function_args (se, expr, args, 2);
9953
9954 /* Result has the characteristics of first argument. */
9955 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
9956 decl = builtin_decl_for_precision (BUILT_IN_SCALBN, argprec);
9957
9958 if (TYPE_PRECISION (TREE_TYPE (args[1])) > TYPE_PRECISION (integer_type_node))
9959 {
9960 /* We need to fold the integer into the range of a C int. */
9961 args[1] = gfc_evaluate_now (args[1], &se->pre);
9962 type = TREE_TYPE (args[1]);
9963
9964 n = gfc_validate_kind (BT_INTEGER, gfc_c_int_kind, false);
9965 huge = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
9966 gfc_c_int_kind);
9967 huge = fold_convert (type, huge);
9968 args[1] = fold_build2_loc (input_location, MIN_EXPR, type, args[1],
9969 huge);
9970 args[1] = fold_build2_loc (input_location, MAX_EXPR, type, args[1],
9971 fold_build1_loc (input_location, NEGATE_EXPR,
9972 type, huge));
9973 }
9974
9975 args[1] = fold_convert (integer_type_node, args[1]);
9976
9977 /* Make the function call. */
9978 call = build_call_expr_loc_array (input_location, decl, 2, args);
9979 se->expr = fold_convert (TREE_TYPE (args[0]), call);
9980}
9981
9982
9983/* Generate code for IEEE_COPY_SIGN. */
9984
9985static void
9986conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
9987{
9988 tree args[2], decl, sign;
9989 int argprec;
9990
9991 conv_ieee_function_args (se, expr, args, 2);
9992
9993 /* Get the sign of the second argument. */
c541d521
FXC
9994 sign = build_call_expr_loc (input_location,
9995 builtin_decl_explicit (BUILT_IN_SIGNBIT),
9996 1, args[1]);
63ee5404 9997 sign = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3b7ea188
FXC
9998 sign, integer_zero_node);
9999
10000 /* Create a value of one, with the right sign. */
10001 sign = fold_build3_loc (input_location, COND_EXPR, integer_type_node,
10002 sign,
10003 fold_build1_loc (input_location, NEGATE_EXPR,
10004 integer_type_node,
10005 integer_one_node),
10006 integer_one_node);
10007 args[1] = fold_convert (TREE_TYPE (args[0]), sign);
10008
10009 argprec = TYPE_PRECISION (TREE_TYPE (args[0]));
10010 decl = builtin_decl_for_precision (BUILT_IN_COPYSIGN, argprec);
10011
10012 se->expr = build_call_expr_loc_array (input_location, decl, 2, args);
10013}
10014
10015
db630423
JJ
10016/* Generate code for IEEE_CLASS. */
10017
10018static void
10019conv_intrinsic_ieee_class (gfc_se *se, gfc_expr *expr)
10020{
10021 tree arg, c, t1, t2, t3, t4;
10022
10023 /* Convert arg, evaluate it only once. */
10024 conv_ieee_function_args (se, expr, &arg, 1);
10025 arg = gfc_evaluate_now (arg, &se->pre);
10026
10027 c = build_call_expr_loc (input_location,
10028 builtin_decl_explicit (BUILT_IN_FPCLASSIFY), 6,
10029 build_int_cst (integer_type_node, IEEE_QUIET_NAN),
10030 build_int_cst (integer_type_node,
10031 IEEE_POSITIVE_INF),
10032 build_int_cst (integer_type_node,
10033 IEEE_POSITIVE_NORMAL),
10034 build_int_cst (integer_type_node,
10035 IEEE_POSITIVE_DENORMAL),
10036 build_int_cst (integer_type_node,
10037 IEEE_POSITIVE_ZERO),
10038 arg);
10039 c = gfc_evaluate_now (c, &se->pre);
10040 t1 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
10041 c, build_int_cst (integer_type_node,
10042 IEEE_QUIET_NAN));
10043 t2 = build_call_expr_loc (input_location,
10044 builtin_decl_explicit (BUILT_IN_ISSIGNALING), 1,
10045 arg);
10046 t2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10047 t2, build_zero_cst (TREE_TYPE (t2)));
10048 t1 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10049 logical_type_node, t1, t2);
10050 t3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
10051 c, build_int_cst (integer_type_node,
10052 IEEE_POSITIVE_ZERO));
10053 t4 = build_call_expr_loc (input_location,
10054 builtin_decl_explicit (BUILT_IN_SIGNBIT), 1,
10055 arg);
10056 t4 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
10057 t4, build_zero_cst (TREE_TYPE (t4)));
10058 t3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10059 logical_type_node, t3, t4);
10060 int s = IEEE_NEGATIVE_ZERO + IEEE_POSITIVE_ZERO;
10061 gcc_assert (IEEE_NEGATIVE_INF == s - IEEE_POSITIVE_INF);
10062 gcc_assert (IEEE_NEGATIVE_NORMAL == s - IEEE_POSITIVE_NORMAL);
10063 gcc_assert (IEEE_NEGATIVE_DENORMAL == s - IEEE_POSITIVE_DENORMAL);
10064 gcc_assert (IEEE_NEGATIVE_SUBNORMAL == s - IEEE_POSITIVE_SUBNORMAL);
10065 gcc_assert (IEEE_NEGATIVE_ZERO == s - IEEE_POSITIVE_ZERO);
10066 t4 = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (c),
10067 build_int_cst (TREE_TYPE (c), s), c);
10068 t3 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c),
10069 t3, t4, c);
10070 t1 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c), t1,
10071 build_int_cst (TREE_TYPE (c), IEEE_SIGNALING_NAN),
10072 t3);
10073 tree type = gfc_typenode_for_spec (&expr->ts);
10074 /* Perform a quick sanity check that the return type is
10075 IEEE_CLASS_TYPE derived type defined in
10076 libgfortran/ieee/ieee_arithmetic.F90
10077 Primarily check that it is a derived type with a single
10078 member in it. */
10079 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
10080 tree field = NULL_TREE;
10081 for (tree f = TYPE_FIELDS (type); f != NULL_TREE; f = DECL_CHAIN (f))
10082 if (TREE_CODE (f) == FIELD_DECL)
10083 {
10084 gcc_assert (field == NULL_TREE);
10085 field = f;
10086 }
10087 gcc_assert (field);
10088 t1 = fold_convert (TREE_TYPE (field), t1);
10089 se->expr = build_constructor_single (type, field, t1);
10090}
10091
10092
3b7ea188
FXC
10093/* Generate code for an intrinsic function from the IEEE_ARITHMETIC
10094 module. */
10095
10096bool
10097gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
10098{
10099 const char *name = expr->value.function.name;
10100
6ba3079d 10101 if (startswith (name, "_gfortran_ieee_is_nan"))
3b7ea188 10102 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
6ba3079d 10103 else if (startswith (name, "_gfortran_ieee_is_finite"))
3b7ea188 10104 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
6ba3079d 10105 else if (startswith (name, "_gfortran_ieee_unordered"))
3b7ea188 10106 conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
6ba3079d 10107 else if (startswith (name, "_gfortran_ieee_is_normal"))
3b7ea188 10108 conv_intrinsic_ieee_is_normal (se, expr);
6ba3079d 10109 else if (startswith (name, "_gfortran_ieee_is_negative"))
3b7ea188 10110 conv_intrinsic_ieee_is_negative (se, expr);
6ba3079d 10111 else if (startswith (name, "_gfortran_ieee_copy_sign"))
3b7ea188 10112 conv_intrinsic_ieee_copy_sign (se, expr);
6ba3079d 10113 else if (startswith (name, "_gfortran_ieee_scalb"))
3b7ea188 10114 conv_intrinsic_ieee_scalb (se, expr);
6ba3079d 10115 else if (startswith (name, "_gfortran_ieee_next_after"))
3b7ea188 10116 conv_intrinsic_ieee_next_after (se, expr);
6ba3079d 10117 else if (startswith (name, "_gfortran_ieee_rem"))
3b7ea188 10118 conv_intrinsic_ieee_rem (se, expr);
6ba3079d 10119 else if (startswith (name, "_gfortran_ieee_logb"))
3b7ea188 10120 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
6ba3079d 10121 else if (startswith (name, "_gfortran_ieee_rint"))
3b7ea188 10122 conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
db630423
JJ
10123 else if (startswith (name, "ieee_class_") && ISDIGIT (name[11]))
10124 conv_intrinsic_ieee_class (se, expr);
3b7ea188
FXC
10125 else
10126 /* It is not among the functions we translate directly. We return
10127 false, so a library function call is emitted. */
10128 return false;
10129
3b7ea188
FXC
10130 return true;
10131}
10132
10133
8b40ca6a
FXC
10134/* Generate a direct call to malloc() for the MALLOC intrinsic. */
10135
10136static void
10137gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr)
10138{
10139 tree arg, res, restype;
10140
10141 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
10142 arg = fold_convert (size_type_node, arg);
10143 res = build_call_expr_loc (input_location,
10144 builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg);
10145 restype = gfc_typenode_for_spec (&expr->ts);
10146 se->expr = fold_convert (restype, res);
10147}
10148
10149
6de9cd9a
DN
10150/* Generate code for an intrinsic function. Some map directly to library
10151 calls, others get special handling. In some cases the name of the function
10152 used depends on the type specifiers. */
10153
10154void
10155gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
10156{
6b25a558 10157 const char *name;
374929b2
FXC
10158 int lib, kind;
10159 tree fndecl;
6de9cd9a 10160
6de9cd9a
DN
10161 name = &expr->value.function.name[2];
10162
712efae1 10163 if (expr->rank > 0)
6de9cd9a
DN
10164 {
10165 lib = gfc_is_intrinsic_libcall (expr);
10166 if (lib != 0)
10167 {
10168 if (lib == 1)
10169 se->ignore_optional = 1;
1fbfb0e2
DK
10170
10171 switch (expr->value.function.isym->id)
10172 {
10173 case GFC_ISYM_EOSHIFT:
10174 case GFC_ISYM_PACK:
10175 case GFC_ISYM_RESHAPE:
10176 /* For all of those the first argument specifies the type and the
10177 third is optional. */
10178 conv_generic_with_optional_char_arg (se, expr, 1, 3);
10179 break;
10180
01ce9e31
TK
10181 case GFC_ISYM_FINDLOC:
10182 gfc_conv_intrinsic_findloc (se, expr);
10183 break;
10184
64b1806b
TK
10185 case GFC_ISYM_MINLOC:
10186 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
10187 break;
f8862a1b 10188
64b1806b
TK
10189 case GFC_ISYM_MAXLOC:
10190 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
10191 break;
10192
1fbfb0e2
DK
10193 default:
10194 gfc_conv_intrinsic_funcall (se, expr);
10195 break;
10196 }
10197
6de9cd9a
DN
10198 return;
10199 }
10200 }
10201
cd5ecab6 10202 switch (expr->value.function.isym->id)
6de9cd9a
DN
10203 {
10204 case GFC_ISYM_NONE:
6e45f57b 10205 gcc_unreachable ();
6de9cd9a
DN
10206
10207 case GFC_ISYM_REPEAT:
10208 gfc_conv_intrinsic_repeat (se, expr);
10209 break;
10210
10211 case GFC_ISYM_TRIM:
10212 gfc_conv_intrinsic_trim (se, expr);
10213 break;
10214
a39fafac
FXC
10215 case GFC_ISYM_SC_KIND:
10216 gfc_conv_intrinsic_sc_kind (se, expr);
10217 break;
10218
6de9cd9a
DN
10219 case GFC_ISYM_SI_KIND:
10220 gfc_conv_intrinsic_si_kind (se, expr);
10221 break;
10222
10223 case GFC_ISYM_SR_KIND:
10224 gfc_conv_intrinsic_sr_kind (se, expr);
10225 break;
10226
10227 case GFC_ISYM_EXPONENT:
10228 gfc_conv_intrinsic_exponent (se, expr);
10229 break;
10230
6de9cd9a 10231 case GFC_ISYM_SCAN:
374929b2
FXC
10232 kind = expr->value.function.actual->expr->ts.kind;
10233 if (kind == 1)
10234 fndecl = gfor_fndecl_string_scan;
10235 else if (kind == 4)
10236 fndecl = gfor_fndecl_string_scan_char4;
10237 else
10238 gcc_unreachable ();
10239
10240 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6de9cd9a
DN
10241 break;
10242
10243 case GFC_ISYM_VERIFY:
374929b2
FXC
10244 kind = expr->value.function.actual->expr->ts.kind;
10245 if (kind == 1)
10246 fndecl = gfor_fndecl_string_verify;
10247 else if (kind == 4)
10248 fndecl = gfor_fndecl_string_verify_char4;
10249 else
10250 gcc_unreachable ();
10251
10252 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6de9cd9a
DN
10253 break;
10254
10255 case GFC_ISYM_ALLOCATED:
10256 gfc_conv_allocated (se, expr);
10257 break;
10258
10259 case GFC_ISYM_ASSOCIATED:
10260 gfc_conv_associated(se, expr);
10261 break;
10262
cf2b3c22
TB
10263 case GFC_ISYM_SAME_TYPE_AS:
10264 gfc_conv_same_type_as (se, expr);
10265 break;
10266
6de9cd9a
DN
10267 case GFC_ISYM_ABS:
10268 gfc_conv_intrinsic_abs (se, expr);
10269 break;
10270
10271 case GFC_ISYM_ADJUSTL:
374929b2
FXC
10272 if (expr->ts.kind == 1)
10273 fndecl = gfor_fndecl_adjustl;
10274 else if (expr->ts.kind == 4)
10275 fndecl = gfor_fndecl_adjustl_char4;
10276 else
10277 gcc_unreachable ();
10278
10279 gfc_conv_intrinsic_adjust (se, expr, fndecl);
6de9cd9a
DN
10280 break;
10281
10282 case GFC_ISYM_ADJUSTR:
374929b2
FXC
10283 if (expr->ts.kind == 1)
10284 fndecl = gfor_fndecl_adjustr;
10285 else if (expr->ts.kind == 4)
10286 fndecl = gfor_fndecl_adjustr_char4;
10287 else
10288 gcc_unreachable ();
10289
10290 gfc_conv_intrinsic_adjust (se, expr, fndecl);
6de9cd9a
DN
10291 break;
10292
10293 case GFC_ISYM_AIMAG:
10294 gfc_conv_intrinsic_imagpart (se, expr);
10295 break;
10296
10297 case GFC_ISYM_AINT:
f9f770a8 10298 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
6de9cd9a
DN
10299 break;
10300
10301 case GFC_ISYM_ALL:
10302 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
10303 break;
10304
10305 case GFC_ISYM_ANINT:
f9f770a8 10306 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
6de9cd9a
DN
10307 break;
10308
5d723e54
FXC
10309 case GFC_ISYM_AND:
10310 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
10311 break;
10312
6de9cd9a
DN
10313 case GFC_ISYM_ANY:
10314 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
10315 break;
10316
57391dda
FR
10317 case GFC_ISYM_ACOSD:
10318 case GFC_ISYM_ASIND:
10319 case GFC_ISYM_ATAND:
10320 gfc_conv_intrinsic_atrigd (se, expr, expr->value.function.isym->id);
10321 break;
10322
10323 case GFC_ISYM_COTAN:
10324 gfc_conv_intrinsic_cotan (se, expr);
10325 break;
10326
10327 case GFC_ISYM_COTAND:
10328 gfc_conv_intrinsic_cotand (se, expr);
10329 break;
10330
10331 case GFC_ISYM_ATAN2D:
10332 gfc_conv_intrinsic_atan2d (se, expr);
10333 break;
10334
6de9cd9a
DN
10335 case GFC_ISYM_BTEST:
10336 gfc_conv_intrinsic_btest (se, expr);
10337 break;
10338
88a95a11
FXC
10339 case GFC_ISYM_BGE:
10340 gfc_conv_intrinsic_bitcomp (se, expr, GE_EXPR);
10341 break;
10342
10343 case GFC_ISYM_BGT:
10344 gfc_conv_intrinsic_bitcomp (se, expr, GT_EXPR);
10345 break;
10346
10347 case GFC_ISYM_BLE:
10348 gfc_conv_intrinsic_bitcomp (se, expr, LE_EXPR);
10349 break;
10350
10351 case GFC_ISYM_BLT:
10352 gfc_conv_intrinsic_bitcomp (se, expr, LT_EXPR);
10353 break;
10354
cadddfdd
TB
10355 case GFC_ISYM_C_ASSOCIATED:
10356 case GFC_ISYM_C_FUNLOC:
10357 case GFC_ISYM_C_LOC:
10358 conv_isocbinding_function (se, expr);
10359 break;
10360
6de9cd9a
DN
10361 case GFC_ISYM_ACHAR:
10362 case GFC_ISYM_CHAR:
10363 gfc_conv_intrinsic_char (se, expr);
10364 break;
10365
10366 case GFC_ISYM_CONVERSION:
6de9cd9a 10367 case GFC_ISYM_DBLE:
878f88b7
SK
10368 case GFC_ISYM_DFLOAT:
10369 case GFC_ISYM_FLOAT:
10370 case GFC_ISYM_LOGICAL:
10371 case GFC_ISYM_REAL:
10372 case GFC_ISYM_REALPART:
10373 case GFC_ISYM_SNGL:
6de9cd9a
DN
10374 gfc_conv_intrinsic_conversion (se, expr);
10375 break;
10376
e7dc5b4f 10377 /* Integer conversions are handled separately to make sure we get the
6de9cd9a
DN
10378 correct rounding mode. */
10379 case GFC_ISYM_INT:
bf3fb7e4
FXC
10380 case GFC_ISYM_INT2:
10381 case GFC_ISYM_INT8:
10382 case GFC_ISYM_LONG:
f9f770a8 10383 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
6de9cd9a
DN
10384 break;
10385
10386 case GFC_ISYM_NINT:
f9f770a8 10387 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
6de9cd9a
DN
10388 break;
10389
10390 case GFC_ISYM_CEILING:
f9f770a8 10391 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
6de9cd9a
DN
10392 break;
10393
10394 case GFC_ISYM_FLOOR:
f9f770a8 10395 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
6de9cd9a
DN
10396 break;
10397
10398 case GFC_ISYM_MOD:
10399 gfc_conv_intrinsic_mod (se, expr, 0);
10400 break;
10401
10402 case GFC_ISYM_MODULO:
10403 gfc_conv_intrinsic_mod (se, expr, 1);
10404 break;
10405
b5116268 10406 case GFC_ISYM_CAF_GET:
3c9f5092
AV
10407 gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
10408 false, NULL);
b5116268
TB
10409 break;
10410
6de9cd9a
DN
10411 case GFC_ISYM_CMPLX:
10412 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
10413 break;
10414
b41b2534 10415 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
d436d3de 10416 gfc_conv_intrinsic_iargc (se, expr);
b41b2534
JB
10417 break;
10418
5d723e54
FXC
10419 case GFC_ISYM_COMPLEX:
10420 gfc_conv_intrinsic_cmplx (se, expr, 1);
10421 break;
10422
6de9cd9a
DN
10423 case GFC_ISYM_CONJG:
10424 gfc_conv_intrinsic_conjg (se, expr);
10425 break;
10426
10427 case GFC_ISYM_COUNT:
10428 gfc_conv_intrinsic_count (se, expr);
10429 break;
10430
35059811
FXC
10431 case GFC_ISYM_CTIME:
10432 gfc_conv_intrinsic_ctime (se, expr);
10433 break;
10434
6de9cd9a
DN
10435 case GFC_ISYM_DIM:
10436 gfc_conv_intrinsic_dim (se, expr);
10437 break;
10438
61321991
PT
10439 case GFC_ISYM_DOT_PRODUCT:
10440 gfc_conv_intrinsic_dot_product (se, expr);
10441 break;
10442
6de9cd9a
DN
10443 case GFC_ISYM_DPROD:
10444 gfc_conv_intrinsic_dprod (se, expr);
10445 break;
10446
88a95a11
FXC
10447 case GFC_ISYM_DSHIFTL:
10448 gfc_conv_intrinsic_dshift (se, expr, true);
10449 break;
10450
10451 case GFC_ISYM_DSHIFTR:
10452 gfc_conv_intrinsic_dshift (se, expr, false);
10453 break;
10454
35059811
FXC
10455 case GFC_ISYM_FDATE:
10456 gfc_conv_intrinsic_fdate (se, expr);
10457 break;
10458
b5a4419c
FXC
10459 case GFC_ISYM_FRACTION:
10460 gfc_conv_intrinsic_fraction (se, expr);
10461 break;
10462
195a95c4
TB
10463 case GFC_ISYM_IALL:
10464 gfc_conv_intrinsic_arith (se, expr, BIT_AND_EXPR, false);
10465 break;
10466
6de9cd9a
DN
10467 case GFC_ISYM_IAND:
10468 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
10469 break;
10470
195a95c4
TB
10471 case GFC_ISYM_IANY:
10472 gfc_conv_intrinsic_arith (se, expr, BIT_IOR_EXPR, false);
10473 break;
10474
6de9cd9a
DN
10475 case GFC_ISYM_IBCLR:
10476 gfc_conv_intrinsic_singlebitop (se, expr, 0);
10477 break;
10478
10479 case GFC_ISYM_IBITS:
10480 gfc_conv_intrinsic_ibits (se, expr);
10481 break;
10482
10483 case GFC_ISYM_IBSET:
10484 gfc_conv_intrinsic_singlebitop (se, expr, 1);
10485 break;
10486
10487 case GFC_ISYM_IACHAR:
10488 case GFC_ISYM_ICHAR:
10489 /* We assume ASCII character sequence. */
10490 gfc_conv_intrinsic_ichar (se, expr);
10491 break;
10492
b41b2534 10493 case GFC_ISYM_IARGC:
d436d3de 10494 gfc_conv_intrinsic_iargc (se, expr);
b41b2534
JB
10495 break;
10496
6de9cd9a
DN
10497 case GFC_ISYM_IEOR:
10498 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
10499 break;
10500
10501 case GFC_ISYM_INDEX:
374929b2
FXC
10502 kind = expr->value.function.actual->expr->ts.kind;
10503 if (kind == 1)
10504 fndecl = gfor_fndecl_string_index;
10505 else if (kind == 4)
10506 fndecl = gfor_fndecl_string_index_char4;
10507 else
10508 gcc_unreachable ();
10509
10510 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6de9cd9a
DN
10511 break;
10512
10513 case GFC_ISYM_IOR:
10514 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
10515 break;
10516
195a95c4
TB
10517 case GFC_ISYM_IPARITY:
10518 gfc_conv_intrinsic_arith (se, expr, BIT_XOR_EXPR, false);
10519 break;
10520
bae89173 10521 case GFC_ISYM_IS_IOSTAT_END:
d74b97cc 10522 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
bae89173
FXC
10523 break;
10524
10525 case GFC_ISYM_IS_IOSTAT_EOR:
d74b97cc 10526 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
bae89173
FXC
10527 break;
10528
419af57c
TK
10529 case GFC_ISYM_IS_CONTIGUOUS:
10530 gfc_conv_intrinsic_is_contiguous (se, expr);
10531 break;
10532
3d97b1af
FXC
10533 case GFC_ISYM_ISNAN:
10534 gfc_conv_intrinsic_isnan (se, expr);
10535 break;
10536
17164de4
SK
10537 case GFC_ISYM_KILL:
10538 conv_intrinsic_kill (se, expr);
10539 break;
10540
a119fc1c 10541 case GFC_ISYM_LSHIFT:
88a95a11 10542 gfc_conv_intrinsic_shift (se, expr, false, false);
a119fc1c
FXC
10543 break;
10544
10545 case GFC_ISYM_RSHIFT:
88a95a11
FXC
10546 gfc_conv_intrinsic_shift (se, expr, true, true);
10547 break;
10548
10549 case GFC_ISYM_SHIFTA:
10550 gfc_conv_intrinsic_shift (se, expr, true, true);
10551 break;
10552
10553 case GFC_ISYM_SHIFTL:
10554 gfc_conv_intrinsic_shift (se, expr, false, false);
10555 break;
10556
10557 case GFC_ISYM_SHIFTR:
10558 gfc_conv_intrinsic_shift (se, expr, true, false);
a119fc1c
FXC
10559 break;
10560
6de9cd9a
DN
10561 case GFC_ISYM_ISHFT:
10562 gfc_conv_intrinsic_ishft (se, expr);
10563 break;
10564
10565 case GFC_ISYM_ISHFTC:
10566 gfc_conv_intrinsic_ishftc (se, expr);
10567 break;
10568
414f00e9
SB
10569 case GFC_ISYM_LEADZ:
10570 gfc_conv_intrinsic_leadz (se, expr);
10571 break;
10572
10573 case GFC_ISYM_TRAILZ:
10574 gfc_conv_intrinsic_trailz (se, expr);
10575 break;
10576
ad5f4de2
FXC
10577 case GFC_ISYM_POPCNT:
10578 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
10579 break;
10580
10581 case GFC_ISYM_POPPAR:
10582 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
10583 break;
10584
6de9cd9a 10585 case GFC_ISYM_LBOUND:
1af78e73 10586 gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_LBOUND);
6de9cd9a
DN
10587 break;
10588
a3935ffc
TB
10589 case GFC_ISYM_LCOBOUND:
10590 conv_intrinsic_cobound (se, expr);
10591 break;
10592
1524f80b 10593 case GFC_ISYM_TRANSPOSE:
712efae1
MM
10594 /* The scalarizer has already been set up for reversed dimension access
10595 order ; now we just get the argument value normally. */
10596 gfc_conv_expr (se, expr->value.function.actual->expr);
1524f80b
RS
10597 break;
10598
6de9cd9a
DN
10599 case GFC_ISYM_LEN:
10600 gfc_conv_intrinsic_len (se, expr);
10601 break;
10602
10603 case GFC_ISYM_LEN_TRIM:
10604 gfc_conv_intrinsic_len_trim (se, expr);
10605 break;
10606
10607 case GFC_ISYM_LGE:
10608 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
10609 break;
10610
10611 case GFC_ISYM_LGT:
10612 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
10613 break;
10614
10615 case GFC_ISYM_LLE:
10616 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
10617 break;
10618
10619 case GFC_ISYM_LLT:
10620 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
10621 break;
10622
8b40ca6a
FXC
10623 case GFC_ISYM_MALLOC:
10624 gfc_conv_intrinsic_malloc (se, expr);
10625 break;
10626
88a95a11
FXC
10627 case GFC_ISYM_MASKL:
10628 gfc_conv_intrinsic_mask (se, expr, 1);
10629 break;
10630
10631 case GFC_ISYM_MASKR:
10632 gfc_conv_intrinsic_mask (se, expr, 0);
10633 break;
10634
6de9cd9a 10635 case GFC_ISYM_MAX:
2263c775
FXC
10636 if (expr->ts.type == BT_CHARACTER)
10637 gfc_conv_intrinsic_minmax_char (se, expr, 1);
10638 else
10639 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
6de9cd9a
DN
10640 break;
10641
10642 case GFC_ISYM_MAXLOC:
10643 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
10644 break;
10645
01ce9e31
TK
10646 case GFC_ISYM_FINDLOC:
10647 gfc_conv_intrinsic_findloc (se, expr);
10648 break;
10649
6de9cd9a
DN
10650 case GFC_ISYM_MAXVAL:
10651 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
10652 break;
10653
10654 case GFC_ISYM_MERGE:
10655 gfc_conv_intrinsic_merge (se, expr);
10656 break;
10657
88a95a11
FXC
10658 case GFC_ISYM_MERGE_BITS:
10659 gfc_conv_intrinsic_merge_bits (se, expr);
10660 break;
10661
6de9cd9a 10662 case GFC_ISYM_MIN:
2263c775
FXC
10663 if (expr->ts.type == BT_CHARACTER)
10664 gfc_conv_intrinsic_minmax_char (se, expr, -1);
10665 else
10666 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
6de9cd9a
DN
10667 break;
10668
10669 case GFC_ISYM_MINLOC:
10670 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
10671 break;
10672
10673 case GFC_ISYM_MINVAL:
10674 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
10675 break;
10676
b5a4419c
FXC
10677 case GFC_ISYM_NEAREST:
10678 gfc_conv_intrinsic_nearest (se, expr);
10679 break;
10680
0cd0559e
TB
10681 case GFC_ISYM_NORM2:
10682 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
10683 break;
10684
6de9cd9a
DN
10685 case GFC_ISYM_NOT:
10686 gfc_conv_intrinsic_not (se, expr);
10687 break;
10688
5d723e54
FXC
10689 case GFC_ISYM_OR:
10690 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
10691 break;
10692
0cd0559e
TB
10693 case GFC_ISYM_PARITY:
10694 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
10695 break;
10696
6de9cd9a
DN
10697 case GFC_ISYM_PRESENT:
10698 gfc_conv_intrinsic_present (se, expr);
10699 break;
10700
10701 case GFC_ISYM_PRODUCT:
0cd0559e 10702 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
6de9cd9a 10703 break;
32e7b05d
TB
10704
10705 case GFC_ISYM_RANK:
10706 gfc_conv_intrinsic_rank (se, expr);
10707 break;
6de9cd9a 10708
b5a4419c
FXC
10709 case GFC_ISYM_RRSPACING:
10710 gfc_conv_intrinsic_rrspacing (se, expr);
10711 break;
10712
10713 case GFC_ISYM_SET_EXPONENT:
10714 gfc_conv_intrinsic_set_exponent (se, expr);
10715 break;
10716
10717 case GFC_ISYM_SCALE:
10718 gfc_conv_intrinsic_scale (se, expr);
10719 break;
10720
1af78e73
SL
10721 case GFC_ISYM_SHAPE:
10722 gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_SHAPE);
10723 break;
10724
6de9cd9a
DN
10725 case GFC_ISYM_SIGN:
10726 gfc_conv_intrinsic_sign (se, expr);
10727 break;
10728
10729 case GFC_ISYM_SIZE:
10730 gfc_conv_intrinsic_size (se, expr);
10731 break;
10732
fd2157ce 10733 case GFC_ISYM_SIZEOF:
048510c8 10734 case GFC_ISYM_C_SIZEOF:
fd2157ce
TS
10735 gfc_conv_intrinsic_sizeof (se, expr);
10736 break;
10737
048510c8
JW
10738 case GFC_ISYM_STORAGE_SIZE:
10739 gfc_conv_intrinsic_storage_size (se, expr);
10740 break;
10741
b5a4419c
FXC
10742 case GFC_ISYM_SPACING:
10743 gfc_conv_intrinsic_spacing (se, expr);
10744 break;
10745
0881224e
TB
10746 case GFC_ISYM_STRIDE:
10747 conv_intrinsic_stride (se, expr);
10748 break;
10749
6de9cd9a 10750 case GFC_ISYM_SUM:
0cd0559e 10751 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
6de9cd9a
DN
10752 break;
10753
f8862a1b
DR
10754 case GFC_ISYM_TEAM_NUMBER:
10755 conv_intrinsic_team_number (se, expr);
10756 break;
10757
6de9cd9a 10758 case GFC_ISYM_TRANSFER:
7a412892 10759 if (se->ss && se->ss->info->useflags)
3db5d687
MM
10760 /* Access the previously obtained result. */
10761 gfc_conv_tmp_array_ref (se);
0c5a42a6 10762 else
c41fea4a 10763 gfc_conv_intrinsic_transfer (se, expr);
25fc05eb
FXC
10764 break;
10765
10766 case GFC_ISYM_TTYNAM:
10767 gfc_conv_intrinsic_ttynam (se, expr);
6de9cd9a
DN
10768 break;
10769
10770 case GFC_ISYM_UBOUND:
1af78e73 10771 gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_UBOUND);
6de9cd9a
DN
10772 break;
10773
a3935ffc
TB
10774 case GFC_ISYM_UCOBOUND:
10775 conv_intrinsic_cobound (se, expr);
10776 break;
10777
5d723e54
FXC
10778 case GFC_ISYM_XOR:
10779 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
10780 break;
10781
83d890b9
AL
10782 case GFC_ISYM_LOC:
10783 gfc_conv_intrinsic_loc (se, expr);
10784 break;
10785
60386f50 10786 case GFC_ISYM_THIS_IMAGE:
0e3184ac
TB
10787 /* For num_images() == 1, handle as LCOBOUND. */
10788 if (expr->value.function.actual->expr
f19626cf 10789 && flag_coarray == GFC_FCOARRAY_SINGLE)
a3935ffc
TB
10790 conv_intrinsic_cobound (se, expr);
10791 else
10792 trans_this_image (se, expr);
60386f50
TB
10793 break;
10794
5af07930
TB
10795 case GFC_ISYM_IMAGE_INDEX:
10796 trans_image_index (se, expr);
10797 break;
10798
ef78bc3c
AV
10799 case GFC_ISYM_IMAGE_STATUS:
10800 conv_intrinsic_image_status (se, expr);
10801 break;
10802
60386f50 10803 case GFC_ISYM_NUM_IMAGES:
05fc16dd 10804 trans_num_images (se, expr);
60386f50
TB
10805 break;
10806
a119fc1c 10807 case GFC_ISYM_ACCESS:
f77b6ca3 10808 case GFC_ISYM_CHDIR:
a119fc1c 10809 case GFC_ISYM_CHMOD:
a1ba31ce 10810 case GFC_ISYM_DTIME:
2bd74949 10811 case GFC_ISYM_ETIME:
7c1dab0d 10812 case GFC_ISYM_EXTENDS_TYPE_OF:
5d723e54
FXC
10813 case GFC_ISYM_FGET:
10814 case GFC_ISYM_FGETC:
df65f093 10815 case GFC_ISYM_FNUM:
5d723e54
FXC
10816 case GFC_ISYM_FPUT:
10817 case GFC_ISYM_FPUTC:
df65f093 10818 case GFC_ISYM_FSTAT:
5d723e54 10819 case GFC_ISYM_FTELL:
a8c60d7f 10820 case GFC_ISYM_GETCWD:
4c0c6b9f
SK
10821 case GFC_ISYM_GETGID:
10822 case GFC_ISYM_GETPID:
10823 case GFC_ISYM_GETUID:
f77b6ca3 10824 case GFC_ISYM_HOSTNM:
f77b6ca3 10825 case GFC_ISYM_IERRNO:
df65f093 10826 case GFC_ISYM_IRAND:
ae8b8789 10827 case GFC_ISYM_ISATTY:
47b99694 10828 case GFC_ISYM_JN2:
f77b6ca3 10829 case GFC_ISYM_LINK:
bf3fb7e4 10830 case GFC_ISYM_LSTAT:
df65f093 10831 case GFC_ISYM_MATMUL:
bf3fb7e4
FXC
10832 case GFC_ISYM_MCLOCK:
10833 case GFC_ISYM_MCLOCK8:
df65f093 10834 case GFC_ISYM_RAND:
f77b6ca3 10835 case GFC_ISYM_RENAME:
df65f093 10836 case GFC_ISYM_SECOND:
53096259 10837 case GFC_ISYM_SECNDS:
185d7d97 10838 case GFC_ISYM_SIGNAL:
df65f093 10839 case GFC_ISYM_STAT:
f77b6ca3 10840 case GFC_ISYM_SYMLNK:
5b1374e9 10841 case GFC_ISYM_SYSTEM:
f77b6ca3
FXC
10842 case GFC_ISYM_TIME:
10843 case GFC_ISYM_TIME8:
d8fe26b2
SK
10844 case GFC_ISYM_UMASK:
10845 case GFC_ISYM_UNLINK:
47b99694 10846 case GFC_ISYM_YN2:
6de9cd9a
DN
10847 gfc_conv_intrinsic_funcall (se, expr);
10848 break;
10849
1fbfb0e2
DK
10850 case GFC_ISYM_EOSHIFT:
10851 case GFC_ISYM_PACK:
10852 case GFC_ISYM_RESHAPE:
10853 /* For those, expr->rank should always be >0 and thus the if above the
10854 switch should have matched. */
10855 gcc_unreachable ();
10856 break;
10857
6de9cd9a
DN
10858 default:
10859 gfc_conv_intrinsic_lib_function (se, expr);
10860 break;
10861 }
10862}
10863
10864
712efae1
MM
10865static gfc_ss *
10866walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
10867{
10868 gfc_ss *arg_ss, *tmp_ss;
10869 gfc_actual_arglist *arg;
10870
10871 arg = expr->value.function.actual;
10872
10873 gcc_assert (arg->expr);
10874
10875 arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
10876 gcc_assert (arg_ss != gfc_ss_terminator);
10877
10878 for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
10879 {
bcc4d4e0
MM
10880 if (tmp_ss->info->type != GFC_SS_SCALAR
10881 && tmp_ss->info->type != GFC_SS_REFERENCE)
712efae1 10882 {
cb4b9eae 10883 gcc_assert (tmp_ss->dimen == 2);
712efae1
MM
10884
10885 /* We just invert dimensions. */
fab27f52 10886 std::swap (tmp_ss->dim[0], tmp_ss->dim[1]);
712efae1
MM
10887 }
10888
10889 /* Stop when tmp_ss points to the last valid element of the chain... */
10890 if (tmp_ss->next == gfc_ss_terminator)
10891 break;
10892 }
10893
10894 /* ... so that we can attach the rest of the chain to it. */
10895 tmp_ss->next = ss;
10896
10897 return arg_ss;
10898}
10899
10900
0c08de8f
MM
10901/* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
10902 This has the side effect of reversing the nested list, so there is no
10903 need to call gfc_reverse_ss on it (the given list is assumed not to be
10904 reversed yet). */
10905
10906static gfc_ss *
10907nest_loop_dimension (gfc_ss *ss, int dim)
10908{
10909 int ss_dim, i;
10910 gfc_ss *new_ss, *prev_ss = gfc_ss_terminator;
10911 gfc_loopinfo *new_loop;
10912
10913 gcc_assert (ss != gfc_ss_terminator);
10914
10915 for (; ss != gfc_ss_terminator; ss = ss->next)
10916 {
10917 new_ss = gfc_get_ss ();
10918 new_ss->next = prev_ss;
10919 new_ss->parent = ss;
10920 new_ss->info = ss->info;
10921 new_ss->info->refcount++;
10922 if (ss->dimen != 0)
10923 {
10924 gcc_assert (ss->info->type != GFC_SS_SCALAR
10925 && ss->info->type != GFC_SS_REFERENCE);
10926
10927 new_ss->dimen = 1;
10928 new_ss->dim[0] = ss->dim[dim];
10929
10930 gcc_assert (dim < ss->dimen);
10931
10932 ss_dim = --ss->dimen;
10933 for (i = dim; i < ss_dim; i++)
10934 ss->dim[i] = ss->dim[i + 1];
10935
10936 ss->dim[ss_dim] = 0;
10937 }
10938 prev_ss = new_ss;
10939
10940 if (ss->nested_ss)
10941 {
10942 ss->nested_ss->parent = new_ss;
10943 new_ss->nested_ss = ss->nested_ss;
10944 }
10945 ss->nested_ss = new_ss;
10946 }
10947
10948 new_loop = gfc_get_loopinfo ();
10949 gfc_init_loopinfo (new_loop);
10950
10951 gcc_assert (prev_ss != NULL);
10952 gcc_assert (prev_ss != gfc_ss_terminator);
10953 gfc_add_ss_to_loop (new_loop, prev_ss);
10954 return new_ss->parent;
10955}
10956
10957
10958/* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
10959 is to be inlined. */
10960
10961static gfc_ss *
10962walk_inline_intrinsic_arith (gfc_ss *ss, gfc_expr *expr)
10963{
10964 gfc_ss *tmp_ss, *tail, *array_ss;
10965 gfc_actual_arglist *arg1, *arg2, *arg3;
10966 int sum_dim;
10967 bool scalar_mask = false;
10968
10969 /* The rank of the result will be determined later. */
10970 arg1 = expr->value.function.actual;
10971 arg2 = arg1->next;
10972 arg3 = arg2->next;
10973 gcc_assert (arg3 != NULL);
10974
10975 if (expr->rank == 0)
10976 return ss;
10977
10978 tmp_ss = gfc_ss_terminator;
10979
10980 if (arg3->expr)
10981 {
10982 gfc_ss *mask_ss;
10983
10984 mask_ss = gfc_walk_subexpr (tmp_ss, arg3->expr);
10985 if (mask_ss == tmp_ss)
10986 scalar_mask = 1;
10987
10988 tmp_ss = mask_ss;
10989 }
10990
10991 array_ss = gfc_walk_subexpr (tmp_ss, arg1->expr);
10992 gcc_assert (array_ss != tmp_ss);
10993
10994 /* Odd thing: If the mask is scalar, it is used by the frontend after
10995 the array (to make an if around the nested loop). Thus it shall
10996 be after array_ss once the gfc_ss list is reversed. */
10997 if (scalar_mask)
10998 tmp_ss = gfc_get_scalar_ss (array_ss, arg3->expr);
10999 else
11000 tmp_ss = array_ss;
11001
11002 /* "Hide" the dimension on which we will sum in the first arg's scalarization
11003 chain. */
11004 sum_dim = mpz_get_si (arg2->expr->value.integer) - 1;
11005 tail = nest_loop_dimension (tmp_ss, sum_dim);
11006 tail->next = ss;
11007
11008 return tmp_ss;
11009}
11010
11011
712efae1
MM
11012static gfc_ss *
11013walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
11014{
11015
11016 switch (expr->value.function.isym->id)
11017 {
0c08de8f
MM
11018 case GFC_ISYM_PRODUCT:
11019 case GFC_ISYM_SUM:
11020 return walk_inline_intrinsic_arith (ss, expr);
11021
712efae1
MM
11022 case GFC_ISYM_TRANSPOSE:
11023 return walk_inline_intrinsic_transpose (ss, expr);
11024
11025 default:
11026 gcc_unreachable ();
11027 }
11028 gcc_unreachable ();
11029}
11030
11031
6de9cd9a
DN
11032/* This generates code to execute before entering the scalarization loop.
11033 Currently does nothing. */
11034
11035void
11036gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
11037{
f98cfd3c 11038 switch (ss->info->expr->value.function.isym->id)
6de9cd9a
DN
11039 {
11040 case GFC_ISYM_UBOUND:
11041 case GFC_ISYM_LBOUND:
a3935ffc
TB
11042 case GFC_ISYM_UCOBOUND:
11043 case GFC_ISYM_LCOBOUND:
11044 case GFC_ISYM_THIS_IMAGE:
1af78e73 11045 case GFC_ISYM_SHAPE:
6de9cd9a
DN
11046 break;
11047
11048 default:
6e45f57b 11049 gcc_unreachable ();
6de9cd9a
DN
11050 }
11051}
11052
11053
1af78e73
SL
11054/* The LBOUND, LCOBOUND, UBOUND, UCOBOUND, and SHAPE intrinsics with
11055 one parameter are expanded into code inside the scalarization loop. */
6de9cd9a
DN
11056
11057static gfc_ss *
11058gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
11059{
c49ea23d
PT
11060 if (expr->value.function.actual->expr->ts.type == BT_CLASS)
11061 gfc_add_class_array_ref (expr->value.function.actual->expr);
11062
6de9cd9a 11063 /* The two argument version returns a scalar. */
1af78e73
SL
11064 if (expr->value.function.isym->id != GFC_ISYM_SHAPE
11065 && expr->value.function.actual->next->expr)
6de9cd9a
DN
11066 return ss;
11067
66877276 11068 return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC);
6de9cd9a
DN
11069}
11070
11071
11072/* Walk an intrinsic array libcall. */
11073
11074static gfc_ss *
11075gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
11076{
6e45f57b 11077 gcc_assert (expr->rank > 0);
66877276 11078 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
6de9cd9a
DN
11079}
11080
11081
712efae1
MM
11082/* Return whether the function call expression EXPR will be expanded
11083 inline by gfc_conv_intrinsic_function. */
11084
11085bool
11086gfc_inline_intrinsic_function_p (gfc_expr *expr)
11087{
2ea47ee9
TK
11088 gfc_actual_arglist *args, *dim_arg, *mask_arg;
11089 gfc_expr *maskexpr;
0c08de8f 11090
712efae1
MM
11091 if (!expr->value.function.isym)
11092 return false;
11093
11094 switch (expr->value.function.isym->id)
11095 {
0c08de8f
MM
11096 case GFC_ISYM_PRODUCT:
11097 case GFC_ISYM_SUM:
11098 /* Disable inline expansion if code size matters. */
11099 if (optimize_size)
11100 return false;
11101
11102 args = expr->value.function.actual;
2ea47ee9
TK
11103 dim_arg = args->next;
11104
0c08de8f 11105 /* We need to be able to subset the SUM argument at compile-time. */
2ea47ee9 11106 if (dim_arg->expr && dim_arg->expr->expr_type != EXPR_CONSTANT)
0c08de8f
MM
11107 return false;
11108
2ea47ee9
TK
11109 /* FIXME: If MASK is optional for a more than two-dimensional
11110 argument, the scalarizer gets confused if the mask is
11111 absent. See PR 82995. For now, fall back to the library
11112 function. */
11113
11114 mask_arg = dim_arg->next;
11115 maskexpr = mask_arg->expr;
11116
11117 if (expr->rank > 0 && maskexpr && maskexpr->expr_type == EXPR_VARIABLE
11118 && maskexpr->symtree->n.sym->attr.dummy
11119 && maskexpr->symtree->n.sym->attr.optional)
11120 return false;
0e308880 11121
0c08de8f
MM
11122 return true;
11123
712efae1
MM
11124 case GFC_ISYM_TRANSPOSE:
11125 return true;
11126
11127 default:
11128 return false;
11129 }
11130}
11131
11132
df2fba9e 11133/* Returns nonzero if the specified intrinsic function call maps directly to
6de9cd9a
DN
11134 an external library call. Should only be used for functions that return
11135 arrays. */
11136
11137int
11138gfc_is_intrinsic_libcall (gfc_expr * expr)
11139{
6e45f57b
PB
11140 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
11141 gcc_assert (expr->rank > 0);
6de9cd9a 11142
712efae1
MM
11143 if (gfc_inline_intrinsic_function_p (expr))
11144 return 0;
11145
cd5ecab6 11146 switch (expr->value.function.isym->id)
6de9cd9a
DN
11147 {
11148 case GFC_ISYM_ALL:
11149 case GFC_ISYM_ANY:
11150 case GFC_ISYM_COUNT:
01ce9e31 11151 case GFC_ISYM_FINDLOC:
47b99694 11152 case GFC_ISYM_JN2:
195a95c4
TB
11153 case GFC_ISYM_IANY:
11154 case GFC_ISYM_IALL:
11155 case GFC_ISYM_IPARITY:
6de9cd9a
DN
11156 case GFC_ISYM_MATMUL:
11157 case GFC_ISYM_MAXLOC:
11158 case GFC_ISYM_MAXVAL:
11159 case GFC_ISYM_MINLOC:
11160 case GFC_ISYM_MINVAL:
0cd0559e
TB
11161 case GFC_ISYM_NORM2:
11162 case GFC_ISYM_PARITY:
6de9cd9a
DN
11163 case GFC_ISYM_PRODUCT:
11164 case GFC_ISYM_SUM:
6de9cd9a 11165 case GFC_ISYM_SPREAD:
47b99694 11166 case GFC_ISYM_YN2:
6de9cd9a
DN
11167 /* Ignore absent optional parameters. */
11168 return 1;
11169
6de9cd9a
DN
11170 case GFC_ISYM_CSHIFT:
11171 case GFC_ISYM_EOSHIFT:
f8862a1b 11172 case GFC_ISYM_GET_TEAM:
ef78bc3c
AV
11173 case GFC_ISYM_FAILED_IMAGES:
11174 case GFC_ISYM_STOPPED_IMAGES:
6de9cd9a 11175 case GFC_ISYM_PACK:
ef78bc3c 11176 case GFC_ISYM_RESHAPE:
6de9cd9a
DN
11177 case GFC_ISYM_UNPACK:
11178 /* Pass absent optional parameters. */
11179 return 2;
11180
11181 default:
11182 return 0;
11183 }
11184}
11185
11186/* Walk an intrinsic function. */
11187gfc_ss *
11188gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
11189 gfc_intrinsic_sym * isym)
11190{
6e45f57b 11191 gcc_assert (isym);
6de9cd9a
DN
11192
11193 if (isym->elemental)
712efae1 11194 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
68d62cb2 11195 expr->value.function.isym,
5d9d16db 11196 GFC_SS_SCALAR);
6de9cd9a
DN
11197
11198 if (expr->rank == 0)
11199 return ss;
11200
712efae1
MM
11201 if (gfc_inline_intrinsic_function_p (expr))
11202 return walk_inline_intrinsic_function (ss, expr);
11203
6de9cd9a
DN
11204 if (gfc_is_intrinsic_libcall (expr))
11205 return gfc_walk_intrinsic_libfunc (ss, expr);
11206
11207 /* Special cases. */
cd5ecab6 11208 switch (isym->id)
6de9cd9a
DN
11209 {
11210 case GFC_ISYM_LBOUND:
a3935ffc 11211 case GFC_ISYM_LCOBOUND:
6de9cd9a 11212 case GFC_ISYM_UBOUND:
a3935ffc
TB
11213 case GFC_ISYM_UCOBOUND:
11214 case GFC_ISYM_THIS_IMAGE:
1af78e73 11215 case GFC_ISYM_SHAPE:
6de9cd9a
DN
11216 return gfc_walk_intrinsic_bound (ss, expr);
11217
0c5a42a6 11218 case GFC_ISYM_TRANSFER:
b5116268 11219 case GFC_ISYM_CAF_GET:
0c5a42a6
PT
11220 return gfc_walk_intrinsic_libfunc (ss, expr);
11221
6de9cd9a
DN
11222 default:
11223 /* This probably meant someone forgot to add an intrinsic to the above
ca39e6f2
FXC
11224 list(s) when they implemented it, or something's gone horribly
11225 wrong. */
11226 gcc_unreachable ();
6de9cd9a
DN
11227 }
11228}
11229
d62cf3df 11230static tree
a16ee379 11231conv_co_collective (gfc_code *code)
d62cf3df
TB
11232{
11233 gfc_se argse;
11234 stmtblock_t block, post_block;
c78d3425 11235 tree fndecl, array = NULL_TREE, strlen, image_index, stat, errmsg, errmsg_len;
229c5919 11236 gfc_expr *image_idx_expr, *stat_expr, *errmsg_expr, *opr_expr;
d62cf3df
TB
11237
11238 gfc_start_block (&block);
11239 gfc_init_block (&post_block);
11240
229c5919
TB
11241 if (code->resolved_isym->id == GFC_ISYM_CO_REDUCE)
11242 {
11243 opr_expr = code->ext.actual->next->expr;
11244 image_idx_expr = code->ext.actual->next->next->expr;
11245 stat_expr = code->ext.actual->next->next->next->expr;
11246 errmsg_expr = code->ext.actual->next->next->next->next->expr;
11247 }
11248 else
11249 {
11250 opr_expr = NULL;
11251 image_idx_expr = code->ext.actual->next->expr;
11252 stat_expr = code->ext.actual->next->next->expr;
11253 errmsg_expr = code->ext.actual->next->next->next->expr;
11254 }
11255
d62cf3df 11256 /* stat. */
229c5919 11257 if (stat_expr)
d62cf3df
TB
11258 {
11259 gfc_init_se (&argse, NULL);
229c5919 11260 gfc_conv_expr (&argse, stat_expr);
d62cf3df
TB
11261 gfc_add_block_to_block (&block, &argse.pre);
11262 gfc_add_block_to_block (&post_block, &argse.post);
11263 stat = argse.expr;
f19626cf 11264 if (flag_coarray != GFC_FCOARRAY_SINGLE)
d62cf3df
TB
11265 stat = gfc_build_addr_expr (NULL_TREE, stat);
11266 }
f19626cf 11267 else if (flag_coarray == GFC_FCOARRAY_SINGLE)
d62cf3df
TB
11268 stat = NULL_TREE;
11269 else
11270 stat = null_pointer_node;
11271
11272 /* Early exit for GFC_FCOARRAY_SINGLE. */
f19626cf 11273 if (flag_coarray == GFC_FCOARRAY_SINGLE)
d62cf3df
TB
11274 {
11275 if (stat != NULL_TREE)
da13e4eb
AV
11276 {
11277 /* For optional stats, check the pointer is valid before zero'ing. */
11278 if (gfc_expr_attr (stat_expr).optional)
11279 {
11280 tree tmp;
11281 stmtblock_t ass_block;
11282 gfc_start_block (&ass_block);
11283 gfc_add_modify (&ass_block, stat,
11284 fold_convert (TREE_TYPE (stat),
11285 integer_zero_node));
11286 tmp = fold_build2 (NE_EXPR, logical_type_node,
11287 gfc_build_addr_expr (NULL_TREE, stat),
11288 null_pointer_node);
11289 tmp = fold_build3 (COND_EXPR, void_type_node, tmp,
11290 gfc_finish_block (&ass_block),
11291 build_empty_stmt (input_location));
11292 gfc_add_expr_to_block (&block, tmp);
11293 }
11294 else
11295 gfc_add_modify (&block, stat,
11296 fold_convert (TREE_TYPE (stat), integer_zero_node));
11297 }
d62cf3df
TB
11298 return gfc_finish_block (&block);
11299 }
11300
26e237fb
AV
11301 gfc_symbol *derived = code->ext.actual->expr->ts.type == BT_DERIVED
11302 ? code->ext.actual->expr->ts.u.derived : NULL;
11303
d62cf3df
TB
11304 /* Handle the array. */
11305 gfc_init_se (&argse, NULL);
26e237fb
AV
11306 if (!derived || !derived->attr.alloc_comp
11307 || code->resolved_isym->id != GFC_ISYM_CO_BROADCAST)
6da86c25 11308 {
26e237fb
AV
11309 if (code->ext.actual->expr->rank == 0)
11310 {
11311 symbol_attribute attr;
11312 gfc_clear_attr (&attr);
11313 gfc_init_se (&argse, NULL);
11314 gfc_conv_expr (&argse, code->ext.actual->expr);
11315 gfc_add_block_to_block (&block, &argse.pre);
11316 gfc_add_block_to_block (&post_block, &argse.post);
11317 array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
11318 array = gfc_build_addr_expr (NULL_TREE, array);
11319 }
11320 else
11321 {
11322 argse.want_pointer = 1;
11323 gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
11324 array = argse.expr;
11325 }
d62cf3df 11326 }
c78d3425 11327
d62cf3df
TB
11328 gfc_add_block_to_block (&block, &argse.pre);
11329 gfc_add_block_to_block (&post_block, &argse.post);
11330
11331 if (code->ext.actual->expr->ts.type == BT_CHARACTER)
11332 strlen = argse.string_length;
11333 else
11334 strlen = integer_zero_node;
11335
d62cf3df 11336 /* image_index. */
229c5919 11337 if (image_idx_expr)
d62cf3df
TB
11338 {
11339 gfc_init_se (&argse, NULL);
229c5919 11340 gfc_conv_expr (&argse, image_idx_expr);
d62cf3df
TB
11341 gfc_add_block_to_block (&block, &argse.pre);
11342 gfc_add_block_to_block (&post_block, &argse.post);
11343 image_index = fold_convert (integer_type_node, argse.expr);
11344 }
11345 else
11346 image_index = integer_zero_node;
11347
11348 /* errmsg. */
229c5919 11349 if (errmsg_expr)
d62cf3df
TB
11350 {
11351 gfc_init_se (&argse, NULL);
229c5919 11352 gfc_conv_expr (&argse, errmsg_expr);
d62cf3df
TB
11353 gfc_add_block_to_block (&block, &argse.pre);
11354 gfc_add_block_to_block (&post_block, &argse.post);
11355 errmsg = argse.expr;
3f5fabc0 11356 errmsg_len = fold_convert (size_type_node, argse.string_length);
d62cf3df
TB
11357 }
11358 else
11359 {
11360 errmsg = null_pointer_node;
3f5fabc0 11361 errmsg_len = build_zero_cst (size_type_node);
d62cf3df
TB
11362 }
11363
11364 /* Generate the function call. */
a16ee379
TB
11365 switch (code->resolved_isym->id)
11366 {
11367 case GFC_ISYM_CO_BROADCAST:
11368 fndecl = gfor_fndecl_co_broadcast;
11369 break;
11370 case GFC_ISYM_CO_MAX:
11371 fndecl = gfor_fndecl_co_max;
11372 break;
11373 case GFC_ISYM_CO_MIN:
11374 fndecl = gfor_fndecl_co_min;
11375 break;
229c5919
TB
11376 case GFC_ISYM_CO_REDUCE:
11377 fndecl = gfor_fndecl_co_reduce;
11378 break;
a16ee379
TB
11379 case GFC_ISYM_CO_SUM:
11380 fndecl = gfor_fndecl_co_sum;
11381 break;
029b2d55 11382 default:
a16ee379
TB
11383 gcc_unreachable ();
11384 }
d62cf3df 11385
c78d3425
AF
11386 if (derived && derived->attr.alloc_comp
11387 && code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
11388 /* The derived type has the attribute 'alloc_comp'. */
11389 {
11390 tree tmp = gfc_bcast_alloc_comp (derived, code->ext.actual->expr,
11391 code->ext.actual->expr->rank,
11392 image_index, stat, errmsg, errmsg_len);
11393 gfc_add_expr_to_block (&block, tmp);
11394 }
229c5919
TB
11395 else
11396 {
c78d3425
AF
11397 if (code->resolved_isym->id == GFC_ISYM_CO_SUM
11398 || code->resolved_isym->id == GFC_ISYM_CO_BROADCAST)
11399 fndecl = build_call_expr_loc (input_location, fndecl, 5, array,
11400 image_index, stat, errmsg, errmsg_len);
11401 else if (code->resolved_isym->id != GFC_ISYM_CO_REDUCE)
11402 fndecl = build_call_expr_loc (input_location, fndecl, 6, array,
11403 image_index, stat, errmsg,
11404 strlen, errmsg_len);
229c5919
TB
11405 else
11406 {
c78d3425
AF
11407 tree opr, opr_flags;
11408
11409 // FIXME: Handle TS29113's bind(C) strings with descriptor.
11410 int opr_flag_int;
11411 if (gfc_is_proc_ptr_comp (opr_expr))
11412 {
11413 gfc_symbol *sym = gfc_get_proc_ptr_comp (opr_expr)->ts.interface;
11414 opr_flag_int = sym->attr.dimension
11415 || (sym->ts.type == BT_CHARACTER
11416 && !sym->attr.is_bind_c)
11417 ? GFC_CAF_BYREF : 0;
11418 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
11419 && !sym->attr.is_bind_c
11420 ? GFC_CAF_HIDDENLEN : 0;
11421 opr_flag_int |= sym->formal->sym->attr.value
11422 ? GFC_CAF_ARG_VALUE : 0;
11423 }
11424 else
11425 {
11426 opr_flag_int = gfc_return_by_reference (opr_expr->symtree->n.sym)
11427 ? GFC_CAF_BYREF : 0;
11428 opr_flag_int |= opr_expr->ts.type == BT_CHARACTER
11429 && !opr_expr->symtree->n.sym->attr.is_bind_c
11430 ? GFC_CAF_HIDDENLEN : 0;
11431 opr_flag_int |= opr_expr->symtree->n.sym->formal->sym->attr.value
11432 ? GFC_CAF_ARG_VALUE : 0;
11433 }
11434 opr_flags = build_int_cst (integer_type_node, opr_flag_int);
11435 gfc_conv_expr (&argse, opr_expr);
11436 opr = argse.expr;
11437 fndecl = build_call_expr_loc (input_location, fndecl, 8, array, opr,
11438 opr_flags, image_index, stat, errmsg,
11439 strlen, errmsg_len);
229c5919 11440 }
229c5919
TB
11441 }
11442
d62cf3df
TB
11443 gfc_add_expr_to_block (&block, fndecl);
11444 gfc_add_block_to_block (&block, &post_block);
11445
d62cf3df
TB
11446 return gfc_finish_block (&block);
11447}
11448
11449
da661a58 11450static tree
7f4aaf91 11451conv_intrinsic_atomic_op (gfc_code *code)
da661a58 11452{
42a8246d
TB
11453 gfc_se argse;
11454 tree tmp, atom, value, old = NULL_TREE, stat = NULL_TREE;
7f4aaf91 11455 stmtblock_t block, post_block;
b5116268 11456 gfc_expr *atom_expr = code->ext.actual->expr;
42a8246d 11457 gfc_expr *stat_expr;
7f4aaf91 11458 built_in_function fn;
b5116268
TB
11459
11460 if (atom_expr->expr_type == EXPR_FUNCTION
11461 && atom_expr->value.function.isym
11462 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
11463 atom_expr = atom_expr->value.function.actual->expr;
da661a58 11464
7f4aaf91
TB
11465 gfc_start_block (&block);
11466 gfc_init_block (&post_block);
42a8246d
TB
11467
11468 gfc_init_se (&argse, NULL);
11469 argse.want_pointer = 1;
11470 gfc_conv_expr (&argse, atom_expr);
11471 gfc_add_block_to_block (&block, &argse.pre);
11472 gfc_add_block_to_block (&post_block, &argse.post);
11473 atom = argse.expr;
11474
11475 gfc_init_se (&argse, NULL);
f19626cf 11476 if (flag_coarray == GFC_FCOARRAY_LIB
42a8246d
TB
11477 && code->ext.actual->next->expr->ts.kind == atom_expr->ts.kind)
11478 argse.want_pointer = 1;
11479 gfc_conv_expr (&argse, code->ext.actual->next->expr);
11480 gfc_add_block_to_block (&block, &argse.pre);
11481 gfc_add_block_to_block (&post_block, &argse.post);
11482 value = argse.expr;
11483
11484 switch (code->resolved_isym->id)
11485 {
11486 case GFC_ISYM_ATOMIC_ADD:
11487 case GFC_ISYM_ATOMIC_AND:
11488 case GFC_ISYM_ATOMIC_DEF:
11489 case GFC_ISYM_ATOMIC_OR:
11490 case GFC_ISYM_ATOMIC_XOR:
11491 stat_expr = code->ext.actual->next->next->expr;
f19626cf 11492 if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d
TB
11493 old = null_pointer_node;
11494 break;
11495 default:
11496 gfc_init_se (&argse, NULL);
f19626cf 11497 if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d
TB
11498 argse.want_pointer = 1;
11499 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
11500 gfc_add_block_to_block (&block, &argse.pre);
11501 gfc_add_block_to_block (&post_block, &argse.post);
11502 old = argse.expr;
11503 stat_expr = code->ext.actual->next->next->next->expr;
11504 }
11505
11506 /* STAT= */
11507 if (stat_expr != NULL)
11508 {
11509 gcc_assert (stat_expr->expr_type == EXPR_VARIABLE);
11510 gfc_init_se (&argse, NULL);
f19626cf 11511 if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d
TB
11512 argse.want_pointer = 1;
11513 gfc_conv_expr_val (&argse, stat_expr);
11514 gfc_add_block_to_block (&block, &argse.pre);
11515 gfc_add_block_to_block (&post_block, &argse.post);
11516 stat = argse.expr;
11517 }
f19626cf 11518 else if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d
TB
11519 stat = null_pointer_node;
11520
f19626cf 11521 if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d
TB
11522 {
11523 tree image_index, caf_decl, offset, token;
11524 int op;
11525
11526 switch (code->resolved_isym->id)
11527 {
11528 case GFC_ISYM_ATOMIC_ADD:
11529 case GFC_ISYM_ATOMIC_FETCH_ADD:
11530 op = (int) GFC_CAF_ATOMIC_ADD;
11531 break;
11532 case GFC_ISYM_ATOMIC_AND:
11533 case GFC_ISYM_ATOMIC_FETCH_AND:
11534 op = (int) GFC_CAF_ATOMIC_AND;
11535 break;
11536 case GFC_ISYM_ATOMIC_OR:
11537 case GFC_ISYM_ATOMIC_FETCH_OR:
11538 op = (int) GFC_CAF_ATOMIC_OR;
11539 break;
11540 case GFC_ISYM_ATOMIC_XOR:
11541 case GFC_ISYM_ATOMIC_FETCH_XOR:
11542 op = (int) GFC_CAF_ATOMIC_XOR;
11543 break;
11544 case GFC_ISYM_ATOMIC_DEF:
11545 op = 0; /* Unused. */
11546 break;
11547 default:
11548 gcc_unreachable ();
11549 }
11550
11551 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
11552 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
11553 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
11554
11555 if (gfc_is_coindexed (atom_expr))
2c69df3b 11556 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
42a8246d
TB
11557 else
11558 image_index = integer_zero_node;
11559
b2c298ab 11560 if (!POINTER_TYPE_P (TREE_TYPE (value)))
42a8246d
TB
11561 {
11562 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
11563 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), value));
11564 value = gfc_build_addr_expr (NULL_TREE, tmp);
11565 }
11566
3c9f5092
AV
11567 gfc_init_se (&argse, NULL);
11568 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
11569 atom_expr);
42a8246d 11570
3c9f5092 11571 gfc_add_block_to_block (&block, &argse.pre);
42a8246d
TB
11572 if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
11573 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
11574 token, offset, image_index, value, stat,
11575 build_int_cst (integer_type_node,
11576 (int) atom_expr->ts.type),
11577 build_int_cst (integer_type_node,
11578 (int) atom_expr->ts.kind));
11579 else
11580 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_op, 9,
11581 build_int_cst (integer_type_node, op),
11582 token, offset, image_index, value, old, stat,
11583 build_int_cst (integer_type_node,
11584 (int) atom_expr->ts.type),
11585 build_int_cst (integer_type_node,
11586 (int) atom_expr->ts.kind));
11587
11588 gfc_add_expr_to_block (&block, tmp);
3c9f5092 11589 gfc_add_block_to_block (&block, &argse.post);
42a8246d
TB
11590 gfc_add_block_to_block (&block, &post_block);
11591 return gfc_finish_block (&block);
11592 }
11593
da661a58 11594
7f4aaf91
TB
11595 switch (code->resolved_isym->id)
11596 {
11597 case GFC_ISYM_ATOMIC_ADD:
11598 case GFC_ISYM_ATOMIC_FETCH_ADD:
11599 fn = BUILT_IN_ATOMIC_FETCH_ADD_N;
11600 break;
11601 case GFC_ISYM_ATOMIC_AND:
11602 case GFC_ISYM_ATOMIC_FETCH_AND:
11603 fn = BUILT_IN_ATOMIC_FETCH_AND_N;
11604 break;
11605 case GFC_ISYM_ATOMIC_DEF:
11606 fn = BUILT_IN_ATOMIC_STORE_N;
11607 break;
11608 case GFC_ISYM_ATOMIC_OR:
11609 case GFC_ISYM_ATOMIC_FETCH_OR:
11610 fn = BUILT_IN_ATOMIC_FETCH_OR_N;
11611 break;
11612 case GFC_ISYM_ATOMIC_XOR:
11613 case GFC_ISYM_ATOMIC_FETCH_XOR:
11614 fn = BUILT_IN_ATOMIC_FETCH_XOR_N;
11615 break;
11616 default:
11617 gcc_unreachable ();
11618 }
11619
42a8246d 11620 tmp = TREE_TYPE (TREE_TYPE (atom));
7f4aaf91
TB
11621 fn = (built_in_function) ((int) fn
11622 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
11623 + 1);
42a8246d 11624 tree itype = TREE_TYPE (TREE_TYPE (atom));
7f4aaf91
TB
11625 tmp = builtin_decl_explicit (fn);
11626
11627 switch (code->resolved_isym->id)
11628 {
11629 case GFC_ISYM_ATOMIC_ADD:
11630 case GFC_ISYM_ATOMIC_AND:
11631 case GFC_ISYM_ATOMIC_DEF:
11632 case GFC_ISYM_ATOMIC_OR:
11633 case GFC_ISYM_ATOMIC_XOR:
42a8246d
TB
11634 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
11635 fold_convert (itype, value),
7f4aaf91
TB
11636 build_int_cst (NULL, MEMMODEL_RELAXED));
11637 gfc_add_expr_to_block (&block, tmp);
11638 break;
11639 default:
42a8246d
TB
11640 tmp = build_call_expr_loc (input_location, tmp, 3, atom,
11641 fold_convert (itype, value),
7f4aaf91 11642 build_int_cst (NULL, MEMMODEL_RELAXED));
42a8246d 11643 gfc_add_modify (&block, old, fold_convert (TREE_TYPE (old), tmp));
7f4aaf91
TB
11644 break;
11645 }
11646
42a8246d
TB
11647 if (stat != NULL_TREE)
11648 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
7f4aaf91 11649 gfc_add_block_to_block (&block, &post_block);
da661a58
TB
11650 return gfc_finish_block (&block);
11651}
11652
11653
11654static tree
11655conv_intrinsic_atomic_ref (gfc_code *code)
11656{
42a8246d
TB
11657 gfc_se argse;
11658 tree tmp, atom, value, stat = NULL_TREE;
7f4aaf91
TB
11659 stmtblock_t block, post_block;
11660 built_in_function fn;
11661 gfc_expr *atom_expr = code->ext.actual->next->expr;
b5116268
TB
11662
11663 if (atom_expr->expr_type == EXPR_FUNCTION
11664 && atom_expr->value.function.isym
11665 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
11666 atom_expr = atom_expr->value.function.actual->expr;
da661a58 11667
7f4aaf91
TB
11668 gfc_start_block (&block);
11669 gfc_init_block (&post_block);
42a8246d
TB
11670 gfc_init_se (&argse, NULL);
11671 argse.want_pointer = 1;
11672 gfc_conv_expr (&argse, atom_expr);
11673 gfc_add_block_to_block (&block, &argse.pre);
11674 gfc_add_block_to_block (&post_block, &argse.post);
11675 atom = argse.expr;
11676
11677 gfc_init_se (&argse, NULL);
f19626cf 11678 if (flag_coarray == GFC_FCOARRAY_LIB
d4b29c13 11679 && code->ext.actual->expr->ts.kind == atom_expr->ts.kind)
42a8246d
TB
11680 argse.want_pointer = 1;
11681 gfc_conv_expr (&argse, code->ext.actual->expr);
11682 gfc_add_block_to_block (&block, &argse.pre);
11683 gfc_add_block_to_block (&post_block, &argse.post);
11684 value = argse.expr;
11685
7f4aaf91
TB
11686 /* STAT= */
11687 if (code->ext.actual->next->next->expr != NULL)
11688 {
11689 gcc_assert (code->ext.actual->next->next->expr->expr_type
11690 == EXPR_VARIABLE);
42a8246d 11691 gfc_init_se (&argse, NULL);
f19626cf 11692 if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d
TB
11693 argse.want_pointer = 1;
11694 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
11695 gfc_add_block_to_block (&block, &argse.pre);
11696 gfc_add_block_to_block (&post_block, &argse.post);
11697 stat = argse.expr;
11698 }
f19626cf 11699 else if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d
TB
11700 stat = null_pointer_node;
11701
f19626cf 11702 if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d
TB
11703 {
11704 tree image_index, caf_decl, offset, token;
d4b29c13 11705 tree orig_value = NULL_TREE, vardecl = NULL_TREE;
42a8246d
TB
11706
11707 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
11708 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
11709 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
11710
11711 if (gfc_is_coindexed (atom_expr))
2c69df3b 11712 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
42a8246d
TB
11713 else
11714 image_index = integer_zero_node;
11715
3c9f5092
AV
11716 gfc_init_se (&argse, NULL);
11717 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
11718 atom_expr);
11719 gfc_add_block_to_block (&block, &argse.pre);
42a8246d 11720
d4b29c13
TB
11721 /* Different type, need type conversion. */
11722 if (!POINTER_TYPE_P (TREE_TYPE (value)))
11723 {
11724 vardecl = gfc_create_var (TREE_TYPE (TREE_TYPE (atom)), "value");
11725 orig_value = value;
11726 value = gfc_build_addr_expr (NULL_TREE, vardecl);
11727 }
11728
42a8246d
TB
11729 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_ref, 7,
11730 token, offset, image_index, value, stat,
11731 build_int_cst (integer_type_node,
11732 (int) atom_expr->ts.type),
11733 build_int_cst (integer_type_node,
11734 (int) atom_expr->ts.kind));
11735 gfc_add_expr_to_block (&block, tmp);
d4b29c13
TB
11736 if (vardecl != NULL_TREE)
11737 gfc_add_modify (&block, orig_value,
11738 fold_convert (TREE_TYPE (orig_value), vardecl));
3c9f5092 11739 gfc_add_block_to_block (&block, &argse.post);
42a8246d
TB
11740 gfc_add_block_to_block (&block, &post_block);
11741 return gfc_finish_block (&block);
7f4aaf91 11742 }
42a8246d
TB
11743
11744 tmp = TREE_TYPE (TREE_TYPE (atom));
11745 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_LOAD_N
11746 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
11747 + 1);
11748 tmp = builtin_decl_explicit (fn);
11749 tmp = build_call_expr_loc (input_location, tmp, 2, atom,
11750 build_int_cst (integer_type_node,
11751 MEMMODEL_RELAXED));
11752 gfc_add_modify (&block, value, fold_convert (TREE_TYPE (value), tmp));
11753
11754 if (stat != NULL_TREE)
11755 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
7f4aaf91
TB
11756 gfc_add_block_to_block (&block, &post_block);
11757 return gfc_finish_block (&block);
11758}
11759
11760
11761static tree
11762conv_intrinsic_atomic_cas (gfc_code *code)
11763{
11764 gfc_se argse;
42a8246d 11765 tree tmp, atom, old, new_val, comp, stat = NULL_TREE;
7f4aaf91
TB
11766 stmtblock_t block, post_block;
11767 built_in_function fn;
11768 gfc_expr *atom_expr = code->ext.actual->expr;
11769
11770 if (atom_expr->expr_type == EXPR_FUNCTION
11771 && atom_expr->value.function.isym
11772 && atom_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
11773 atom_expr = atom_expr->value.function.actual->expr;
da661a58
TB
11774
11775 gfc_init_block (&block);
7f4aaf91
TB
11776 gfc_init_block (&post_block);
11777 gfc_init_se (&argse, NULL);
11778 argse.want_pointer = 1;
11779 gfc_conv_expr (&argse, atom_expr);
11780 atom = argse.expr;
11781
11782 gfc_init_se (&argse, NULL);
f19626cf 11783 if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d 11784 argse.want_pointer = 1;
7f4aaf91
TB
11785 gfc_conv_expr (&argse, code->ext.actual->next->expr);
11786 gfc_add_block_to_block (&block, &argse.pre);
11787 gfc_add_block_to_block (&post_block, &argse.post);
11788 old = argse.expr;
11789
11790 gfc_init_se (&argse, NULL);
f19626cf 11791 if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d 11792 argse.want_pointer = 1;
7f4aaf91
TB
11793 gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
11794 gfc_add_block_to_block (&block, &argse.pre);
11795 gfc_add_block_to_block (&post_block, &argse.post);
11796 comp = argse.expr;
11797
11798 gfc_init_se (&argse, NULL);
f19626cf 11799 if (flag_coarray == GFC_FCOARRAY_LIB
42a8246d
TB
11800 && code->ext.actual->next->next->next->expr->ts.kind
11801 == atom_expr->ts.kind)
11802 argse.want_pointer = 1;
7f4aaf91
TB
11803 gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
11804 gfc_add_block_to_block (&block, &argse.pre);
11805 gfc_add_block_to_block (&post_block, &argse.post);
11806 new_val = argse.expr;
11807
42a8246d
TB
11808 /* STAT= */
11809 if (code->ext.actual->next->next->next->next->expr != NULL)
11810 {
11811 gcc_assert (code->ext.actual->next->next->next->next->expr->expr_type
11812 == EXPR_VARIABLE);
11813 gfc_init_se (&argse, NULL);
f19626cf 11814 if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d
TB
11815 argse.want_pointer = 1;
11816 gfc_conv_expr_val (&argse,
11817 code->ext.actual->next->next->next->next->expr);
11818 gfc_add_block_to_block (&block, &argse.pre);
11819 gfc_add_block_to_block (&post_block, &argse.post);
11820 stat = argse.expr;
11821 }
f19626cf 11822 else if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d
TB
11823 stat = null_pointer_node;
11824
f19626cf 11825 if (flag_coarray == GFC_FCOARRAY_LIB)
42a8246d
TB
11826 {
11827 tree image_index, caf_decl, offset, token;
11828
11829 caf_decl = gfc_get_tree_for_caf_expr (atom_expr);
11830 if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
11831 caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
11832
11833 if (gfc_is_coindexed (atom_expr))
2c69df3b 11834 image_index = gfc_caf_get_image_index (&block, atom_expr, caf_decl);
42a8246d
TB
11835 else
11836 image_index = integer_zero_node;
11837
11838 if (TREE_TYPE (TREE_TYPE (new_val)) != TREE_TYPE (TREE_TYPE (old)))
11839 {
11840 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "new");
11841 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), new_val));
11842 new_val = gfc_build_addr_expr (NULL_TREE, tmp);
11843 }
11844
11845 /* Convert a constant to a pointer. */
11846 if (!POINTER_TYPE_P (TREE_TYPE (comp)))
11847 {
11848 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
11849 gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
11850 comp = gfc_build_addr_expr (NULL_TREE, tmp);
11851 }
11852
3c9f5092
AV
11853 gfc_init_se (&argse, NULL);
11854 gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
11855 atom_expr);
11856 gfc_add_block_to_block (&block, &argse.pre);
42a8246d
TB
11857
11858 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
11859 token, offset, image_index, old, comp, new_val,
11860 stat, build_int_cst (integer_type_node,
11861 (int) atom_expr->ts.type),
11862 build_int_cst (integer_type_node,
11863 (int) atom_expr->ts.kind));
11864 gfc_add_expr_to_block (&block, tmp);
3c9f5092 11865 gfc_add_block_to_block (&block, &argse.post);
42a8246d
TB
11866 gfc_add_block_to_block (&block, &post_block);
11867 return gfc_finish_block (&block);
11868 }
11869
7f4aaf91
TB
11870 tmp = TREE_TYPE (TREE_TYPE (atom));
11871 fn = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
11872 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
11873 + 1);
11874 tmp = builtin_decl_explicit (fn);
11875
11876 gfc_add_modify (&block, old, comp);
11877 tmp = build_call_expr_loc (input_location, tmp, 6, atom,
11878 gfc_build_addr_expr (NULL, old),
11879 fold_convert (TREE_TYPE (old), new_val),
11880 boolean_false_node,
11881 build_int_cst (NULL, MEMMODEL_RELAXED),
11882 build_int_cst (NULL, MEMMODEL_RELAXED));
11883 gfc_add_expr_to_block (&block, tmp);
029b2d55 11884
42a8246d
TB
11885 if (stat != NULL_TREE)
11886 gfc_add_modify (&block, stat, build_int_cst (TREE_TYPE (stat), 0));
7f4aaf91 11887 gfc_add_block_to_block (&block, &post_block);
da661a58
TB
11888 return gfc_finish_block (&block);
11889}
11890
5df445a2
TB
11891static tree
11892conv_intrinsic_event_query (gfc_code *code)
11893{
11894 gfc_se se, argse;
11895 tree stat = NULL_TREE, stat2 = NULL_TREE;
11896 tree count = NULL_TREE, count2 = NULL_TREE;
11897
11898 gfc_expr *event_expr = code->ext.actual->expr;
11899
11900 if (code->ext.actual->next->next->expr)
11901 {
11902 gcc_assert (code->ext.actual->next->next->expr->expr_type
11903 == EXPR_VARIABLE);
11904 gfc_init_se (&argse, NULL);
11905 gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
11906 stat = argse.expr;
11907 }
11908 else if (flag_coarray == GFC_FCOARRAY_LIB)
11909 stat = null_pointer_node;
11910
11911 if (code->ext.actual->next->expr)
11912 {
11913 gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
11914 gfc_init_se (&argse, NULL);
11915 gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
11916 count = argse.expr;
11917 }
11918
11919 gfc_start_block (&se.pre);
11920 if (flag_coarray == GFC_FCOARRAY_LIB)
11921 {
11922 tree tmp, token, image_index;
0f97b81b 11923 tree index = build_zero_cst (gfc_array_index_type);
5df445a2
TB
11924
11925 if (event_expr->expr_type == EXPR_FUNCTION
11926 && event_expr->value.function.isym
11927 && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
11928 event_expr = event_expr->value.function.actual->expr;
11929
11930 tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
11931
11932 if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
11933 || event_expr->symtree->n.sym->ts.u.derived->from_intmod
11934 != INTMOD_ISO_FORTRAN_ENV
11935 || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
11936 != ISOFORTRAN_EVENT_TYPE)
11937 {
11938 gfc_error ("Sorry, the event component of derived type at %L is not "
11939 "yet supported", &event_expr->where);
11940 return NULL_TREE;
11941 }
11942
11943 if (gfc_is_coindexed (event_expr))
11944 {
2f029c08 11945 gfc_error ("The event variable at %L shall not be coindexed",
5df445a2
TB
11946 &event_expr->where);
11947 return NULL_TREE;
11948 }
11949
11950 image_index = integer_zero_node;
11951
3c9f5092
AV
11952 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
11953 event_expr);
5df445a2
TB
11954
11955 /* For arrays, obtain the array index. */
11956 if (gfc_expr_attr (event_expr).dimension)
11957 {
11958 tree desc, tmp, extent, lbound, ubound;
11959 gfc_array_ref *ar, ar2;
11960 int i;
11961
11962 /* TODO: Extend this, once DT components are supported. */
11963 ar = &event_expr->ref->u.ar;
11964 ar2 = *ar;
11965 memset (ar, '\0', sizeof (*ar));
11966 ar->as = ar2.as;
11967 ar->type = AR_FULL;
11968
11969 gfc_init_se (&argse, NULL);
11970 argse.descriptor_only = 1;
11971 gfc_conv_expr_descriptor (&argse, event_expr);
11972 gfc_add_block_to_block (&se.pre, &argse.pre);
11973 desc = argse.expr;
11974 *ar = ar2;
11975
0f97b81b 11976 extent = build_one_cst (gfc_array_index_type);
5df445a2
TB
11977 for (i = 0; i < ar->dimen; i++)
11978 {
11979 gfc_init_se (&argse, NULL);
0f97b81b 11980 gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
5df445a2
TB
11981 gfc_add_block_to_block (&argse.pre, &argse.pre);
11982 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
11983 tmp = fold_build2_loc (input_location, MINUS_EXPR,
0f97b81b 11984 TREE_TYPE (lbound), argse.expr, lbound);
5df445a2 11985 tmp = fold_build2_loc (input_location, MULT_EXPR,
0f97b81b 11986 TREE_TYPE (tmp), extent, tmp);
5df445a2 11987 index = fold_build2_loc (input_location, PLUS_EXPR,
0f97b81b 11988 TREE_TYPE (tmp), index, tmp);
5df445a2
TB
11989 if (i < ar->dimen - 1)
11990 {
11991 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
11992 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
5df445a2 11993 extent = fold_build2_loc (input_location, MULT_EXPR,
0f97b81b 11994 TREE_TYPE (tmp), extent, tmp);
5df445a2
TB
11995 }
11996 }
11997 }
11998
11999 if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
12000 {
12001 count2 = count;
12002 count = gfc_create_var (integer_type_node, "count");
12003 }
12004
12005 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
12006 {
12007 stat2 = stat;
12008 stat = gfc_create_var (integer_type_node, "stat");
12009 }
12010
cbd29d0e 12011 index = fold_convert (size_type_node, index);
5df445a2
TB
12012 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
12013 token, index, image_index, count
12014 ? gfc_build_addr_expr (NULL, count) : count,
12015 stat != null_pointer_node
12016 ? gfc_build_addr_expr (NULL, stat) : stat);
12017 gfc_add_expr_to_block (&se.pre, tmp);
12018
12019 if (count2 != NULL_TREE)
12020 gfc_add_modify (&se.pre, count2,
12021 fold_convert (TREE_TYPE (count2), count));
12022
12023 if (stat2 != NULL_TREE)
12024 gfc_add_modify (&se.pre, stat2,
12025 fold_convert (TREE_TYPE (stat2), stat));
12026
12027 return gfc_finish_block (&se.pre);
12028 }
12029
12030 gfc_init_se (&argse, NULL);
12031 gfc_conv_expr_val (&argse, code->ext.actual->expr);
12032 gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
12033
12034 if (stat != NULL_TREE)
12035 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
12036
12037 return gfc_finish_block (&se.pre);
12038}
da661a58 12039
5c5ce609
HA
12040
12041/* This is a peculiar case because of the need to do dependency checking.
e53b6e56 12042 It is called via trans-stmt.cc(gfc_trans_call), where it is picked out as
5c5ce609
HA
12043 a special case and this function called instead of
12044 gfc_conv_procedure_call. */
12045void
12046gfc_conv_intrinsic_mvbits (gfc_se *se, gfc_actual_arglist *actual_args,
12047 gfc_loopinfo *loop)
12048{
12049 gfc_actual_arglist *actual;
12050 gfc_se argse[5];
12051 gfc_expr *arg[5];
12052 gfc_ss *lss;
12053 int n;
12054
12055 tree from, frompos, len, to, topos;
12056 tree lenmask, oldbits, newbits, bitsize;
12057 tree type, utype, above, mask1, mask2;
12058
12059 if (loop)
12060 lss = loop->ss;
12061 else
12062 lss = gfc_ss_terminator;
12063
12064 actual = actual_args;
12065 for (n = 0; n < 5; n++, actual = actual->next)
12066 {
12067 arg[n] = actual->expr;
12068 gfc_init_se (&argse[n], NULL);
12069
12070 if (lss != gfc_ss_terminator)
12071 {
12072 gfc_copy_loopinfo_to_se (&argse[n], loop);
12073 /* Find the ss for the expression if it is there. */
12074 argse[n].ss = lss;
12075 gfc_mark_ss_chain_used (lss, 1);
12076 }
12077
12078 gfc_conv_expr (&argse[n], arg[n]);
12079
12080 if (loop)
12081 lss = argse[n].ss;
12082 }
12083
12084 from = argse[0].expr;
12085 frompos = argse[1].expr;
12086 len = argse[2].expr;
12087 to = argse[3].expr;
12088 topos = argse[4].expr;
12089
12090 /* The type of the result (TO). */
12091 type = TREE_TYPE (to);
12092 bitsize = build_int_cst (integer_type_node, TYPE_PRECISION (type));
12093
12094 /* Optionally generate code for runtime argument check. */
12095 if (gfc_option.rtcheck & GFC_RTCHECK_BITS)
12096 {
12097 tree nbits, below, ccond;
12098 tree fp = fold_convert (long_integer_type_node, frompos);
12099 tree ln = fold_convert (long_integer_type_node, len);
12100 tree tp = fold_convert (long_integer_type_node, topos);
12101 below = fold_build2_loc (input_location, LT_EXPR,
12102 logical_type_node, frompos,
12103 build_int_cst (TREE_TYPE (frompos), 0));
12104 above = fold_build2_loc (input_location, GT_EXPR,
12105 logical_type_node, frompos,
12106 fold_convert (TREE_TYPE (frompos), bitsize));
12107 ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
12108 logical_type_node, below, above);
12109 gfc_trans_runtime_check (true, false, ccond, &argse[1].pre,
12110 &arg[1]->where,
12111 "FROMPOS argument (%ld) out of range 0:%d "
12112 "in intrinsic MVBITS", fp, bitsize);
12113 below = fold_build2_loc (input_location, LT_EXPR,
12114 logical_type_node, len,
12115 build_int_cst (TREE_TYPE (len), 0));
12116 above = fold_build2_loc (input_location, GT_EXPR,
12117 logical_type_node, len,
12118 fold_convert (TREE_TYPE (len), bitsize));
12119 ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
12120 logical_type_node, below, above);
12121 gfc_trans_runtime_check (true, false, ccond, &argse[2].pre,
12122 &arg[2]->where,
12123 "LEN argument (%ld) out of range 0:%d "
12124 "in intrinsic MVBITS", ln, bitsize);
12125 below = fold_build2_loc (input_location, LT_EXPR,
12126 logical_type_node, topos,
12127 build_int_cst (TREE_TYPE (topos), 0));
12128 above = fold_build2_loc (input_location, GT_EXPR,
12129 logical_type_node, topos,
12130 fold_convert (TREE_TYPE (topos), bitsize));
12131 ccond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
12132 logical_type_node, below, above);
12133 gfc_trans_runtime_check (true, false, ccond, &argse[4].pre,
12134 &arg[4]->where,
12135 "TOPOS argument (%ld) out of range 0:%d "
12136 "in intrinsic MVBITS", tp, bitsize);
12137
12138 /* The tests above ensure that FROMPOS, LEN and TOPOS fit into short
12139 integers. Additions below cannot overflow. */
12140 nbits = fold_convert (long_integer_type_node, bitsize);
12141 above = fold_build2_loc (input_location, PLUS_EXPR,
12142 long_integer_type_node, fp, ln);
12143 ccond = fold_build2_loc (input_location, GT_EXPR,
12144 logical_type_node, above, nbits);
12145 gfc_trans_runtime_check (true, false, ccond, &argse[1].pre,
12146 &arg[1]->where,
12147 "FROMPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
12148 "in intrinsic MVBITS", fp, ln, bitsize);
12149 above = fold_build2_loc (input_location, PLUS_EXPR,
12150 long_integer_type_node, tp, ln);
12151 ccond = fold_build2_loc (input_location, GT_EXPR,
12152 logical_type_node, above, nbits);
12153 gfc_trans_runtime_check (true, false, ccond, &argse[4].pre,
12154 &arg[4]->where,
12155 "TOPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
12156 "in intrinsic MVBITS", tp, ln, bitsize);
12157 }
12158
12159 for (n = 0; n < 5; n++)
12160 {
12161 gfc_add_block_to_block (&se->pre, &argse[n].pre);
12162 gfc_add_block_to_block (&se->post, &argse[n].post);
12163 }
12164
12165 /* lenmask = (LEN >= bit_size (TYPE)) ? ~(TYPE)0 : ((TYPE)1 << LEN) - 1 */
12166 above = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
12167 len, fold_convert (TREE_TYPE (len), bitsize));
12168 mask1 = build_int_cst (type, -1);
12169 mask2 = fold_build2_loc (input_location, LSHIFT_EXPR, type,
12170 build_int_cst (type, 1), len);
12171 mask2 = fold_build2_loc (input_location, MINUS_EXPR, type,
12172 mask2, build_int_cst (type, 1));
12173 lenmask = fold_build3_loc (input_location, COND_EXPR, type,
12174 above, mask1, mask2);
12175
12176 /* newbits = (((UTYPE)(FROM) >> FROMPOS) & lenmask) << TOPOS.
12177 * For valid frompos+len <= bit_size(FROM) the conversion to unsigned is
12178 * not strictly necessary; artificial bits from rshift will be masked. */
12179 utype = unsigned_type_for (type);
12180 newbits = fold_build2_loc (input_location, RSHIFT_EXPR, utype,
12181 fold_convert (utype, from), frompos);
12182 newbits = fold_build2_loc (input_location, BIT_AND_EXPR, type,
12183 fold_convert (type, newbits), lenmask);
12184 newbits = fold_build2_loc (input_location, LSHIFT_EXPR, type,
12185 newbits, topos);
12186
12187 /* oldbits = TO & (~(lenmask << TOPOS)). */
12188 oldbits = fold_build2_loc (input_location, LSHIFT_EXPR, type,
12189 lenmask, topos);
12190 oldbits = fold_build1_loc (input_location, BIT_NOT_EXPR, type, oldbits);
12191 oldbits = fold_build2_loc (input_location, BIT_AND_EXPR, type, oldbits, to);
12192
12193 /* TO = newbits | oldbits. */
12194 se->expr = fold_build2_loc (input_location, BIT_IOR_EXPR, type,
12195 oldbits, newbits);
12196
12197 /* Return the assignment. */
12198 se->expr = fold_build2_loc (input_location, MODIFY_EXPR,
12199 void_type_node, to, se->expr);
12200}
12201
12202
da661a58
TB
12203static tree
12204conv_intrinsic_move_alloc (gfc_code *code)
b2a5eb75 12205{
e0516b05
TB
12206 stmtblock_t block;
12207 gfc_expr *from_expr, *to_expr;
fde50fe6 12208 gfc_expr *to_expr2, *from_expr2 = NULL;
e0516b05 12209 gfc_se from_se, to_se;
e0516b05 12210 tree tmp;
c1fb34c3 12211 bool coarray;
b2a5eb75 12212
e0516b05 12213 gfc_start_block (&block);
b2a5eb75 12214
e0516b05
TB
12215 from_expr = code->ext.actual->expr;
12216 to_expr = code->ext.actual->next->expr;
b2a5eb75 12217
e0516b05
TB
12218 gfc_init_se (&from_se, NULL);
12219 gfc_init_se (&to_se, NULL);
8199eea1 12220
102344e2
TB
12221 gcc_assert (from_expr->ts.type != BT_CLASS
12222 || to_expr->ts.type == BT_CLASS);
c1fb34c3 12223 coarray = gfc_get_corank (from_expr) != 0;
102344e2 12224
c1fb34c3 12225 if (from_expr->rank == 0 && !coarray)
e0516b05
TB
12226 {
12227 if (from_expr->ts.type != BT_CLASS)
fde50fe6
TB
12228 from_expr2 = from_expr;
12229 else
e0516b05 12230 {
fde50fe6
TB
12231 from_expr2 = gfc_copy_expr (from_expr);
12232 gfc_add_data_component (from_expr2);
e0516b05 12233 }
fde50fe6
TB
12234
12235 if (to_expr->ts.type != BT_CLASS)
12236 to_expr2 = to_expr;
b2a5eb75 12237 else
e0516b05
TB
12238 {
12239 to_expr2 = gfc_copy_expr (to_expr);
e0516b05
TB
12240 gfc_add_data_component (to_expr2);
12241 }
b2a5eb75 12242
e0516b05
TB
12243 from_se.want_pointer = 1;
12244 to_se.want_pointer = 1;
12245 gfc_conv_expr (&from_se, from_expr2);
12246 gfc_conv_expr (&to_se, to_expr2);
12247 gfc_add_block_to_block (&block, &from_se.pre);
12248 gfc_add_block_to_block (&block, &to_se.pre);
12249
12250 /* Deallocate "to". */
ba85c8c3
AV
12251 tmp = gfc_deallocate_scalar_with_status (to_se.expr, NULL_TREE, NULL_TREE,
12252 true, to_expr, to_expr->ts);
b2a5eb75
JW
12253 gfc_add_expr_to_block (&block, tmp);
12254
e0516b05
TB
12255 /* Assign (_data) pointers. */
12256 gfc_add_modify_loc (input_location, &block, to_se.expr,
12257 fold_convert (TREE_TYPE (to_se.expr), from_se.expr));
12258
12259 /* Set "from" to NULL. */
12260 gfc_add_modify_loc (input_location, &block, from_se.expr,
12261 fold_convert (TREE_TYPE (from_se.expr), null_pointer_node));
12262
12263 gfc_add_block_to_block (&block, &from_se.post);
12264 gfc_add_block_to_block (&block, &to_se.post);
12265
12266 /* Set _vptr. */
fde50fe6 12267 if (to_expr->ts.type == BT_CLASS)
e0516b05 12268 {
f6c28ef1
TB
12269 gfc_symbol *vtab;
12270
fde50fe6 12271 gfc_free_expr (to_expr2);
e0516b05 12272 gfc_init_se (&to_se, NULL);
e0516b05 12273 to_se.want_pointer = 1;
e0516b05 12274 gfc_add_vptr_component (to_expr);
e0516b05 12275 gfc_conv_expr (&to_se, to_expr);
fde50fe6
TB
12276
12277 if (from_expr->ts.type == BT_CLASS)
12278 {
f968d60b
TB
12279 if (UNLIMITED_POLY (from_expr))
12280 vtab = NULL;
12281 else
12282 {
12283 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
12284 gcc_assert (vtab);
12285 }
f6c28ef1 12286
fde50fe6
TB
12287 gfc_free_expr (from_expr2);
12288 gfc_init_se (&from_se, NULL);
12289 from_se.want_pointer = 1;
12290 gfc_add_vptr_component (from_expr);
12291 gfc_conv_expr (&from_se, from_expr);
f6c28ef1
TB
12292 gfc_add_modify_loc (input_location, &block, to_se.expr,
12293 fold_convert (TREE_TYPE (to_se.expr),
12294 from_se.expr));
12295
12296 /* Reset _vptr component to declared type. */
910ddd18
TB
12297 if (vtab == NULL)
12298 /* Unlimited polymorphic. */
f968d60b
TB
12299 gfc_add_modify_loc (input_location, &block, from_se.expr,
12300 fold_convert (TREE_TYPE (from_se.expr),
12301 null_pointer_node));
12302 else
12303 {
12304 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
12305 gfc_add_modify_loc (input_location, &block, from_se.expr,
12306 fold_convert (TREE_TYPE (from_se.expr), tmp));
12307 }
fde50fe6
TB
12308 }
12309 else
12310 {
7289d1c9 12311 vtab = gfc_find_vtab (&from_expr->ts);
fde50fe6
TB
12312 gcc_assert (vtab);
12313 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
f6c28ef1
TB
12314 gfc_add_modify_loc (input_location, &block, to_se.expr,
12315 fold_convert (TREE_TYPE (to_se.expr), tmp));
fde50fe6 12316 }
e0516b05
TB
12317 }
12318
38217d3e
PT
12319 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
12320 {
12321 gfc_add_modify_loc (input_location, &block, to_se.string_length,
12322 fold_convert (TREE_TYPE (to_se.string_length),
12323 from_se.string_length));
12324 if (from_expr->ts.deferred)
12325 gfc_add_modify_loc (input_location, &block, from_se.string_length,
12326 build_int_cst (TREE_TYPE (from_se.string_length), 0));
12327 }
12328
b2a5eb75
JW
12329 return gfc_finish_block (&block);
12330 }
e0516b05
TB
12331
12332 /* Update _vptr component. */
fde50fe6 12333 if (to_expr->ts.type == BT_CLASS)
e0516b05 12334 {
f6c28ef1
TB
12335 gfc_symbol *vtab;
12336
e0516b05 12337 to_se.want_pointer = 1;
e0516b05 12338 to_expr2 = gfc_copy_expr (to_expr);
e0516b05 12339 gfc_add_vptr_component (to_expr2);
e0516b05
TB
12340 gfc_conv_expr (&to_se, to_expr2);
12341
fde50fe6
TB
12342 if (from_expr->ts.type == BT_CLASS)
12343 {
f968d60b
TB
12344 if (UNLIMITED_POLY (from_expr))
12345 vtab = NULL;
12346 else
12347 {
12348 vtab = gfc_find_derived_vtab (from_expr->ts.u.derived);
12349 gcc_assert (vtab);
12350 }
f6c28ef1 12351
fde50fe6
TB
12352 from_se.want_pointer = 1;
12353 from_expr2 = gfc_copy_expr (from_expr);
12354 gfc_add_vptr_component (from_expr2);
12355 gfc_conv_expr (&from_se, from_expr2);
f6c28ef1
TB
12356 gfc_add_modify_loc (input_location, &block, to_se.expr,
12357 fold_convert (TREE_TYPE (to_se.expr),
12358 from_se.expr));
12359
12360 /* Reset _vptr component to declared type. */
910ddd18
TB
12361 if (vtab == NULL)
12362 /* Unlimited polymorphic. */
f968d60b
TB
12363 gfc_add_modify_loc (input_location, &block, from_se.expr,
12364 fold_convert (TREE_TYPE (from_se.expr),
12365 null_pointer_node));
12366 else
12367 {
12368 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
12369 gfc_add_modify_loc (input_location, &block, from_se.expr,
12370 fold_convert (TREE_TYPE (from_se.expr), tmp));
12371 }
fde50fe6
TB
12372 }
12373 else
12374 {
7289d1c9 12375 vtab = gfc_find_vtab (&from_expr->ts);
fde50fe6
TB
12376 gcc_assert (vtab);
12377 tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
f6c28ef1
TB
12378 gfc_add_modify_loc (input_location, &block, to_se.expr,
12379 fold_convert (TREE_TYPE (to_se.expr), tmp));
fde50fe6
TB
12380 }
12381
e0516b05 12382 gfc_free_expr (to_expr2);
e0516b05 12383 gfc_init_se (&to_se, NULL);
fde50fe6
TB
12384
12385 if (from_expr->ts.type == BT_CLASS)
12386 {
12387 gfc_free_expr (from_expr2);
12388 gfc_init_se (&from_se, NULL);
12389 }
e0516b05
TB
12390 }
12391
2960a368 12392
e0516b05 12393 /* Deallocate "to". */
2960a368 12394 if (from_expr->rank == 0)
c1fb34c3 12395 {
2960a368
TB
12396 to_se.want_coarray = 1;
12397 from_se.want_coarray = 1;
c1fb34c3 12398 }
2960a368
TB
12399 gfc_conv_expr_descriptor (&to_se, to_expr);
12400 gfc_conv_expr_descriptor (&from_se, from_expr);
e0516b05 12401
c1fb34c3
TB
12402 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
12403 is an image control "statement", cf. IR F08/0040 in 12-006A. */
f19626cf 12404 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
c1fb34c3
TB
12405 {
12406 tree cond;
12407
12408 tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
12409 NULL_TREE, NULL_TREE, true, to_expr,
ba85c8c3 12410 GFC_CAF_COARRAY_DEALLOCATE_ONLY);
c1fb34c3
TB
12411 gfc_add_expr_to_block (&block, tmp);
12412
12413 tmp = gfc_conv_descriptor_data_get (to_se.expr);
12414 cond = fold_build2_loc (input_location, EQ_EXPR,
63ee5404 12415 logical_type_node, tmp,
c1fb34c3
TB
12416 fold_convert (TREE_TYPE (tmp),
12417 null_pointer_node));
12418 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
12419 3, null_pointer_node, null_pointer_node,
12420 build_int_cst (integer_type_node, 0));
12421
12422 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
12423 tmp, build_empty_stmt (input_location));
12424 gfc_add_expr_to_block (&block, tmp);
12425 }
12426 else
12427 {
38217d3e
PT
12428 if (to_expr->ts.type == BT_DERIVED
12429 && to_expr->ts.u.derived->attr.alloc_comp)
12430 {
12431 tmp = gfc_deallocate_alloc_comp (to_expr->ts.u.derived,
12432 to_se.expr, to_expr->rank);
12433 gfc_add_expr_to_block (&block, tmp);
12434 }
12435
c1fb34c3
TB
12436 tmp = gfc_conv_descriptor_data_get (to_se.expr);
12437 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
ba85c8c3
AV
12438 NULL_TREE, true, to_expr,
12439 GFC_CAF_COARRAY_NOCOARRAY);
c1fb34c3
TB
12440 gfc_add_expr_to_block (&block, tmp);
12441 }
e0516b05
TB
12442
12443 /* Move the pointer and update the array descriptor data. */
12444 gfc_add_modify_loc (input_location, &block, to_se.expr, from_se.expr);
12445
f6c28ef1 12446 /* Set "from" to NULL. */
e0516b05
TB
12447 tmp = gfc_conv_descriptor_data_get (from_se.expr);
12448 gfc_add_modify_loc (input_location, &block, tmp,
12449 fold_convert (TREE_TYPE (tmp), null_pointer_node));
12450
38217d3e
PT
12451
12452 if (to_expr->ts.type == BT_CHARACTER && to_expr->ts.deferred)
12453 {
12454 gfc_add_modify_loc (input_location, &block, to_se.string_length,
12455 fold_convert (TREE_TYPE (to_se.string_length),
12456 from_se.string_length));
12457 if (from_expr->ts.deferred)
12458 gfc_add_modify_loc (input_location, &block, from_se.string_length,
12459 build_int_cst (TREE_TYPE (from_se.string_length), 0));
12460 }
12461
e0516b05 12462 return gfc_finish_block (&block);
b2a5eb75
JW
12463}
12464
12465
da661a58
TB
12466tree
12467gfc_conv_intrinsic_subroutine (gfc_code *code)
12468{
12469 tree res;
12470
12471 gcc_assert (code->resolved_isym);
12472
12473 switch (code->resolved_isym->id)
12474 {
12475 case GFC_ISYM_MOVE_ALLOC:
12476 res = conv_intrinsic_move_alloc (code);
12477 break;
12478
7f4aaf91
TB
12479 case GFC_ISYM_ATOMIC_CAS:
12480 res = conv_intrinsic_atomic_cas (code);
12481 break;
12482
12483 case GFC_ISYM_ATOMIC_ADD:
12484 case GFC_ISYM_ATOMIC_AND:
da661a58 12485 case GFC_ISYM_ATOMIC_DEF:
7f4aaf91
TB
12486 case GFC_ISYM_ATOMIC_OR:
12487 case GFC_ISYM_ATOMIC_XOR:
12488 case GFC_ISYM_ATOMIC_FETCH_ADD:
12489 case GFC_ISYM_ATOMIC_FETCH_AND:
12490 case GFC_ISYM_ATOMIC_FETCH_OR:
12491 case GFC_ISYM_ATOMIC_FETCH_XOR:
12492 res = conv_intrinsic_atomic_op (code);
da661a58
TB
12493 break;
12494
12495 case GFC_ISYM_ATOMIC_REF:
12496 res = conv_intrinsic_atomic_ref (code);
12497 break;
12498
5df445a2
TB
12499 case GFC_ISYM_EVENT_QUERY:
12500 res = conv_intrinsic_event_query (code);
12501 break;
12502
cadddfdd
TB
12503 case GFC_ISYM_C_F_POINTER:
12504 case GFC_ISYM_C_F_PROCPOINTER:
12505 res = conv_isocbinding_subroutine (code);
12506 break;
12507
b5116268
TB
12508 case GFC_ISYM_CAF_SEND:
12509 res = conv_caf_send (code);
12510 break;
12511
a16ee379 12512 case GFC_ISYM_CO_BROADCAST:
d62cf3df
TB
12513 case GFC_ISYM_CO_MIN:
12514 case GFC_ISYM_CO_MAX:
229c5919 12515 case GFC_ISYM_CO_REDUCE:
d62cf3df 12516 case GFC_ISYM_CO_SUM:
a16ee379 12517 res = conv_co_collective (code);
d62cf3df 12518 break;
cadddfdd 12519
8b40ca6a
FXC
12520 case GFC_ISYM_FREE:
12521 res = conv_intrinsic_free (code);
12522 break;
12523
ddd3e26e
SK
12524 case GFC_ISYM_RANDOM_INIT:
12525 res = conv_intrinsic_random_init (code);
12526 break;
12527
17164de4
SK
12528 case GFC_ISYM_KILL:
12529 res = conv_intrinsic_kill_sub (code);
12530 break;
12531
5c5ce609
HA
12532 case GFC_ISYM_MVBITS:
12533 res = NULL_TREE;
12534 break;
12535
a416c4c7
FXC
12536 case GFC_ISYM_SYSTEM_CLOCK:
12537 res = conv_intrinsic_system_clock (code);
12538 break;
12539
da661a58
TB
12540 default:
12541 res = NULL_TREE;
12542 break;
12543 }
12544
12545 return res;
12546}
12547
6de9cd9a 12548#include "gt-fortran-trans-intrinsic.h"
This page took 8.586201 seconds and 5 git commands to generate.