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