]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-intrinsic.c
re PR fortran/38282 (Bit intrinsics: ILEN and IBCHNG)
[thirdparty/gcc.git] / gcc / fortran / trans-intrinsic.c
CommitLineData
6de9cd9a 1/* Intrinsic translation
fa502cb2 2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
0eadc091 3 Free Software Foundation, Inc.
6de9cd9a
DN
4 Contributed by Paul Brook <paul@nowt.org>
5 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6
9fc4d79b 7This file is part of GCC.
6de9cd9a 8
9fc4d79b
TS
9GCC is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
d234d788 11Software Foundation; either version 3, or (at your option) any later
9fc4d79b 12version.
6de9cd9a 13
9fc4d79b
TS
14GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17for more details.
6de9cd9a
DN
18
19You should have received a copy of the GNU General Public License
d234d788
NC
20along with GCC; see the file COPYING3. If not see
21<http://www.gnu.org/licenses/>. */
6de9cd9a
DN
22
23/* trans-intrinsic.c-- generate GENERIC trees for calls to intrinsics. */
24
25#include "config.h"
26#include "system.h"
27#include "coretypes.h"
a48ba7e1 28#include "tm.h" /* For UNITS_PER_WORD. */
6de9cd9a 29#include "tree.h"
6de9cd9a 30#include "ggc.h"
c829d016
TB
31#include "diagnostic-core.h" /* For internal_error. */
32#include "toplev.h" /* For rest_of_decl_compilation. */
6de9cd9a 33#include "flags.h"
6de9cd9a 34#include "gfortran.h"
f8e566e5 35#include "arith.h"
6de9cd9a
DN
36#include "intrinsic.h"
37#include "trans.h"
38#include "trans-const.h"
39#include "trans-types.h"
40#include "trans-array.h"
41#include "defaults.h"
42/* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
43#include "trans-stmt.h"
44
45/* This maps fortran intrinsic math functions to external library or GCC
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{
142 int i = END_BUILTINS;
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
FXC
160
161 return (i == END_BUILTINS ? NULL_TREE : built_in_decls[i]);
162}
163
164
165static tree
166builtin_decl_for_float_kind (enum built_in_function double_built_in, int kind)
167{
168 int i = gfc_validate_kind (BT_REAL, kind, false);
a3c85b74
FXC
169
170 if (gfc_real_kinds[i].c_float128)
171 {
172 /* For __float128, the story is a bit different, because we return
173 a decl to a library function rather than a built-in. */
174 gfc_intrinsic_map_t *m;
175 for (m = gfc_intrinsic_map; m->double_built_in != double_built_in ; m++)
176 ;
177
178 return m->real16_decl;
179 }
180
2921157d
FXC
181 return builtin_decl_for_precision (double_built_in,
182 gfc_real_kinds[i].mode_precision);
183}
184
185
55637e51
LM
186/* Evaluate the arguments to an intrinsic function. The value
187 of NARGS may be less than the actual number of arguments in EXPR
188 to allow optional "KIND" arguments that are not included in the
189 generated code to be ignored. */
6de9cd9a 190
55637e51
LM
191static void
192gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
193 tree *argarray, int nargs)
6de9cd9a
DN
194{
195 gfc_actual_arglist *actual;
e15e9be3
PT
196 gfc_expr *e;
197 gfc_intrinsic_arg *formal;
6de9cd9a 198 gfc_se argse;
55637e51 199 int curr_arg;
6de9cd9a 200
e15e9be3 201 formal = expr->value.function.isym->formal;
55637e51 202 actual = expr->value.function.actual;
e15e9be3 203
55637e51
LM
204 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
205 actual = actual->next,
206 formal = formal ? formal->next : NULL)
6de9cd9a 207 {
55637e51 208 gcc_assert (actual);
e15e9be3 209 e = actual->expr;
aa9c57ec 210 /* Skip omitted optional arguments. */
e15e9be3 211 if (!e)
55637e51
LM
212 {
213 --curr_arg;
214 continue;
215 }
6de9cd9a
DN
216
217 /* Evaluate the parameter. This will substitute scalarized
f7b529fa 218 references automatically. */
6de9cd9a
DN
219 gfc_init_se (&argse, se);
220
e15e9be3 221 if (e->ts.type == BT_CHARACTER)
6de9cd9a 222 {
e15e9be3 223 gfc_conv_expr (&argse, e);
6de9cd9a 224 gfc_conv_string_parameter (&argse);
55637e51
LM
225 argarray[curr_arg++] = argse.string_length;
226 gcc_assert (curr_arg < nargs);
6de9cd9a
DN
227 }
228 else
e15e9be3
PT
229 gfc_conv_expr_val (&argse, e);
230
231 /* If an optional argument is itself an optional dummy argument,
232 check its presence and substitute a null if absent. */
33717d59 233 if (e->expr_type == EXPR_VARIABLE
e15e9be3
PT
234 && e->symtree->n.sym->attr.optional
235 && formal
236 && formal->optional)
be9c3c6e 237 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
6de9cd9a
DN
238
239 gfc_add_block_to_block (&se->pre, &argse.pre);
240 gfc_add_block_to_block (&se->post, &argse.post);
55637e51
LM
241 argarray[curr_arg] = argse.expr;
242 }
243}
244
245/* Count the number of actual arguments to the intrinsic function EXPR
246 including any "hidden" string length arguments. */
247
248static unsigned int
249gfc_intrinsic_argument_list_length (gfc_expr *expr)
250{
251 int n = 0;
252 gfc_actual_arglist *actual;
253
254 for (actual = expr->value.function.actual; actual; actual = actual->next)
255 {
256 if (!actual->expr)
257 continue;
258
259 if (actual->expr->ts.type == BT_CHARACTER)
260 n += 2;
261 else
262 n++;
8374844f 263 }
55637e51
LM
264
265 return n;
6de9cd9a
DN
266}
267
268
269/* Conversions between different types are output by the frontend as
270 intrinsic functions. We implement these directly with inline code. */
271
272static void
273gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
274{
275 tree type;
55637e51
LM
276 tree *args;
277 int nargs;
6de9cd9a 278
55637e51 279 nargs = gfc_intrinsic_argument_list_length (expr);
1145e690 280 args = XALLOCAVEC (tree, nargs);
55637e51
LM
281
282 /* Evaluate all the arguments passed. Whilst we're only interested in the
283 first one here, there are other parts of the front-end that assume this
284 and will trigger an ICE if it's not the case. */
6de9cd9a 285 type = gfc_typenode_for_spec (&expr->ts);
6e45f57b 286 gcc_assert (expr->value.function.actual->expr);
55637e51 287 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6de9cd9a 288
d393bbd7
FXC
289 /* Conversion between character kinds involves a call to a library
290 function. */
291 if (expr->ts.type == BT_CHARACTER)
292 {
293 tree fndecl, var, addr, tmp;
294
295 if (expr->ts.kind == 1
296 && expr->value.function.actual->expr->ts.kind == 4)
297 fndecl = gfor_fndecl_convert_char4_to_char1;
298 else if (expr->ts.kind == 4
299 && expr->value.function.actual->expr->ts.kind == 1)
300 fndecl = gfor_fndecl_convert_char1_to_char4;
301 else
302 gcc_unreachable ();
303
304 /* Create the variable storing the converted value. */
305 type = gfc_get_pchar_type (expr->ts.kind);
306 var = gfc_create_var (type, "str");
307 addr = gfc_build_addr_expr (build_pointer_type (type), var);
308
309 /* Call the library function that will perform the conversion. */
310 gcc_assert (nargs >= 2);
db3927fb
AH
311 tmp = build_call_expr_loc (input_location,
312 fndecl, 3, addr, args[0], args[1]);
d393bbd7
FXC
313 gfc_add_expr_to_block (&se->pre, tmp);
314
315 /* Free the temporary afterwards. */
316 tmp = gfc_call_free (var);
317 gfc_add_expr_to_block (&se->post, tmp);
318
319 se->expr = var;
320 se->string_length = args[0];
321
322 return;
323 }
324
6de9cd9a
DN
325 /* Conversion from complex to non-complex involves taking the real
326 component of the value. */
55637e51 327 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
6de9cd9a
DN
328 && expr->ts.type != BT_COMPLEX)
329 {
330 tree artype;
331
55637e51 332 artype = TREE_TYPE (TREE_TYPE (args[0]));
44855d8c 333 args[0] = fold_build1 (REALPART_EXPR, artype, args[0]);
6de9cd9a
DN
334 }
335
55637e51 336 se->expr = convert (type, args[0]);
6de9cd9a
DN
337}
338
4fdb5c71
TS
339/* This is needed because the gcc backend only implements
340 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
341 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
6de9cd9a
DN
342 Similarly for CEILING. */
343
344static tree
345build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
346{
347 tree tmp;
348 tree cond;
349 tree argtype;
350 tree intval;
351
352 argtype = TREE_TYPE (arg);
353 arg = gfc_evaluate_now (arg, pblock);
354
355 intval = convert (type, arg);
356 intval = gfc_evaluate_now (intval, pblock);
357
358 tmp = convert (argtype, intval);
44855d8c 359 cond = fold_build2 (up ? GE_EXPR : LE_EXPR, boolean_type_node, tmp, arg);
6de9cd9a 360
44855d8c
TS
361 tmp = fold_build2 (up ? PLUS_EXPR : MINUS_EXPR, type, intval,
362 build_int_cst (type, 1));
363 tmp = fold_build3 (COND_EXPR, type, cond, intval, tmp);
6de9cd9a
DN
364 return tmp;
365}
366
367
94f548c2 368/* Round to nearest integer, away from zero. */
6de9cd9a
DN
369
370static tree
94f548c2 371build_round_expr (tree arg, tree restype)
6de9cd9a 372{
6de9cd9a 373 tree argtype;
94f548c2 374 tree fn;
c833f6d2 375 bool longlong;
94f548c2 376 int argprec, resprec;
6de9cd9a
DN
377
378 argtype = TREE_TYPE (arg);
94f548c2
FXC
379 argprec = TYPE_PRECISION (argtype);
380 resprec = TYPE_PRECISION (restype);
6de9cd9a 381
94f548c2
FXC
382 /* Depending on the type of the result, choose the long int intrinsic
383 (lround family) or long long intrinsic (llround). We might also
384 need to convert the result afterwards. */
385 if (resprec <= LONG_TYPE_SIZE)
c833f6d2 386 longlong = false;
94f548c2 387 else if (resprec <= LONG_LONG_TYPE_SIZE)
c833f6d2 388 longlong = true;
94f548c2
FXC
389 else
390 gcc_unreachable ();
391
392 /* Now, depending on the argument type, we choose between intrinsics. */
2921157d
FXC
393 if (longlong)
394 fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
94f548c2 395 else
2921157d 396 fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
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:
44855d8c 426 return fold_build1 (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;
74687efe 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:
2921157d 465 decl = builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
6de9cd9a
DN
466 break;
467
f9f770a8 468 case RND_TRUNC:
2921157d 469 decl = 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);
44855d8c 498 cond = fold_build2 (LT_EXPR, boolean_type_node, arg[0], tmp);
6de9cd9a 499
f8e566e5 500 mpfr_neg (huge, huge, GFC_RND_MODE);
346a77d1 501 tmp = gfc_conv_mpfr_to_tree (huge, kind, 0);
44855d8c
TS
502 tmp = fold_build2 (GT_EXPR, boolean_type_node, arg[0], tmp);
503 cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond, tmp);
6de9cd9a
DN
504 itype = gfc_get_int_type (kind);
505
74687efe 506 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
6de9cd9a 507 tmp = convert (type, tmp);
44855d8c 508 se->expr = fold_build3 (COND_EXPR, type, cond, tmp, arg[0]);
f8e566e5 509 mpfr_clear (huge);
6de9cd9a
DN
510}
511
512
513/* Convert to an integer using the specified rounding mode. */
514
515static void
f9f770a8 516gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
6de9cd9a
DN
517{
518 tree type;
ffd82975
LM
519 tree *args;
520 int nargs;
6de9cd9a 521
ffd82975 522 nargs = gfc_intrinsic_argument_list_length (expr);
1145e690 523 args = XALLOCAVEC (tree, nargs);
ffd82975
LM
524
525 /* Evaluate the argument, we process all arguments even though we only
526 use the first one for code generation purposes. */
6de9cd9a 527 type = gfc_typenode_for_spec (&expr->ts);
6e45f57b 528 gcc_assert (expr->value.function.actual->expr);
ffd82975 529 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6de9cd9a 530
ffd82975 531 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
6de9cd9a
DN
532 {
533 /* Conversion to a different integer kind. */
ffd82975 534 se->expr = convert (type, args[0]);
6de9cd9a
DN
535 }
536 else
537 {
538 /* Conversion from complex to non-complex involves taking the real
539 component of the value. */
ffd82975 540 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
6de9cd9a
DN
541 && expr->ts.type != BT_COMPLEX)
542 {
543 tree artype;
544
ffd82975 545 artype = TREE_TYPE (TREE_TYPE (args[0]));
44855d8c 546 args[0] = fold_build1 (REALPART_EXPR, artype, args[0]);
6de9cd9a
DN
547 }
548
ffd82975 549 se->expr = build_fix_expr (&se->pre, args[0], type, op);
6de9cd9a
DN
550 }
551}
552
553
554/* Get the imaginary component of a value. */
555
556static void
557gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
558{
559 tree arg;
560
55637e51 561 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
44855d8c 562 se->expr = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
6de9cd9a
DN
563}
564
565
566/* Get the complex conjugate of a value. */
567
568static void
569gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
570{
571 tree arg;
572
55637e51 573 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
44855d8c 574 se->expr = fold_build1 (CONJ_EXPR, TREE_TYPE (arg), arg);
6de9cd9a
DN
575}
576
577
a3c85b74
FXC
578
579static tree
580define_quad_builtin (const char *name, tree type, bool is_const)
581{
582 tree fndecl;
583 fndecl = build_decl (input_location, FUNCTION_DECL, get_identifier (name),
584 type);
585
586 /* Mark the decl as external. */
587 DECL_EXTERNAL (fndecl) = 1;
588 TREE_PUBLIC (fndecl) = 1;
589
590 /* Mark it __attribute__((const)). */
591 TREE_READONLY (fndecl) = is_const;
592
593 rest_of_decl_compilation (fndecl, 1, 0);
594
595 return fndecl;
596}
597
598
599
6de9cd9a
DN
600/* Initialize function decls for library functions. The external functions
601 are created as required. Builtin functions are added here. */
602
603void
604gfc_build_intrinsic_lib_fndecls (void)
605{
606 gfc_intrinsic_map_t *m;
a3c85b74
FXC
607 tree quad_decls[(int) END_BUILTINS];
608
609 if (gfc_real16_is_float128)
610 {
611 /* If we have soft-float types, we create the decls for their
612 C99-like library functions. For now, we only handle __float128
613 q-suffixed functions. */
614
615 tree tmp, func_0, func_1, func_2, func_cabs, func_frexp;
616 tree func_lround, func_llround, func_scalbn;
617
618 memset (quad_decls, 0, sizeof(tree) * (int) END_BUILTINS);
619
620 /* type (*) (void) */
621 func_0 = build_function_type (float128_type_node, void_list_node);
622 /* type (*) (type) */
623 tmp = tree_cons (NULL_TREE, float128_type_node, void_list_node);
624 func_1 = build_function_type (float128_type_node, tmp);
625 /* long (*) (type) */
626 func_lround = build_function_type (long_integer_type_node, tmp);
627 /* long long (*) (type) */
628 func_llround = build_function_type (long_long_integer_type_node, tmp);
629 /* type (*) (type, type) */
630 tmp = tree_cons (NULL_TREE, float128_type_node, tmp);
631 func_2 = build_function_type (float128_type_node, tmp);
632 /* type (*) (type, &int) */
633 tmp = tree_cons (NULL_TREE, float128_type_node, void_list_node);
634 tmp = tree_cons (NULL_TREE, build_pointer_type (integer_type_node), tmp);
635 func_frexp = build_function_type (float128_type_node, tmp);
636 /* type (*) (type, int) */
637 tmp = tree_cons (NULL_TREE, float128_type_node, void_list_node);
638 tmp = tree_cons (NULL_TREE, integer_type_node, tmp);
639 func_scalbn = build_function_type (float128_type_node, tmp);
640 /* type (*) (complex type) */
641 tmp = tree_cons (NULL_TREE, complex_float128_type_node, void_list_node);
642 func_cabs = build_function_type (float128_type_node, tmp);
643
644#define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
645#define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
646#define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
647
648 /* Only these built-ins are actually needed here. These are used directly
649 from the code, when calling builtin_decl_for_precision() or
650 builtin_decl_for_float_type(). The others are all constructed by
651 gfc_get_intrinsic_lib_fndecl(). */
652#define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
653 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
654
655#include "mathbuiltins.def"
656
657#undef OTHER_BUILTIN
658#undef LIB_FUNCTION
659#undef DEFINE_MATH_BUILTIN
660#undef DEFINE_MATH_BUILTIN_C
661
662 }
6de9cd9a
DN
663
664 /* Add GCC builtin functions. */
2921157d
FXC
665 for (m = gfc_intrinsic_map;
666 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
667 {
668 if (m->float_built_in != END_BUILTINS)
669 m->real4_decl = built_in_decls[m->float_built_in];
670 if (m->complex_float_built_in != END_BUILTINS)
671 m->complex4_decl = built_in_decls[m->complex_float_built_in];
672 if (m->double_built_in != END_BUILTINS)
673 m->real8_decl = built_in_decls[m->double_built_in];
674 if (m->complex_double_built_in != END_BUILTINS)
675 m->complex8_decl = built_in_decls[m->complex_double_built_in];
676
677 /* If real(kind=10) exists, it is always long double. */
678 if (m->long_double_built_in != END_BUILTINS)
679 m->real10_decl = built_in_decls[m->long_double_built_in];
680 if (m->complex_long_double_built_in != END_BUILTINS)
681 m->complex10_decl = built_in_decls[m->complex_long_double_built_in];
682
a3c85b74
FXC
683 if (!gfc_real16_is_float128)
684 {
685 if (m->long_double_built_in != END_BUILTINS)
686 m->real16_decl = built_in_decls[m->long_double_built_in];
687 if (m->complex_long_double_built_in != END_BUILTINS)
688 m->complex16_decl = built_in_decls[m->complex_long_double_built_in];
689 }
690 else if (quad_decls[m->double_built_in] != NULL_TREE)
691 {
692 /* Quad-precision function calls are constructed when first
693 needed by builtin_decl_for_precision(), except for those
694 that will be used directly (define by OTHER_BUILTIN). */
695 m->real16_decl = quad_decls[m->double_built_in];
696 }
697 else if (quad_decls[m->complex_double_built_in] != NULL_TREE)
698 {
699 /* Same thing for the complex ones. */
700 m->complex16_decl = quad_decls[m->double_built_in];
701 m->real16_decl = quad_decls[m->double_built_in];
702 }
6de9cd9a
DN
703 }
704}
705
706
707/* Create a fndecl for a simple intrinsic library function. */
708
709static tree
710gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
711{
712 tree type;
713 tree argtypes;
714 tree fndecl;
715 gfc_actual_arglist *actual;
716 tree *pdecl;
717 gfc_typespec *ts;
718 char name[GFC_MAX_SYMBOL_LEN + 3];
719
720 ts = &expr->ts;
721 if (ts->type == BT_REAL)
722 {
723 switch (ts->kind)
724 {
725 case 4:
726 pdecl = &m->real4_decl;
727 break;
728 case 8:
729 pdecl = &m->real8_decl;
730 break;
644cb69f
FXC
731 case 10:
732 pdecl = &m->real10_decl;
733 break;
734 case 16:
735 pdecl = &m->real16_decl;
736 break;
6de9cd9a 737 default:
6e45f57b 738 gcc_unreachable ();
6de9cd9a
DN
739 }
740 }
741 else if (ts->type == BT_COMPLEX)
742 {
6e45f57b 743 gcc_assert (m->complex_available);
6de9cd9a
DN
744
745 switch (ts->kind)
746 {
747 case 4:
748 pdecl = &m->complex4_decl;
749 break;
750 case 8:
751 pdecl = &m->complex8_decl;
752 break;
644cb69f
FXC
753 case 10:
754 pdecl = &m->complex10_decl;
755 break;
756 case 16:
757 pdecl = &m->complex16_decl;
758 break;
6de9cd9a 759 default:
6e45f57b 760 gcc_unreachable ();
6de9cd9a
DN
761 }
762 }
763 else
6e45f57b 764 gcc_unreachable ();
6de9cd9a
DN
765
766 if (*pdecl)
767 return *pdecl;
768
769 if (m->libm_name)
770 {
2921157d
FXC
771 int n = gfc_validate_kind (BT_REAL, ts->kind, false);
772 if (gfc_real_kinds[n].c_float)
e48d66a9 773 snprintf (name, sizeof (name), "%s%s%s",
2921157d
FXC
774 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
775 else if (gfc_real_kinds[n].c_double)
e48d66a9 776 snprintf (name, sizeof (name), "%s%s",
2921157d
FXC
777 ts->type == BT_COMPLEX ? "c" : "", m->name);
778 else if (gfc_real_kinds[n].c_long_double)
779 snprintf (name, sizeof (name), "%s%s%s",
780 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
a3c85b74
FXC
781 else if (gfc_real_kinds[n].c_float128)
782 snprintf (name, sizeof (name), "%s%s%s",
783 ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
e48d66a9 784 else
2921157d 785 gcc_unreachable ();
6de9cd9a
DN
786 }
787 else
788 {
789 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
790 ts->type == BT_COMPLEX ? 'c' : 'r',
791 ts->kind);
792 }
793
794 argtypes = NULL_TREE;
795 for (actual = expr->value.function.actual; actual; actual = actual->next)
796 {
797 type = gfc_typenode_for_spec (&actual->expr->ts);
798 argtypes = gfc_chainon_list (argtypes, type);
799 }
35d3d688 800 argtypes = chainon (argtypes, void_list_node);
6de9cd9a 801 type = build_function_type (gfc_typenode_for_spec (ts), argtypes);
c2255bc4
AH
802 fndecl = build_decl (input_location,
803 FUNCTION_DECL, get_identifier (name), type);
6de9cd9a
DN
804
805 /* Mark the decl as external. */
806 DECL_EXTERNAL (fndecl) = 1;
807 TREE_PUBLIC (fndecl) = 1;
808
809 /* Mark it __attribute__((const)), if possible. */
810 TREE_READONLY (fndecl) = m->is_constant;
811
0e6df31e 812 rest_of_decl_compilation (fndecl, 1, 0);
6de9cd9a
DN
813
814 (*pdecl) = fndecl;
815 return fndecl;
816}
817
818
819/* Convert an intrinsic function into an external or builtin call. */
820
821static void
822gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
823{
824 gfc_intrinsic_map_t *m;
6de9cd9a 825 tree fndecl;
55637e51
LM
826 tree rettype;
827 tree *args;
828 unsigned int num_args;
cd5ecab6 829 gfc_isym_id id;
6de9cd9a 830
cd5ecab6 831 id = expr->value.function.isym->id;
6de9cd9a 832 /* Find the entry for this function. */
2921157d
FXC
833 for (m = gfc_intrinsic_map;
834 m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
6de9cd9a
DN
835 {
836 if (id == m->id)
837 break;
838 }
839
840 if (m->id == GFC_ISYM_NONE)
841 {
842 internal_error ("Intrinsic function %s(%d) not recognized",
843 expr->value.function.name, id);
844 }
845
846 /* Get the decl and generate the call. */
55637e51 847 num_args = gfc_intrinsic_argument_list_length (expr);
1145e690 848 args = XALLOCAVEC (tree, num_args);
55637e51
LM
849
850 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6de9cd9a 851 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
55637e51
LM
852 rettype = TREE_TYPE (TREE_TYPE (fndecl));
853
854 fndecl = build_addr (fndecl, current_function_decl);
db3927fb 855 se->expr = build_call_array_loc (input_location, rettype, fndecl, num_args, args);
6de9cd9a
DN
856}
857
8c13133c
DK
858
859/* If bounds-checking is enabled, create code to verify at runtime that the
860 string lengths for both expressions are the same (needed for e.g. MERGE).
861 If bounds-checking is not enabled, does nothing. */
862
fb5bc08b
DK
863void
864gfc_trans_same_strlen_check (const char* intr_name, locus* where,
865 tree a, tree b, stmtblock_t* target)
8c13133c
DK
866{
867 tree cond;
868 tree name;
869
870 /* If bounds-checking is disabled, do nothing. */
d3d3011f 871 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
8c13133c
DK
872 return;
873
874 /* Compare the two string lengths. */
875 cond = fold_build2 (NE_EXPR, boolean_type_node, a, b);
876
877 /* Output the runtime-check. */
878 name = gfc_build_cstring_const (intr_name);
879 name = gfc_build_addr_expr (pchar_type_node, name);
880 gfc_trans_runtime_check (true, false, cond, target, where,
fb5bc08b 881 "Unequal character lengths (%ld/%ld) in %s",
8c13133c
DK
882 fold_convert (long_integer_type_node, a),
883 fold_convert (long_integer_type_node, b), name);
884}
885
886
b5a4419c
FXC
887/* The EXPONENT(s) intrinsic function is translated into
888 int ret;
889 frexp (s, &ret);
890 return ret;
891 */
6de9cd9a
DN
892
893static void
14b1261a 894gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
6de9cd9a 895{
2921157d 896 tree arg, type, res, tmp, frexp;
6de9cd9a 897
2921157d
FXC
898 frexp = builtin_decl_for_float_kind (BUILT_IN_FREXP,
899 expr->value.function.actual->expr->ts.kind);
6de9cd9a 900
b5a4419c
FXC
901 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
902
903 res = gfc_create_var (integer_type_node, NULL);
2921157d
FXC
904 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
905 gfc_build_addr_expr (NULL_TREE, res));
b5a4419c
FXC
906 gfc_add_expr_to_block (&se->pre, tmp);
907
14b1261a 908 type = gfc_typenode_for_spec (&expr->ts);
b5a4419c 909 se->expr = fold_convert (type, res);
6de9cd9a
DN
910}
911
912/* Evaluate a single upper or lower bound. */
1f2959f0 913/* TODO: bound intrinsic generates way too much unnecessary code. */
6de9cd9a
DN
914
915static void
916gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
917{
918 gfc_actual_arglist *arg;
919 gfc_actual_arglist *arg2;
920 tree desc;
921 tree type;
922 tree bound;
923 tree tmp;
c4fae39e 924 tree cond, cond1, cond3, cond4, size;
ac677cc8
FXC
925 tree ubound;
926 tree lbound;
6de9cd9a
DN
927 gfc_se argse;
928 gfc_ss *ss;
ac677cc8 929 gfc_array_spec * as;
6de9cd9a 930
6de9cd9a
DN
931 arg = expr->value.function.actual;
932 arg2 = arg->next;
933
934 if (se->ss)
935 {
936 /* Create an implicit second parameter from the loop variable. */
6e45f57b
PB
937 gcc_assert (!arg2->expr);
938 gcc_assert (se->loop->dimen == 1);
939 gcc_assert (se->ss->expr == expr);
6de9cd9a
DN
940 gfc_advance_se_ss_chain (se);
941 bound = se->loop->loopvar[0];
10c7a96f
SB
942 bound = fold_build2 (MINUS_EXPR, gfc_array_index_type, bound,
943 se->loop->from[0]);
6de9cd9a
DN
944 }
945 else
946 {
947 /* use the passed argument. */
6e45f57b 948 gcc_assert (arg->next->expr);
6de9cd9a
DN
949 gfc_init_se (&argse, NULL);
950 gfc_conv_expr_type (&argse, arg->next->expr, gfc_array_index_type);
951 gfc_add_block_to_block (&se->pre, &argse.pre);
952 bound = argse.expr;
953 /* Convert from one based to zero based. */
10c7a96f
SB
954 bound = fold_build2 (MINUS_EXPR, gfc_array_index_type, bound,
955 gfc_index_one_node);
6de9cd9a
DN
956 }
957
958 /* TODO: don't re-evaluate the descriptor on each iteration. */
959 /* Get a descriptor for the first parameter. */
960 ss = gfc_walk_expr (arg->expr);
6e45f57b 961 gcc_assert (ss != gfc_ss_terminator);
4fd9a813 962 gfc_init_se (&argse, NULL);
6de9cd9a
DN
963 gfc_conv_expr_descriptor (&argse, arg->expr, ss);
964 gfc_add_block_to_block (&se->pre, &argse.pre);
965 gfc_add_block_to_block (&se->post, &argse.post);
966
967 desc = argse.expr;
968
969 if (INTEGER_CST_P (bound))
970 {
9f1dce56
FXC
971 int hi, low;
972
973 hi = TREE_INT_CST_HIGH (bound);
974 low = TREE_INT_CST_LOW (bound);
975 if (hi || low < 0 || low >= GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)))
976 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
977 "dimension index", upper ? "UBOUND" : "LBOUND",
978 &expr->where);
6de9cd9a
DN
979 }
980 else
981 {
d3d3011f 982 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
6de9cd9a
DN
983 {
984 bound = gfc_evaluate_now (bound, &se->pre);
10c7a96f
SB
985 cond = fold_build2 (LT_EXPR, boolean_type_node,
986 bound, build_int_cst (TREE_TYPE (bound), 0));
6de9cd9a 987 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
10c7a96f
SB
988 tmp = fold_build2 (GE_EXPR, boolean_type_node, bound, tmp);
989 cond = fold_build2 (TRUTH_ORIF_EXPR, boolean_type_node, cond, tmp);
0d52899f
TB
990 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
991 gfc_msg_fault);
6de9cd9a
DN
992 }
993 }
994
568e8e1e
PT
995 ubound = gfc_conv_descriptor_ubound_get (desc, bound);
996 lbound = gfc_conv_descriptor_lbound_get (desc, bound);
ac677cc8 997
b7d1d8b4 998 as = gfc_get_full_arrayspec_from_expr (arg->expr);
ac677cc8
FXC
999
1000 /* 13.14.53: Result value for LBOUND
1001
1002 Case (i): For an array section or for an array expression other than a
1003 whole array or array structure component, LBOUND(ARRAY, DIM)
1004 has the value 1. For a whole array or array structure
1005 component, LBOUND(ARRAY, DIM) has the value:
1006 (a) equal to the lower bound for subscript DIM of ARRAY if
1007 dimension DIM of ARRAY does not have extent zero
1008 or if ARRAY is an assumed-size array of rank DIM,
1009 or (b) 1 otherwise.
1010
1011 13.14.113: Result value for UBOUND
1012
1013 Case (i): For an array section or for an array expression other than a
1014 whole array or array structure component, UBOUND(ARRAY, DIM)
1015 has the value equal to the number of elements in the given
1016 dimension; otherwise, it has a value equal to the upper bound
1017 for subscript DIM of ARRAY if dimension DIM of ARRAY does
1018 not have size zero and has value zero if dimension DIM has
1019 size zero. */
1020
1021 if (as)
1022 {
568e8e1e 1023 tree stride = gfc_conv_descriptor_stride_get (desc, bound);
9f1dce56 1024
ac677cc8 1025 cond1 = fold_build2 (GE_EXPR, boolean_type_node, ubound, lbound);
9f1dce56
FXC
1026
1027 cond3 = fold_build2 (GE_EXPR, boolean_type_node, stride,
ac677cc8 1028 gfc_index_zero_node);
9f1dce56
FXC
1029 cond3 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond3, cond1);
1030
1031 cond4 = fold_build2 (LT_EXPR, boolean_type_node, stride,
1032 gfc_index_zero_node);
ac677cc8
FXC
1033
1034 if (upper)
1035 {
61a39615 1036 tree cond5;
9f1dce56 1037 cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond3, cond4);
ac677cc8 1038
61a39615
PT
1039 cond5 = fold_build2 (EQ_EXPR, boolean_type_node, gfc_index_one_node, lbound);
1040 cond5 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond4, cond5);
1041
1042 cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond, cond5);
1043
ac677cc8
FXC
1044 se->expr = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
1045 ubound, gfc_index_zero_node);
1046 }
1047 else
1048 {
1049 if (as->type == AS_ASSUMED_SIZE)
1050 cond = fold_build2 (EQ_EXPR, boolean_type_node, bound,
1051 build_int_cst (TREE_TYPE (bound),
9f1dce56 1052 arg->expr->rank - 1));
ac677cc8
FXC
1053 else
1054 cond = boolean_false_node;
1055
9f1dce56 1056 cond1 = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond3, cond4);
ac677cc8
FXC
1057 cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond, cond1);
1058
1059 se->expr = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
1060 lbound, gfc_index_one_node);
1061 }
1062 }
1063 else
1064 {
1065 if (upper)
1066 {
1067 size = fold_build2 (MINUS_EXPR, gfc_array_index_type, ubound, lbound);
1068 se->expr = fold_build2 (PLUS_EXPR, gfc_array_index_type, size,
1069 gfc_index_one_node);
f10827b1
FXC
1070 se->expr = fold_build2 (MAX_EXPR, gfc_array_index_type, se->expr,
1071 gfc_index_zero_node);
ac677cc8
FXC
1072 }
1073 else
1074 se->expr = gfc_index_one_node;
1075 }
6de9cd9a
DN
1076
1077 type = gfc_typenode_for_spec (&expr->ts);
1078 se->expr = convert (type, se->expr);
1079}
1080
1081
1082static void
1083gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
1084{
2921157d 1085 tree arg, cabs;
6de9cd9a 1086
55637e51 1087 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
6de9cd9a
DN
1088
1089 switch (expr->value.function.actual->expr->ts.type)
1090 {
1091 case BT_INTEGER:
1092 case BT_REAL:
44855d8c 1093 se->expr = fold_build1 (ABS_EXPR, TREE_TYPE (arg), arg);
6de9cd9a
DN
1094 break;
1095
1096 case BT_COMPLEX:
2921157d
FXC
1097 cabs = builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
1098 se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
6de9cd9a
DN
1099 break;
1100
1101 default:
6e45f57b 1102 gcc_unreachable ();
6de9cd9a
DN
1103 }
1104}
1105
1106
1107/* Create a complex value from one or two real components. */
1108
1109static void
1110gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
1111{
6de9cd9a
DN
1112 tree real;
1113 tree imag;
1114 tree type;
55637e51
LM
1115 tree *args;
1116 unsigned int num_args;
1117
1118 num_args = gfc_intrinsic_argument_list_length (expr);
1145e690 1119 args = XALLOCAVEC (tree, num_args);
6de9cd9a
DN
1120
1121 type = gfc_typenode_for_spec (&expr->ts);
55637e51
LM
1122 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
1123 real = convert (TREE_TYPE (type), args[0]);
6de9cd9a 1124 if (both)
55637e51
LM
1125 imag = convert (TREE_TYPE (type), args[1]);
1126 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
6de9cd9a 1127 {
44855d8c
TS
1128 imag = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (args[0])),
1129 args[0]);
6de9cd9a
DN
1130 imag = convert (TREE_TYPE (type), imag);
1131 }
1132 else
1133 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
1134
10c7a96f 1135 se->expr = fold_build2 (COMPLEX_EXPR, type, real, imag);
6de9cd9a
DN
1136}
1137
e98a8b5b
TS
1138/* Remainder function MOD(A, P) = A - INT(A / P) * P
1139 MODULO(A, P) = A - FLOOR (A / P) * P */
6de9cd9a
DN
1140/* TODO: MOD(x, 0) */
1141
1142static void
1143gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
1144{
6de9cd9a
DN
1145 tree type;
1146 tree itype;
1147 tree tmp;
6de9cd9a
DN
1148 tree test;
1149 tree test2;
2921157d 1150 tree fmod;
f8e566e5 1151 mpfr_t huge;
3e7cb1c7 1152 int n, ikind;
55637e51 1153 tree args[2];
6de9cd9a 1154
55637e51 1155 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6de9cd9a
DN
1156
1157 switch (expr->ts.type)
1158 {
1159 case BT_INTEGER:
1160 /* Integer case is easy, we've got a builtin op. */
55637e51 1161 type = TREE_TYPE (args[0]);
58b6e047 1162
e98a8b5b 1163 if (modulo)
44855d8c 1164 se->expr = fold_build2 (FLOOR_MOD_EXPR, type, args[0], args[1]);
e98a8b5b 1165 else
44855d8c 1166 se->expr = fold_build2 (TRUNC_MOD_EXPR, type, args[0], args[1]);
6de9cd9a
DN
1167 break;
1168
1169 case BT_REAL:
2921157d 1170 fmod = NULL_TREE;
58b6e047 1171 /* Check if we have a builtin fmod. */
2921157d 1172 fmod = builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
58b6e047
PT
1173
1174 /* Use it if it exists. */
2921157d 1175 if (fmod != NULL_TREE)
58b6e047 1176 {
2921157d 1177 tmp = build_addr (fmod, current_function_decl);
db3927fb 1178 se->expr = build_call_array_loc (input_location,
2921157d 1179 TREE_TYPE (TREE_TYPE (fmod)),
55637e51 1180 tmp, 2, args);
58b6e047
PT
1181 if (modulo == 0)
1182 return;
1183 }
1184
55637e51 1185 type = TREE_TYPE (args[0]);
58b6e047 1186
55637e51
LM
1187 args[0] = gfc_evaluate_now (args[0], &se->pre);
1188 args[1] = gfc_evaluate_now (args[1], &se->pre);
6de9cd9a 1189
58b6e047
PT
1190 /* Definition:
1191 modulo = arg - floor (arg/arg2) * arg2, so
1192 = test ? fmod (arg, arg2) : fmod (arg, arg2) + arg2,
1193 where
1194 test = (fmod (arg, arg2) != 0) && ((arg < 0) xor (arg2 < 0))
1195 thereby avoiding another division and retaining the accuracy
1196 of the builtin function. */
2921157d 1197 if (fmod != NULL_TREE && modulo)
58b6e047
PT
1198 {
1199 tree zero = gfc_build_const (type, integer_zero_node);
1200 tmp = gfc_evaluate_now (se->expr, &se->pre);
44855d8c
TS
1201 test = fold_build2 (LT_EXPR, boolean_type_node, args[0], zero);
1202 test2 = fold_build2 (LT_EXPR, boolean_type_node, args[1], zero);
1203 test2 = fold_build2 (TRUTH_XOR_EXPR, boolean_type_node, test, test2);
1204 test = fold_build2 (NE_EXPR, boolean_type_node, tmp, zero);
1205 test = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, test, test2);
58b6e047 1206 test = gfc_evaluate_now (test, &se->pre);
44855d8c
TS
1207 se->expr = fold_build3 (COND_EXPR, type, test,
1208 fold_build2 (PLUS_EXPR, type, tmp, args[1]),
1209 tmp);
58b6e047
PT
1210 return;
1211 }
1212
1213 /* If we do not have a built_in fmod, the calculation is going to
1214 have to be done longhand. */
44855d8c 1215 tmp = fold_build2 (RDIV_EXPR, type, args[0], args[1]);
58b6e047 1216
6de9cd9a 1217 /* Test if the value is too large to handle sensibly. */
f8e566e5
SK
1218 gfc_set_model_kind (expr->ts.kind);
1219 mpfr_init (huge);
3e7cb1c7
FXC
1220 n = gfc_validate_kind (BT_INTEGER, expr->ts.kind, true);
1221 ikind = expr->ts.kind;
1222 if (n < 0)
1223 {
1224 n = gfc_validate_kind (BT_INTEGER, gfc_max_integer_kind, false);
1225 ikind = gfc_max_integer_kind;
1226 }
f8e566e5 1227 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
346a77d1 1228 test = gfc_conv_mpfr_to_tree (huge, expr->ts.kind, 0);
44855d8c 1229 test2 = fold_build2 (LT_EXPR, boolean_type_node, tmp, test);
6de9cd9a 1230
f8e566e5 1231 mpfr_neg (huge, huge, GFC_RND_MODE);
346a77d1 1232 test = gfc_conv_mpfr_to_tree (huge, expr->ts.kind, 0);
44855d8c
TS
1233 test = fold_build2 (GT_EXPR, boolean_type_node, tmp, test);
1234 test2 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, test, test2);
6de9cd9a 1235
3e7cb1c7 1236 itype = gfc_get_int_type (ikind);
e98a8b5b 1237 if (modulo)
f9f770a8 1238 tmp = build_fix_expr (&se->pre, tmp, itype, RND_FLOOR);
e98a8b5b 1239 else
f9f770a8 1240 tmp = build_fix_expr (&se->pre, tmp, itype, RND_TRUNC);
6de9cd9a 1241 tmp = convert (type, tmp);
44855d8c
TS
1242 tmp = fold_build3 (COND_EXPR, type, test2, tmp, args[0]);
1243 tmp = fold_build2 (MULT_EXPR, type, tmp, args[1]);
1244 se->expr = fold_build2 (MINUS_EXPR, type, args[0], tmp);
f8e566e5 1245 mpfr_clear (huge);
6de9cd9a
DN
1246 break;
1247
1248 default:
6e45f57b 1249 gcc_unreachable ();
6de9cd9a 1250 }
6de9cd9a
DN
1251}
1252
1253/* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
1254
1255static void
1256gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
1257{
6de9cd9a
DN
1258 tree val;
1259 tree tmp;
1260 tree type;
1261 tree zero;
55637e51 1262 tree args[2];
6de9cd9a 1263
55637e51
LM
1264 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1265 type = TREE_TYPE (args[0]);
6de9cd9a 1266
44855d8c 1267 val = fold_build2 (MINUS_EXPR, type, args[0], args[1]);
6de9cd9a
DN
1268 val = gfc_evaluate_now (val, &se->pre);
1269
1270 zero = gfc_build_const (type, integer_zero_node);
44855d8c
TS
1271 tmp = fold_build2 (LE_EXPR, boolean_type_node, val, zero);
1272 se->expr = fold_build3 (COND_EXPR, type, tmp, zero, val);
6de9cd9a
DN
1273}
1274
1275
1276/* SIGN(A, B) is absolute value of A times sign of B.
1277 The real value versions use library functions to ensure the correct
1278 handling of negative zero. Integer case implemented as:
0eadc091 1279 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
6de9cd9a
DN
1280 */
1281
1282static void
1283gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
1284{
1285 tree tmp;
6de9cd9a 1286 tree type;
55637e51 1287 tree args[2];
6de9cd9a 1288
55637e51 1289 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6de9cd9a
DN
1290 if (expr->ts.type == BT_REAL)
1291 {
60d340ef
TB
1292 tree abs;
1293
2921157d
FXC
1294 tmp = builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
1295 abs = builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
60d340ef
TB
1296
1297 /* We explicitly have to ignore the minus sign. We do so by using
1298 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
1299 if (!gfc_option.flag_sign_zero
1300 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1]))))
1301 {
1302 tree cond, zero;
1303 zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node);
1304 cond = fold_build2 (EQ_EXPR, boolean_type_node, args[1], zero);
1305 se->expr = fold_build3 (COND_EXPR, TREE_TYPE (args[0]), cond,
1306 build_call_expr (abs, 1, args[0]),
1307 build_call_expr (tmp, 2, args[0], args[1]));
1308 }
1309 else
2921157d
FXC
1310 se->expr = build_call_expr_loc (input_location, tmp, 2,
1311 args[0], args[1]);
6de9cd9a
DN
1312 return;
1313 }
1314
0eadc091
RS
1315 /* Having excluded floating point types, we know we are now dealing
1316 with signed integer types. */
55637e51 1317 type = TREE_TYPE (args[0]);
6de9cd9a 1318
55637e51
LM
1319 /* Args[0] is used multiple times below. */
1320 args[0] = gfc_evaluate_now (args[0], &se->pre);
0eadc091
RS
1321
1322 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
1323 the signs of A and B are the same, and of all ones if they differ. */
55637e51 1324 tmp = fold_build2 (BIT_XOR_EXPR, type, args[0], args[1]);
0eadc091
RS
1325 tmp = fold_build2 (RSHIFT_EXPR, type, tmp,
1326 build_int_cst (type, TYPE_PRECISION (type) - 1));
1327 tmp = gfc_evaluate_now (tmp, &se->pre);
1328
1329 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
1330 is all ones (i.e. -1). */
1331 se->expr = fold_build2 (BIT_XOR_EXPR, type,
55637e51 1332 fold_build2 (PLUS_EXPR, type, args[0], tmp),
0eadc091 1333 tmp);
6de9cd9a
DN
1334}
1335
1336
1337/* Test for the presence of an optional argument. */
1338
1339static void
1340gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
1341{
1342 gfc_expr *arg;
1343
1344 arg = expr->value.function.actual->expr;
6e45f57b 1345 gcc_assert (arg->expr_type == EXPR_VARIABLE);
6de9cd9a
DN
1346 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
1347 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
1348}
1349
1350
1351/* Calculate the double precision product of two single precision values. */
1352
1353static void
1354gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
1355{
6de9cd9a 1356 tree type;
55637e51 1357 tree args[2];
6de9cd9a 1358
55637e51 1359 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6de9cd9a
DN
1360
1361 /* Convert the args to double precision before multiplying. */
1362 type = gfc_typenode_for_spec (&expr->ts);
55637e51
LM
1363 args[0] = convert (type, args[0]);
1364 args[1] = convert (type, args[1]);
44855d8c 1365 se->expr = fold_build2 (MULT_EXPR, type, args[0], args[1]);
6de9cd9a
DN
1366}
1367
1368
1369/* Return a length one character string containing an ascii character. */
1370
1371static void
1372gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
1373{
c2408681 1374 tree arg[2];
6de9cd9a
DN
1375 tree var;
1376 tree type;
c2408681 1377 unsigned int num_args;
6de9cd9a 1378
c2408681
PT
1379 num_args = gfc_intrinsic_argument_list_length (expr);
1380 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
6de9cd9a 1381
d393bbd7 1382 type = gfc_get_char_type (expr->ts.kind);
6de9cd9a
DN
1383 var = gfc_create_var (type, "char");
1384
d393bbd7 1385 arg[0] = fold_build1 (NOP_EXPR, type, arg[0]);
726a989a 1386 gfc_add_modify (&se->pre, var, arg[0]);
6de9cd9a
DN
1387 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
1388 se->string_length = integer_one_node;
1389}
1390
1391
35059811
FXC
1392static void
1393gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
1394{
1395 tree var;
1396 tree len;
1397 tree tmp;
35059811 1398 tree cond;
55637e51
LM
1399 tree fndecl;
1400 tree *args;
1401 unsigned int num_args;
1402
1403 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1145e690 1404 args = XALLOCAVEC (tree, num_args);
35059811 1405
691da334
FXC
1406 var = gfc_create_var (pchar_type_node, "pstr");
1407 len = gfc_create_var (gfc_get_int_type (8), "len");
35059811 1408
55637e51 1409 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
628c189e
RG
1410 args[0] = gfc_build_addr_expr (NULL_TREE, var);
1411 args[1] = gfc_build_addr_expr (NULL_TREE, len);
35059811 1412
55637e51 1413 fndecl = build_addr (gfor_fndecl_ctime, current_function_decl);
db3927fb
AH
1414 tmp = build_call_array_loc (input_location,
1415 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
55637e51 1416 fndecl, num_args, args);
35059811
FXC
1417 gfc_add_expr_to_block (&se->pre, tmp);
1418
1419 /* Free the temporary afterwards, if necessary. */
44855d8c
TS
1420 cond = fold_build2 (GT_EXPR, boolean_type_node,
1421 len, build_int_cst (TREE_TYPE (len), 0));
1529b8d9 1422 tmp = gfc_call_free (var);
c2255bc4 1423 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
35059811
FXC
1424 gfc_add_expr_to_block (&se->post, tmp);
1425
1426 se->expr = var;
1427 se->string_length = len;
1428}
1429
1430
1431static void
1432gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
1433{
1434 tree var;
1435 tree len;
1436 tree tmp;
35059811 1437 tree cond;
55637e51
LM
1438 tree fndecl;
1439 tree *args;
1440 unsigned int num_args;
1441
1442 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1145e690 1443 args = XALLOCAVEC (tree, num_args);
35059811 1444
691da334 1445 var = gfc_create_var (pchar_type_node, "pstr");
6cd8d93a 1446 len = gfc_create_var (gfc_charlen_type_node, "len");
35059811 1447
55637e51 1448 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
628c189e
RG
1449 args[0] = gfc_build_addr_expr (NULL_TREE, var);
1450 args[1] = gfc_build_addr_expr (NULL_TREE, len);
35059811 1451
55637e51 1452 fndecl = build_addr (gfor_fndecl_fdate, current_function_decl);
db3927fb
AH
1453 tmp = build_call_array_loc (input_location,
1454 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
55637e51 1455 fndecl, num_args, args);
35059811
FXC
1456 gfc_add_expr_to_block (&se->pre, tmp);
1457
1458 /* Free the temporary afterwards, if necessary. */
44855d8c
TS
1459 cond = fold_build2 (GT_EXPR, boolean_type_node,
1460 len, build_int_cst (TREE_TYPE (len), 0));
1529b8d9 1461 tmp = gfc_call_free (var);
c2255bc4 1462 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
35059811
FXC
1463 gfc_add_expr_to_block (&se->post, tmp);
1464
1465 se->expr = var;
1466 se->string_length = len;
1467}
1468
1469
25fc05eb
FXC
1470/* Return a character string containing the tty name. */
1471
1472static void
1473gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
1474{
1475 tree var;
1476 tree len;
1477 tree tmp;
25fc05eb 1478 tree cond;
55637e51 1479 tree fndecl;
55637e51
LM
1480 tree *args;
1481 unsigned int num_args;
1482
1483 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1145e690 1484 args = XALLOCAVEC (tree, num_args);
25fc05eb 1485
691da334 1486 var = gfc_create_var (pchar_type_node, "pstr");
6cd8d93a 1487 len = gfc_create_var (gfc_charlen_type_node, "len");
25fc05eb 1488
55637e51 1489 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
628c189e
RG
1490 args[0] = gfc_build_addr_expr (NULL_TREE, var);
1491 args[1] = gfc_build_addr_expr (NULL_TREE, len);
25fc05eb 1492
55637e51 1493 fndecl = build_addr (gfor_fndecl_ttynam, current_function_decl);
db3927fb
AH
1494 tmp = build_call_array_loc (input_location,
1495 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
55637e51 1496 fndecl, num_args, args);
25fc05eb
FXC
1497 gfc_add_expr_to_block (&se->pre, tmp);
1498
1499 /* Free the temporary afterwards, if necessary. */
44855d8c
TS
1500 cond = fold_build2 (GT_EXPR, boolean_type_node,
1501 len, build_int_cst (TREE_TYPE (len), 0));
1529b8d9 1502 tmp = gfc_call_free (var);
c2255bc4 1503 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
25fc05eb
FXC
1504 gfc_add_expr_to_block (&se->post, tmp);
1505
1506 se->expr = var;
1507 se->string_length = len;
1508}
1509
1510
6de9cd9a
DN
1511/* Get the minimum/maximum value of all the parameters.
1512 minmax (a1, a2, a3, ...)
1513 {
7af6648c
FXC
1514 mvar = a1;
1515 if (a2 .op. mvar || isnan(mvar))
6de9cd9a 1516 mvar = a2;
5fcb93f1 1517 if (a3 .op. mvar || isnan(mvar))
6de9cd9a
DN
1518 mvar = a3;
1519 ...
1520 return mvar
1521 }
1522 */
1523
1524/* TODO: Mismatching types can occur when specific names are used.
1525 These should be handled during resolution. */
1526static void
8fa2df72 1527gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
6de9cd9a 1528{
6de9cd9a
DN
1529 tree tmp;
1530 tree mvar;
1531 tree val;
1532 tree thencase;
55637e51 1533 tree *args;
6de9cd9a 1534 tree type;
0160a2c7 1535 gfc_actual_arglist *argexpr;
7af6648c 1536 unsigned int i, nargs;
6de9cd9a 1537
55637e51 1538 nargs = gfc_intrinsic_argument_list_length (expr);
1145e690 1539 args = XALLOCAVEC (tree, nargs);
55637e51
LM
1540
1541 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
6de9cd9a
DN
1542 type = gfc_typenode_for_spec (&expr->ts);
1543
0160a2c7 1544 argexpr = expr->value.function.actual;
7af6648c
FXC
1545 if (TREE_TYPE (args[0]) != type)
1546 args[0] = convert (type, args[0]);
6de9cd9a 1547 /* Only evaluate the argument once. */
7af6648c
FXC
1548 if (TREE_CODE (args[0]) != VAR_DECL && !TREE_CONSTANT (args[0]))
1549 args[0] = gfc_evaluate_now (args[0], &se->pre);
6de9cd9a
DN
1550
1551 mvar = gfc_create_var (type, "M");
726a989a 1552 gfc_add_modify (&se->pre, mvar, args[0]);
55637e51 1553 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
6de9cd9a 1554 {
5fcb93f1 1555 tree cond, isnan;
0160a2c7 1556
55637e51 1557 val = args[i];
6de9cd9a 1558
0160a2c7 1559 /* Handle absent optional arguments by ignoring the comparison. */
7af6648c 1560 if (argexpr->expr->expr_type == EXPR_VARIABLE
0160a2c7
FXC
1561 && argexpr->expr->symtree->n.sym->attr.optional
1562 && TREE_CODE (val) == INDIRECT_REF)
db3927fb
AH
1563 cond = fold_build2_loc (input_location,
1564 NE_EXPR, boolean_type_node,
1565 TREE_OPERAND (val, 0),
1566 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
0160a2c7
FXC
1567 else
1568 {
1569 cond = NULL_TREE;
1570
1571 /* Only evaluate the argument once. */
1572 if (TREE_CODE (val) != VAR_DECL && !TREE_CONSTANT (val))
1573 val = gfc_evaluate_now (val, &se->pre);
1574 }
6de9cd9a 1575
923ab88c 1576 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
6de9cd9a 1577
44855d8c 1578 tmp = fold_build2 (op, boolean_type_node, convert (type, val), mvar);
5fcb93f1
FXC
1579
1580 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
1581 __builtin_isnan might be made dependent on that module being loaded,
1582 to help performance of programs that don't rely on IEEE semantics. */
7af6648c 1583 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
5fcb93f1 1584 {
db3927fb
AH
1585 isnan = build_call_expr_loc (input_location,
1586 built_in_decls[BUILT_IN_ISNAN], 1, mvar);
8a09ef91
FXC
1587 tmp = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, tmp,
1588 fold_convert (boolean_type_node, isnan));
5fcb93f1 1589 }
c2255bc4
AH
1590 tmp = build3_v (COND_EXPR, tmp, thencase,
1591 build_empty_stmt (input_location));
0160a2c7
FXC
1592
1593 if (cond != NULL_TREE)
c2255bc4
AH
1594 tmp = build3_v (COND_EXPR, cond, tmp,
1595 build_empty_stmt (input_location));
0160a2c7 1596
6de9cd9a 1597 gfc_add_expr_to_block (&se->pre, tmp);
0160a2c7 1598 argexpr = argexpr->next;
6de9cd9a
DN
1599 }
1600 se->expr = mvar;
1601}
1602
1603
2263c775
FXC
1604/* Generate library calls for MIN and MAX intrinsics for character
1605 variables. */
1606static void
1607gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
1608{
1609 tree *args;
374929b2 1610 tree var, len, fndecl, tmp, cond, function;
2263c775
FXC
1611 unsigned int nargs;
1612
1613 nargs = gfc_intrinsic_argument_list_length (expr);
1145e690 1614 args = XALLOCAVEC (tree, nargs + 4);
2263c775
FXC
1615 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
1616
1617 /* Create the result variables. */
1618 len = gfc_create_var (gfc_charlen_type_node, "len");
628c189e 1619 args[0] = gfc_build_addr_expr (NULL_TREE, len);
691da334 1620 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
2263c775
FXC
1621 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
1622 args[2] = build_int_cst (NULL_TREE, op);
1623 args[3] = build_int_cst (NULL_TREE, nargs / 2);
1624
374929b2
FXC
1625 if (expr->ts.kind == 1)
1626 function = gfor_fndecl_string_minmax;
1627 else if (expr->ts.kind == 4)
1628 function = gfor_fndecl_string_minmax_char4;
1629 else
1630 gcc_unreachable ();
1631
2263c775 1632 /* Make the function call. */
374929b2 1633 fndecl = build_addr (function, current_function_decl);
db3927fb
AH
1634 tmp = build_call_array_loc (input_location,
1635 TREE_TYPE (TREE_TYPE (function)), fndecl,
374929b2 1636 nargs + 4, args);
2263c775
FXC
1637 gfc_add_expr_to_block (&se->pre, tmp);
1638
1639 /* Free the temporary afterwards, if necessary. */
44855d8c
TS
1640 cond = fold_build2 (GT_EXPR, boolean_type_node,
1641 len, build_int_cst (TREE_TYPE (len), 0));
2263c775 1642 tmp = gfc_call_free (var);
c2255bc4 1643 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2263c775
FXC
1644 gfc_add_expr_to_block (&se->post, tmp);
1645
1646 se->expr = var;
1647 se->string_length = len;
1648}
1649
1650
4b9b6210
TS
1651/* Create a symbol node for this intrinsic. The symbol from the frontend
1652 has the generic name. */
6de9cd9a
DN
1653
1654static gfc_symbol *
1655gfc_get_symbol_for_expr (gfc_expr * expr)
1656{
1657 gfc_symbol *sym;
1658
1659 /* TODO: Add symbols for intrinsic function to the global namespace. */
6e45f57b 1660 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
6de9cd9a
DN
1661 sym = gfc_new_symbol (expr->value.function.name, NULL);
1662
1663 sym->ts = expr->ts;
1664 sym->attr.external = 1;
1665 sym->attr.function = 1;
1666 sym->attr.always_explicit = 1;
1667 sym->attr.proc = PROC_INTRINSIC;
1668 sym->attr.flavor = FL_PROCEDURE;
1669 sym->result = sym;
1670 if (expr->rank > 0)
1671 {
1672 sym->attr.dimension = 1;
1673 sym->as = gfc_get_array_spec ();
1674 sym->as->type = AS_ASSUMED_SHAPE;
1675 sym->as->rank = expr->rank;
1676 }
1677
47b99694
TB
1678 gfc_copy_formal_args_intr (sym, expr->value.function.isym);
1679
6de9cd9a
DN
1680 return sym;
1681}
1682
1683/* Generate a call to an external intrinsic function. */
1684static void
1685gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
1686{
1687 gfc_symbol *sym;
989ea525 1688 VEC(tree,gc) *append_args;
6de9cd9a 1689
6e45f57b 1690 gcc_assert (!se->ss || se->ss->expr == expr);
6de9cd9a
DN
1691
1692 if (se->ss)
6e45f57b 1693 gcc_assert (expr->rank > 0);
6de9cd9a 1694 else
6e45f57b 1695 gcc_assert (expr->rank == 0);
6de9cd9a
DN
1696
1697 sym = gfc_get_symbol_for_expr (expr);
5a0aad31
FXC
1698
1699 /* Calls to libgfortran_matmul need to be appended special arguments,
1700 to be able to call the BLAS ?gemm functions if required and possible. */
989ea525 1701 append_args = NULL;
cd5ecab6 1702 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
5a0aad31
FXC
1703 && sym->ts.type != BT_LOGICAL)
1704 {
1705 tree cint = gfc_get_int_type (gfc_c_int_kind);
1706
1707 if (gfc_option.flag_external_blas
1708 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
1709 && (sym->ts.kind == gfc_default_real_kind
1710 || sym->ts.kind == gfc_default_double_kind))
1711 {
1712 tree gemm_fndecl;
1713
1714 if (sym->ts.type == BT_REAL)
1715 {
1716 if (sym->ts.kind == gfc_default_real_kind)
1717 gemm_fndecl = gfor_fndecl_sgemm;
1718 else
1719 gemm_fndecl = gfor_fndecl_dgemm;
1720 }
1721 else
1722 {
1723 if (sym->ts.kind == gfc_default_real_kind)
1724 gemm_fndecl = gfor_fndecl_cgemm;
1725 else
1726 gemm_fndecl = gfor_fndecl_zgemm;
1727 }
1728
989ea525
NF
1729 append_args = VEC_alloc (tree, gc, 3);
1730 VEC_quick_push (tree, append_args, build_int_cst (cint, 1));
1731 VEC_quick_push (tree, append_args,
1732 build_int_cst (cint, gfc_option.blas_matmul_limit));
1733 VEC_quick_push (tree, append_args,
1734 gfc_build_addr_expr (NULL_TREE, gemm_fndecl));
5a0aad31
FXC
1735 }
1736 else
1737 {
989ea525
NF
1738 append_args = VEC_alloc (tree, gc, 3);
1739 VEC_quick_push (tree, append_args, build_int_cst (cint, 0));
1740 VEC_quick_push (tree, append_args, build_int_cst (cint, 0));
1741 VEC_quick_push (tree, append_args, null_pointer_node);
5a0aad31
FXC
1742 }
1743 }
1744
713485cc
JW
1745 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
1746 append_args);
6de9cd9a
DN
1747 gfc_free (sym);
1748}
1749
1750/* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
1751 Implemented as
1752 any(a)
1753 {
1754 forall (i=...)
1755 if (a[i] != 0)
1756 return 1
1757 end forall
1758 return 0
1759 }
1760 all(a)
1761 {
1762 forall (i=...)
1763 if (a[i] == 0)
1764 return 0
1765 end forall
1766 return 1
1767 }
1768 */
1769static void
8fa2df72 1770gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, enum tree_code op)
6de9cd9a
DN
1771{
1772 tree resvar;
1773 stmtblock_t block;
1774 stmtblock_t body;
1775 tree type;
1776 tree tmp;
1777 tree found;
1778 gfc_loopinfo loop;
1779 gfc_actual_arglist *actual;
1780 gfc_ss *arrayss;
1781 gfc_se arrayse;
1782 tree exit_label;
1783
1784 if (se->ss)
1785 {
1786 gfc_conv_intrinsic_funcall (se, expr);
1787 return;
1788 }
1789
1790 actual = expr->value.function.actual;
1791 type = gfc_typenode_for_spec (&expr->ts);
1792 /* Initialize the result. */
1793 resvar = gfc_create_var (type, "test");
1794 if (op == EQ_EXPR)
1795 tmp = convert (type, boolean_true_node);
1796 else
1797 tmp = convert (type, boolean_false_node);
726a989a 1798 gfc_add_modify (&se->pre, resvar, tmp);
6de9cd9a
DN
1799
1800 /* Walk the arguments. */
1801 arrayss = gfc_walk_expr (actual->expr);
6e45f57b 1802 gcc_assert (arrayss != gfc_ss_terminator);
6de9cd9a
DN
1803
1804 /* Initialize the scalarizer. */
1805 gfc_init_loopinfo (&loop);
1806 exit_label = gfc_build_label_decl (NULL_TREE);
1807 TREE_USED (exit_label) = 1;
1808 gfc_add_ss_to_loop (&loop, arrayss);
1809
1810 /* Initialize the loop. */
1811 gfc_conv_ss_startstride (&loop);
bdfd2ff0 1812 gfc_conv_loop_setup (&loop, &expr->where);
6de9cd9a
DN
1813
1814 gfc_mark_ss_chain_used (arrayss, 1);
1815 /* Generate the loop body. */
1816 gfc_start_scalarized_body (&loop, &body);
1817
1818 /* If the condition matches then set the return value. */
1819 gfc_start_block (&block);
1820 if (op == EQ_EXPR)
1821 tmp = convert (type, boolean_false_node);
1822 else
1823 tmp = convert (type, boolean_true_node);
726a989a 1824 gfc_add_modify (&block, resvar, tmp);
6de9cd9a
DN
1825
1826 /* And break out of the loop. */
1827 tmp = build1_v (GOTO_EXPR, exit_label);
1828 gfc_add_expr_to_block (&block, tmp);
1829
1830 found = gfc_finish_block (&block);
1831
1832 /* Check this element. */
1833 gfc_init_se (&arrayse, NULL);
1834 gfc_copy_loopinfo_to_se (&arrayse, &loop);
1835 arrayse.ss = arrayss;
1836 gfc_conv_expr_val (&arrayse, actual->expr);
1837
1838 gfc_add_block_to_block (&body, &arrayse.pre);
61a04b5b
RS
1839 tmp = fold_build2 (op, boolean_type_node, arrayse.expr,
1840 build_int_cst (TREE_TYPE (arrayse.expr), 0));
c2255bc4 1841 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt (input_location));
6de9cd9a
DN
1842 gfc_add_expr_to_block (&body, tmp);
1843 gfc_add_block_to_block (&body, &arrayse.post);
1844
1845 gfc_trans_scalarizing_loops (&loop, &body);
1846
1847 /* Add the exit label. */
1848 tmp = build1_v (LABEL_EXPR, exit_label);
1849 gfc_add_expr_to_block (&loop.pre, tmp);
1850
1851 gfc_add_block_to_block (&se->pre, &loop.pre);
1852 gfc_add_block_to_block (&se->pre, &loop.post);
1853 gfc_cleanup_loop (&loop);
1854
1855 se->expr = resvar;
1856}
1857
1858/* COUNT(A) = Number of true elements in A. */
1859static void
1860gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
1861{
1862 tree resvar;
1863 tree type;
1864 stmtblock_t body;
1865 tree tmp;
1866 gfc_loopinfo loop;
1867 gfc_actual_arglist *actual;
1868 gfc_ss *arrayss;
1869 gfc_se arrayse;
1870
1871 if (se->ss)
1872 {
1873 gfc_conv_intrinsic_funcall (se, expr);
1874 return;
1875 }
1876
1877 actual = expr->value.function.actual;
1878
1879 type = gfc_typenode_for_spec (&expr->ts);
1880 /* Initialize the result. */
1881 resvar = gfc_create_var (type, "count");
726a989a 1882 gfc_add_modify (&se->pre, resvar, build_int_cst (type, 0));
6de9cd9a
DN
1883
1884 /* Walk the arguments. */
1885 arrayss = gfc_walk_expr (actual->expr);
6e45f57b 1886 gcc_assert (arrayss != gfc_ss_terminator);
6de9cd9a
DN
1887
1888 /* Initialize the scalarizer. */
1889 gfc_init_loopinfo (&loop);
1890 gfc_add_ss_to_loop (&loop, arrayss);
1891
1892 /* Initialize the loop. */
1893 gfc_conv_ss_startstride (&loop);
bdfd2ff0 1894 gfc_conv_loop_setup (&loop, &expr->where);
6de9cd9a
DN
1895
1896 gfc_mark_ss_chain_used (arrayss, 1);
1897 /* Generate the loop body. */
1898 gfc_start_scalarized_body (&loop, &body);
1899
44855d8c
TS
1900 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (resvar),
1901 resvar, build_int_cst (TREE_TYPE (resvar), 1));
923ab88c 1902 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
6de9cd9a
DN
1903
1904 gfc_init_se (&arrayse, NULL);
1905 gfc_copy_loopinfo_to_se (&arrayse, &loop);
1906 arrayse.ss = arrayss;
1907 gfc_conv_expr_val (&arrayse, actual->expr);
c2255bc4
AH
1908 tmp = build3_v (COND_EXPR, arrayse.expr, tmp,
1909 build_empty_stmt (input_location));
6de9cd9a
DN
1910
1911 gfc_add_block_to_block (&body, &arrayse.pre);
1912 gfc_add_expr_to_block (&body, tmp);
1913 gfc_add_block_to_block (&body, &arrayse.post);
1914
1915 gfc_trans_scalarizing_loops (&loop, &body);
1916
1917 gfc_add_block_to_block (&se->pre, &loop.pre);
1918 gfc_add_block_to_block (&se->pre, &loop.post);
1919 gfc_cleanup_loop (&loop);
1920
1921 se->expr = resvar;
1922}
1923
1924/* Inline implementation of the sum and product intrinsics. */
1925static void
0cd0559e
TB
1926gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, enum tree_code op,
1927 bool norm2)
6de9cd9a
DN
1928{
1929 tree resvar;
0cd0559e 1930 tree scale = NULL_TREE;
6de9cd9a
DN
1931 tree type;
1932 stmtblock_t body;
1933 stmtblock_t block;
1934 tree tmp;
1935 gfc_loopinfo loop;
1936 gfc_actual_arglist *actual;
1937 gfc_ss *arrayss;
1938 gfc_ss *maskss;
1939 gfc_se arrayse;
1940 gfc_se maskse;
1941 gfc_expr *arrayexpr;
1942 gfc_expr *maskexpr;
1943
1944 if (se->ss)
1945 {
1946 gfc_conv_intrinsic_funcall (se, expr);
1947 return;
1948 }
1949
1950 type = gfc_typenode_for_spec (&expr->ts);
1951 /* Initialize the result. */
1952 resvar = gfc_create_var (type, "val");
0cd0559e
TB
1953 if (norm2)
1954 {
1955 /* result = 0.0;
1956 scale = 1.0. */
1957 scale = gfc_create_var (type, "scale");
1958 gfc_add_modify (&se->pre, scale,
1959 gfc_build_const (type, integer_one_node));
1960 tmp = gfc_build_const (type, integer_zero_node);
1961 }
1962 else if (op == PLUS_EXPR)
6de9cd9a 1963 tmp = gfc_build_const (type, integer_zero_node);
0cd0559e
TB
1964 else if (op == NE_EXPR)
1965 /* PARITY. */
1966 tmp = convert (type, boolean_false_node);
6de9cd9a
DN
1967 else
1968 tmp = gfc_build_const (type, integer_one_node);
1969
726a989a 1970 gfc_add_modify (&se->pre, resvar, tmp);
6de9cd9a
DN
1971
1972 /* Walk the arguments. */
1973 actual = expr->value.function.actual;
1974 arrayexpr = actual->expr;
1975 arrayss = gfc_walk_expr (arrayexpr);
6e45f57b 1976 gcc_assert (arrayss != gfc_ss_terminator);
6de9cd9a 1977
0cd0559e
TB
1978 if (op == NE_EXPR || norm2)
1979 /* PARITY and NORM2. */
1980 maskexpr = NULL;
1981 else
1982 {
1983 actual = actual->next->next;
1984 gcc_assert (actual);
1985 maskexpr = actual->expr;
1986 }
1987
eaf618e3 1988 if (maskexpr && maskexpr->rank != 0)
6de9cd9a
DN
1989 {
1990 maskss = gfc_walk_expr (maskexpr);
6e45f57b 1991 gcc_assert (maskss != gfc_ss_terminator);
6de9cd9a
DN
1992 }
1993 else
1994 maskss = NULL;
1995
1996 /* Initialize the scalarizer. */
1997 gfc_init_loopinfo (&loop);
1998 gfc_add_ss_to_loop (&loop, arrayss);
1999 if (maskss)
2000 gfc_add_ss_to_loop (&loop, maskss);
2001
2002 /* Initialize the loop. */
2003 gfc_conv_ss_startstride (&loop);
bdfd2ff0 2004 gfc_conv_loop_setup (&loop, &expr->where);
6de9cd9a
DN
2005
2006 gfc_mark_ss_chain_used (arrayss, 1);
2007 if (maskss)
2008 gfc_mark_ss_chain_used (maskss, 1);
2009 /* Generate the loop body. */
2010 gfc_start_scalarized_body (&loop, &body);
2011
2012 /* If we have a mask, only add this element if the mask is set. */
2013 if (maskss)
2014 {
2015 gfc_init_se (&maskse, NULL);
2016 gfc_copy_loopinfo_to_se (&maskse, &loop);
2017 maskse.ss = maskss;
2018 gfc_conv_expr_val (&maskse, maskexpr);
2019 gfc_add_block_to_block (&body, &maskse.pre);
2020
2021 gfc_start_block (&block);
2022 }
2023 else
2024 gfc_init_block (&block);
2025
2026 /* Do the actual summation/product. */
2027 gfc_init_se (&arrayse, NULL);
2028 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2029 arrayse.ss = arrayss;
2030 gfc_conv_expr_val (&arrayse, arrayexpr);
2031 gfc_add_block_to_block (&block, &arrayse.pre);
2032
0cd0559e
TB
2033 if (norm2)
2034 {
2035 /* if (x(i) != 0.0)
2036 {
2037 absX = abs(x(i))
2038 if (absX > scale)
2039 {
2040 val = scale/absX;
2041 result = 1.0 + result * val * val;
2042 scale = absX;
2043 }
2044 else
2045 {
2046 val = absX/scale;
2047 result += val * val;
2048 }
2049 } */
2050 tree res1, res2, cond, absX, val;
2051 stmtblock_t ifblock1, ifblock2, ifblock3;
2052
2053 gfc_init_block (&ifblock1);
2054
2055 absX = gfc_create_var (type, "absX");
2056 gfc_add_modify (&ifblock1, absX,
2057 fold_build1 (ABS_EXPR, type, arrayse.expr));
2058 val = gfc_create_var (type, "val");
2059 gfc_add_expr_to_block (&ifblock1, val);
2060
2061 gfc_init_block (&ifblock2);
2062 gfc_add_modify (&ifblock2, val,
2063 fold_build2 (RDIV_EXPR, type, scale, absX));
2064 res1 = fold_build2 (MULT_EXPR, type, val, val);
2065 res1 = fold_build2 (MULT_EXPR, type, resvar, res1);
2066 res1 = fold_build2 (PLUS_EXPR, type, res1,
2067 gfc_build_const (type, integer_one_node));
2068 gfc_add_modify (&ifblock2, resvar, res1);
2069 gfc_add_modify (&ifblock2, scale, absX);
2070 res1 = gfc_finish_block (&ifblock2);
2071
2072 gfc_init_block (&ifblock3);
2073 gfc_add_modify (&ifblock3, val,
2074 fold_build2 (RDIV_EXPR, type, absX, scale));
2075 res2 = fold_build2 (MULT_EXPR, type, val, val);
2076 res2 = fold_build2 (PLUS_EXPR, type, resvar, res2);
2077 gfc_add_modify (&ifblock3, resvar, res2);
2078 res2 = gfc_finish_block (&ifblock3);
2079
2080 cond = fold_build2 (GT_EXPR, boolean_type_node, absX, scale);
2081 tmp = build3_v (COND_EXPR, cond, res1, res2);
2082 gfc_add_expr_to_block (&ifblock1, tmp);
2083 tmp = gfc_finish_block (&ifblock1);
2084
2085 cond = fold_build2 (NE_EXPR, boolean_type_node, arrayse.expr,
2086 gfc_build_const (type, integer_zero_node));
2087
2088 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2089 gfc_add_expr_to_block (&block, tmp);
2090 }
2091 else
2092 {
2093 tmp = fold_build2 (op, type, resvar, arrayse.expr);
2094 gfc_add_modify (&block, resvar, tmp);
2095 }
2096
6de9cd9a
DN
2097 gfc_add_block_to_block (&block, &arrayse.post);
2098
2099 if (maskss)
2100 {
2101 /* We enclose the above in if (mask) {...} . */
6de9cd9a 2102
0cd0559e 2103 tmp = gfc_finish_block (&block);
c2255bc4
AH
2104 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2105 build_empty_stmt (input_location));
6de9cd9a
DN
2106 }
2107 else
2108 tmp = gfc_finish_block (&block);
2109 gfc_add_expr_to_block (&body, tmp);
2110
2111 gfc_trans_scalarizing_loops (&loop, &body);
eaf618e3
TK
2112
2113 /* For a scalar mask, enclose the loop in an if statement. */
2114 if (maskexpr && maskss == NULL)
2115 {
2116 gfc_init_se (&maskse, NULL);
2117 gfc_conv_expr_val (&maskse, maskexpr);
2118 gfc_init_block (&block);
2119 gfc_add_block_to_block (&block, &loop.pre);
2120 gfc_add_block_to_block (&block, &loop.post);
2121 tmp = gfc_finish_block (&block);
2122
c2255bc4
AH
2123 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2124 build_empty_stmt (input_location));
eaf618e3
TK
2125 gfc_add_expr_to_block (&block, tmp);
2126 gfc_add_block_to_block (&se->pre, &block);
2127 }
2128 else
2129 {
2130 gfc_add_block_to_block (&se->pre, &loop.pre);
2131 gfc_add_block_to_block (&se->pre, &loop.post);
2132 }
2133
6de9cd9a
DN
2134 gfc_cleanup_loop (&loop);
2135
0cd0559e
TB
2136 if (norm2)
2137 {
2138 /* result = scale * sqrt(result). */
2139 tree sqrt;
2140 sqrt = builtin_decl_for_float_kind (BUILT_IN_SQRT, expr->ts.kind);
2141 resvar = build_call_expr_loc (input_location,
2142 sqrt, 1, resvar);
2143 resvar = fold_build2 (MULT_EXPR, type, scale, resvar);
2144 }
2145
6de9cd9a
DN
2146 se->expr = resvar;
2147}
2148
61321991
PT
2149
2150/* Inline implementation of the dot_product intrinsic. This function
2151 is based on gfc_conv_intrinsic_arith (the previous function). */
2152static void
2153gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
2154{
2155 tree resvar;
2156 tree type;
2157 stmtblock_t body;
2158 stmtblock_t block;
2159 tree tmp;
2160 gfc_loopinfo loop;
2161 gfc_actual_arglist *actual;
2162 gfc_ss *arrayss1, *arrayss2;
2163 gfc_se arrayse1, arrayse2;
2164 gfc_expr *arrayexpr1, *arrayexpr2;
2165
2166 type = gfc_typenode_for_spec (&expr->ts);
2167
2168 /* Initialize the result. */
2169 resvar = gfc_create_var (type, "val");
2170 if (expr->ts.type == BT_LOGICAL)
19ee2065 2171 tmp = build_int_cst (type, 0);
61321991
PT
2172 else
2173 tmp = gfc_build_const (type, integer_zero_node);
2174
726a989a 2175 gfc_add_modify (&se->pre, resvar, tmp);
61321991
PT
2176
2177 /* Walk argument #1. */
2178 actual = expr->value.function.actual;
2179 arrayexpr1 = actual->expr;
2180 arrayss1 = gfc_walk_expr (arrayexpr1);
2181 gcc_assert (arrayss1 != gfc_ss_terminator);
2182
2183 /* Walk argument #2. */
2184 actual = actual->next;
2185 arrayexpr2 = actual->expr;
2186 arrayss2 = gfc_walk_expr (arrayexpr2);
2187 gcc_assert (arrayss2 != gfc_ss_terminator);
2188
2189 /* Initialize the scalarizer. */
2190 gfc_init_loopinfo (&loop);
2191 gfc_add_ss_to_loop (&loop, arrayss1);
2192 gfc_add_ss_to_loop (&loop, arrayss2);
2193
2194 /* Initialize the loop. */
2195 gfc_conv_ss_startstride (&loop);
bdfd2ff0 2196 gfc_conv_loop_setup (&loop, &expr->where);
61321991
PT
2197
2198 gfc_mark_ss_chain_used (arrayss1, 1);
2199 gfc_mark_ss_chain_used (arrayss2, 1);
2200
2201 /* Generate the loop body. */
2202 gfc_start_scalarized_body (&loop, &body);
2203 gfc_init_block (&block);
2204
2205 /* Make the tree expression for [conjg(]array1[)]. */
2206 gfc_init_se (&arrayse1, NULL);
2207 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
2208 arrayse1.ss = arrayss1;
2209 gfc_conv_expr_val (&arrayse1, arrayexpr1);
2210 if (expr->ts.type == BT_COMPLEX)
44855d8c 2211 arrayse1.expr = fold_build1 (CONJ_EXPR, type, arrayse1.expr);
61321991
PT
2212 gfc_add_block_to_block (&block, &arrayse1.pre);
2213
2214 /* Make the tree expression for array2. */
2215 gfc_init_se (&arrayse2, NULL);
2216 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
2217 arrayse2.ss = arrayss2;
2218 gfc_conv_expr_val (&arrayse2, arrayexpr2);
2219 gfc_add_block_to_block (&block, &arrayse2.pre);
2220
2221 /* Do the actual product and sum. */
2222 if (expr->ts.type == BT_LOGICAL)
2223 {
44855d8c
TS
2224 tmp = fold_build2 (TRUTH_AND_EXPR, type, arrayse1.expr, arrayse2.expr);
2225 tmp = fold_build2 (TRUTH_OR_EXPR, type, resvar, tmp);
61321991
PT
2226 }
2227 else
2228 {
44855d8c
TS
2229 tmp = fold_build2 (MULT_EXPR, type, arrayse1.expr, arrayse2.expr);
2230 tmp = fold_build2 (PLUS_EXPR, type, resvar, tmp);
61321991 2231 }
726a989a 2232 gfc_add_modify (&block, resvar, tmp);
61321991
PT
2233
2234 /* Finish up the loop block and the loop. */
2235 tmp = gfc_finish_block (&block);
2236 gfc_add_expr_to_block (&body, tmp);
2237
2238 gfc_trans_scalarizing_loops (&loop, &body);
2239 gfc_add_block_to_block (&se->pre, &loop.pre);
2240 gfc_add_block_to_block (&se->pre, &loop.post);
2241 gfc_cleanup_loop (&loop);
2242
2243 se->expr = resvar;
2244}
2245
2246
80927a56
JJ
2247/* Emit code for minloc or maxloc intrinsic. There are many different cases
2248 we need to handle. For performance reasons we sometimes create two
2249 loops instead of one, where the second one is much simpler.
2250 Examples for minloc intrinsic:
2251 1) Result is an array, a call is generated
2252 2) Array mask is used and NaNs need to be supported:
2253 limit = Infinity;
2254 pos = 0;
2255 S = from;
2256 while (S <= to) {
2257 if (mask[S]) {
2258 if (pos == 0) pos = S + (1 - from);
2259 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
2260 }
2261 S++;
2262 }
2263 goto lab2;
2264 lab1:;
2265 while (S <= to) {
2266 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
2267 S++;
2268 }
2269 lab2:;
2270 3) NaNs need to be supported, but it is known at compile time or cheaply
2271 at runtime whether array is nonempty or not:
2272 limit = Infinity;
2273 pos = 0;
2274 S = from;
2275 while (S <= to) {
2276 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
2277 S++;
2278 }
2279 if (from <= to) pos = 1;
2280 goto lab2;
2281 lab1:;
2282 while (S <= to) {
2283 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
2284 S++;
2285 }
2286 lab2:;
2287 4) NaNs aren't supported, array mask is used:
2288 limit = infinities_supported ? Infinity : huge (limit);
2289 pos = 0;
2290 S = from;
2291 while (S <= to) {
2292 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
2293 S++;
2294 }
2295 goto lab2;
2296 lab1:;
2297 while (S <= to) {
2298 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
2299 S++;
2300 }
2301 lab2:;
2302 5) Same without array mask:
2303 limit = infinities_supported ? Infinity : huge (limit);
2304 pos = (from <= to) ? 1 : 0;
2305 S = from;
2306 while (S <= to) {
2307 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
2308 S++;
2309 }
2310 For 3) and 5), if mask is scalar, this all goes into a conditional,
2311 setting pos = 0; in the else branch. */
2312
6de9cd9a 2313static void
8fa2df72 2314gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
6de9cd9a
DN
2315{
2316 stmtblock_t body;
2317 stmtblock_t block;
2318 stmtblock_t ifblock;
8cd25827 2319 stmtblock_t elseblock;
6de9cd9a
DN
2320 tree limit;
2321 tree type;
2322 tree tmp;
80927a56 2323 tree cond;
8cd25827 2324 tree elsetmp;
6de9cd9a 2325 tree ifbody;
f0b3c58d 2326 tree offset;
80927a56
JJ
2327 tree nonempty;
2328 tree lab1, lab2;
6de9cd9a
DN
2329 gfc_loopinfo loop;
2330 gfc_actual_arglist *actual;
2331 gfc_ss *arrayss;
2332 gfc_ss *maskss;
2333 gfc_se arrayse;
2334 gfc_se maskse;
2335 gfc_expr *arrayexpr;
2336 gfc_expr *maskexpr;
2337 tree pos;
2338 int n;
2339
2340 if (se->ss)
2341 {
2342 gfc_conv_intrinsic_funcall (se, expr);
2343 return;
2344 }
2345
2346 /* Initialize the result. */
2347 pos = gfc_create_var (gfc_array_index_type, "pos");
f0b3c58d 2348 offset = gfc_create_var (gfc_array_index_type, "offset");
6de9cd9a
DN
2349 type = gfc_typenode_for_spec (&expr->ts);
2350
2351 /* Walk the arguments. */
2352 actual = expr->value.function.actual;
2353 arrayexpr = actual->expr;
2354 arrayss = gfc_walk_expr (arrayexpr);
6e45f57b 2355 gcc_assert (arrayss != gfc_ss_terminator);
6de9cd9a
DN
2356
2357 actual = actual->next->next;
6e45f57b 2358 gcc_assert (actual);
6de9cd9a 2359 maskexpr = actual->expr;
80927a56 2360 nonempty = NULL;
8cd25827 2361 if (maskexpr && maskexpr->rank != 0)
6de9cd9a
DN
2362 {
2363 maskss = gfc_walk_expr (maskexpr);
6e45f57b 2364 gcc_assert (maskss != gfc_ss_terminator);
6de9cd9a
DN
2365 }
2366 else
80927a56
JJ
2367 {
2368 mpz_t asize;
2369 if (gfc_array_size (arrayexpr, &asize) == SUCCESS)
2370 {
2371 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
2372 mpz_clear (asize);
2373 nonempty = fold_build2 (GT_EXPR, boolean_type_node, nonempty,
2374 gfc_index_zero_node);
2375 }
2376 maskss = NULL;
2377 }
6de9cd9a
DN
2378
2379 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
e7a2d5fb 2380 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
6de9cd9a
DN
2381 switch (arrayexpr->ts.type)
2382 {
2383 case BT_REAL:
80927a56
JJ
2384 if (HONOR_INFINITIES (DECL_MODE (limit)))
2385 {
2386 REAL_VALUE_TYPE real;
2387 real_inf (&real);
2388 tmp = build_real (TREE_TYPE (limit), real);
2389 }
2390 else
2391 tmp = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
2392 arrayexpr->ts.kind, 0);
6de9cd9a
DN
2393 break;
2394
2395 case BT_INTEGER:
2396 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
2397 arrayexpr->ts.kind);
2398 break;
2399
2400 default:
6e45f57b 2401 gcc_unreachable ();
6de9cd9a
DN
2402 }
2403
88116029
TB
2404 /* We start with the most negative possible value for MAXLOC, and the most
2405 positive possible value for MINLOC. The most negative possible value is
2406 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
66e4ab31 2407 possible value is HUGE in both cases. */
6de9cd9a 2408 if (op == GT_EXPR)
10c7a96f 2409 tmp = fold_build1 (NEGATE_EXPR, TREE_TYPE (tmp), tmp);
88116029 2410 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
44855d8c
TS
2411 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), tmp,
2412 build_int_cst (type, 1));
88116029 2413
258bd5dc
JJ
2414 gfc_add_modify (&se->pre, limit, tmp);
2415
6de9cd9a
DN
2416 /* Initialize the scalarizer. */
2417 gfc_init_loopinfo (&loop);
2418 gfc_add_ss_to_loop (&loop, arrayss);
2419 if (maskss)
2420 gfc_add_ss_to_loop (&loop, maskss);
2421
2422 /* Initialize the loop. */
2423 gfc_conv_ss_startstride (&loop);
bdfd2ff0 2424 gfc_conv_loop_setup (&loop, &expr->where);
6de9cd9a 2425
6e45f57b 2426 gcc_assert (loop.dimen == 1);
80927a56
JJ
2427 if (nonempty == NULL && maskss == NULL && loop.from[0] && loop.to[0])
2428 nonempty = fold_build2 (LE_EXPR, boolean_type_node, loop.from[0],
2429 loop.to[0]);
6de9cd9a 2430
80927a56
JJ
2431 lab1 = NULL;
2432 lab2 = NULL;
a4b9e93e
PT
2433 /* Initialize the position to zero, following Fortran 2003. We are free
2434 to do this because Fortran 95 allows the result of an entirely false
80927a56
JJ
2435 mask to be processor dependent. If we know at compile time the array
2436 is non-empty and no MASK is used, we can initialize to 1 to simplify
2437 the inner loop. */
2438 if (nonempty != NULL && !HONOR_NANS (DECL_MODE (limit)))
2439 gfc_add_modify (&loop.pre, pos,
2440 fold_build3 (COND_EXPR, gfc_array_index_type,
2441 nonempty, gfc_index_one_node,
2442 gfc_index_zero_node));
2443 else
2444 {
2445 gfc_add_modify (&loop.pre, pos, gfc_index_zero_node);
2446 lab1 = gfc_build_label_decl (NULL_TREE);
2447 TREE_USED (lab1) = 1;
2448 lab2 = gfc_build_label_decl (NULL_TREE);
2449 TREE_USED (lab2) = 1;
2450 }
b36cd00b 2451
6de9cd9a
DN
2452 gfc_mark_ss_chain_used (arrayss, 1);
2453 if (maskss)
2454 gfc_mark_ss_chain_used (maskss, 1);
2455 /* Generate the loop body. */
2456 gfc_start_scalarized_body (&loop, &body);
2457
2458 /* If we have a mask, only check this element if the mask is set. */
2459 if (maskss)
2460 {
2461 gfc_init_se (&maskse, NULL);
2462 gfc_copy_loopinfo_to_se (&maskse, &loop);
2463 maskse.ss = maskss;
2464 gfc_conv_expr_val (&maskse, maskexpr);
2465 gfc_add_block_to_block (&body, &maskse.pre);
2466
2467 gfc_start_block (&block);
2468 }
2469 else
2470 gfc_init_block (&block);
2471
2472 /* Compare with the current limit. */
2473 gfc_init_se (&arrayse, NULL);
2474 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2475 arrayse.ss = arrayss;
2476 gfc_conv_expr_val (&arrayse, arrayexpr);
2477 gfc_add_block_to_block (&block, &arrayse.pre);
2478
2479 /* We do the following if this is a more extreme value. */
2480 gfc_start_block (&ifblock);
2481
2482 /* Assign the value to the limit... */
726a989a 2483 gfc_add_modify (&ifblock, limit, arrayse.expr);
6de9cd9a 2484
f0b3c58d
PT
2485 /* Remember where we are. An offset must be added to the loop
2486 counter to obtain the required position. */
4e77ad24
JD
2487 if (loop.from[0])
2488 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
2489 gfc_index_one_node, loop.from[0]);
f0b3c58d 2490 else
8c3ed71e 2491 tmp = gfc_index_one_node;
80927a56 2492
726a989a 2493 gfc_add_modify (&block, offset, tmp);
f0b3c58d 2494
80927a56
JJ
2495 if (nonempty == NULL && HONOR_NANS (DECL_MODE (limit)))
2496 {
2497 stmtblock_t ifblock2;
2498 tree ifbody2;
2499
2500 gfc_start_block (&ifblock2);
2501 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (pos),
2502 loop.loopvar[0], offset);
2503 gfc_add_modify (&ifblock2, pos, tmp);
2504 ifbody2 = gfc_finish_block (&ifblock2);
2505 cond = fold_build2 (EQ_EXPR, boolean_type_node, pos,
2506 gfc_index_zero_node);
2507 tmp = build3_v (COND_EXPR, cond, ifbody2,
2508 build_empty_stmt (input_location));
2509 gfc_add_expr_to_block (&block, tmp);
2510 }
2511
44855d8c
TS
2512 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (pos),
2513 loop.loopvar[0], offset);
726a989a 2514 gfc_add_modify (&ifblock, pos, tmp);
6de9cd9a 2515
80927a56
JJ
2516 if (lab1)
2517 gfc_add_expr_to_block (&ifblock, build1_v (GOTO_EXPR, lab1));
2518
6de9cd9a
DN
2519 ifbody = gfc_finish_block (&ifblock);
2520
80927a56
JJ
2521 if (!lab1 || HONOR_NANS (DECL_MODE (limit)))
2522 {
2523 if (lab1)
2524 cond = fold_build2 (op == GT_EXPR ? GE_EXPR : LE_EXPR,
2525 boolean_type_node, arrayse.expr, limit);
2526 else
2527 cond = fold_build2 (op, boolean_type_node, arrayse.expr, limit);
2528
2529 ifbody = build3_v (COND_EXPR, cond, ifbody,
2530 build_empty_stmt (input_location));
2531 }
2532 gfc_add_expr_to_block (&block, ifbody);
6de9cd9a
DN
2533
2534 if (maskss)
2535 {
2536 /* We enclose the above in if (mask) {...}. */
2537 tmp = gfc_finish_block (&block);
2538
c2255bc4
AH
2539 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2540 build_empty_stmt (input_location));
6de9cd9a
DN
2541 }
2542 else
2543 tmp = gfc_finish_block (&block);
2544 gfc_add_expr_to_block (&body, tmp);
2545
80927a56
JJ
2546 if (lab1)
2547 {
2548 gfc_trans_scalarized_loop_end (&loop, 0, &body);
2549
2550 if (HONOR_NANS (DECL_MODE (limit)))
2551 {
2552 if (nonempty != NULL)
2553 {
2554 ifbody = build2_v (MODIFY_EXPR, pos, gfc_index_one_node);
2555 tmp = build3_v (COND_EXPR, nonempty, ifbody,
2556 build_empty_stmt (input_location));
2557 gfc_add_expr_to_block (&loop.code[0], tmp);
2558 }
2559 }
2560
2561 gfc_add_expr_to_block (&loop.code[0], build1_v (GOTO_EXPR, lab2));
2562 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab1));
2563 gfc_start_block (&body);
2564
2565 /* If we have a mask, only check this element if the mask is set. */
2566 if (maskss)
2567 {
2568 gfc_init_se (&maskse, NULL);
2569 gfc_copy_loopinfo_to_se (&maskse, &loop);
2570 maskse.ss = maskss;
2571 gfc_conv_expr_val (&maskse, maskexpr);
2572 gfc_add_block_to_block (&body, &maskse.pre);
2573
2574 gfc_start_block (&block);
2575 }
2576 else
2577 gfc_init_block (&block);
2578
2579 /* Compare with the current limit. */
2580 gfc_init_se (&arrayse, NULL);
2581 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2582 arrayse.ss = arrayss;
2583 gfc_conv_expr_val (&arrayse, arrayexpr);
2584 gfc_add_block_to_block (&block, &arrayse.pre);
2585
2586 /* We do the following if this is a more extreme value. */
2587 gfc_start_block (&ifblock);
2588
2589 /* Assign the value to the limit... */
2590 gfc_add_modify (&ifblock, limit, arrayse.expr);
2591
2592 /* Remember where we are. An offset must be added to the loop
2593 counter to obtain the required position. */
2594 if (loop.from[0])
2595 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
2596 gfc_index_one_node, loop.from[0]);
2597 else
2598 tmp = gfc_index_one_node;
2599
2600 gfc_add_modify (&block, offset, tmp);
2601
2602 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (pos),
2603 loop.loopvar[0], offset);
2604 gfc_add_modify (&ifblock, pos, tmp);
2605
2606 ifbody = gfc_finish_block (&ifblock);
2607
2608 cond = fold_build2 (op, boolean_type_node, arrayse.expr, limit);
2609
2610 tmp = build3_v (COND_EXPR, cond, ifbody,
2611 build_empty_stmt (input_location));
2612 gfc_add_expr_to_block (&block, tmp);
2613
2614 if (maskss)
2615 {
2616 /* We enclose the above in if (mask) {...}. */
2617 tmp = gfc_finish_block (&block);
2618
2619 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
2620 build_empty_stmt (input_location));
2621 }
2622 else
2623 tmp = gfc_finish_block (&block);
2624 gfc_add_expr_to_block (&body, tmp);
2625 /* Avoid initializing loopvar[0] again, it should be left where
2626 it finished by the first loop. */
2627 loop.from[0] = loop.loopvar[0];
2628 }
2629
6de9cd9a
DN
2630 gfc_trans_scalarizing_loops (&loop, &body);
2631
80927a56
JJ
2632 if (lab2)
2633 gfc_add_expr_to_block (&loop.pre, build1_v (LABEL_EXPR, lab2));
2634
8cd25827
TK
2635 /* For a scalar mask, enclose the loop in an if statement. */
2636 if (maskexpr && maskss == NULL)
2637 {
2638 gfc_init_se (&maskse, NULL);
2639 gfc_conv_expr_val (&maskse, maskexpr);
2640 gfc_init_block (&block);
2641 gfc_add_block_to_block (&block, &loop.pre);
2642 gfc_add_block_to_block (&block, &loop.post);
2643 tmp = gfc_finish_block (&block);
2644
2645 /* For the else part of the scalar mask, just initialize
2646 the pos variable the same way as above. */
2647
2648 gfc_init_block (&elseblock);
726a989a 2649 gfc_add_modify (&elseblock, pos, gfc_index_zero_node);
8cd25827
TK
2650 elsetmp = gfc_finish_block (&elseblock);
2651
2652 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
2653 gfc_add_expr_to_block (&block, tmp);
2654 gfc_add_block_to_block (&se->pre, &block);
2655 }
2656 else
2657 {
2658 gfc_add_block_to_block (&se->pre, &loop.pre);
2659 gfc_add_block_to_block (&se->pre, &loop.post);
2660 }
6de9cd9a
DN
2661 gfc_cleanup_loop (&loop);
2662
f0b3c58d 2663 se->expr = convert (type, pos);
6de9cd9a
DN
2664}
2665
80927a56
JJ
2666/* Emit code for minval or maxval intrinsic. There are many different cases
2667 we need to handle. For performance reasons we sometimes create two
2668 loops instead of one, where the second one is much simpler.
2669 Examples for minval intrinsic:
2670 1) Result is an array, a call is generated
2671 2) Array mask is used and NaNs need to be supported, rank 1:
2672 limit = Infinity;
2673 nonempty = false;
2674 S = from;
2675 while (S <= to) {
2676 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
2677 S++;
2678 }
2679 limit = nonempty ? NaN : huge (limit);
2680 lab:
2681 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
2682 3) NaNs need to be supported, but it is known at compile time or cheaply
2683 at runtime whether array is nonempty or not, rank 1:
2684 limit = Infinity;
2685 S = from;
2686 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
2687 limit = (from <= to) ? NaN : huge (limit);
2688 lab:
2689 while (S <= to) { limit = min (a[S], limit); S++; }
2690 4) Array mask is used and NaNs need to be supported, rank > 1:
2691 limit = Infinity;
2692 nonempty = false;
2693 fast = false;
2694 S1 = from1;
2695 while (S1 <= to1) {
2696 S2 = from2;
2697 while (S2 <= to2) {
2698 if (mask[S1][S2]) {
2699 if (fast) limit = min (a[S1][S2], limit);
2700 else {
2701 nonempty = true;
2702 if (a[S1][S2] <= limit) {
2703 limit = a[S1][S2];
2704 fast = true;
2705 }
2706 }
2707 }
2708 S2++;
2709 }
2710 S1++;
2711 }
2712 if (!fast)
2713 limit = nonempty ? NaN : huge (limit);
2714 5) NaNs need to be supported, but it is known at compile time or cheaply
2715 at runtime whether array is nonempty or not, rank > 1:
2716 limit = Infinity;
2717 fast = false;
2718 S1 = from1;
2719 while (S1 <= to1) {
2720 S2 = from2;
2721 while (S2 <= to2) {
2722 if (fast) limit = min (a[S1][S2], limit);
2723 else {
2724 if (a[S1][S2] <= limit) {
2725 limit = a[S1][S2];
2726 fast = true;
2727 }
2728 }
2729 S2++;
2730 }
2731 S1++;
2732 }
2733 if (!fast)
2734 limit = (nonempty_array) ? NaN : huge (limit);
2735 6) NaNs aren't supported, but infinities are. Array mask is used:
2736 limit = Infinity;
2737 nonempty = false;
2738 S = from;
2739 while (S <= to) {
2740 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
2741 S++;
2742 }
2743 limit = nonempty ? limit : huge (limit);
2744 7) Same without array mask:
2745 limit = Infinity;
2746 S = from;
2747 while (S <= to) { limit = min (a[S], limit); S++; }
2748 limit = (from <= to) ? limit : huge (limit);
2749 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
2750 limit = huge (limit);
2751 S = from;
2752 while (S <= to) { limit = min (a[S], limit); S++); }
2753 (or
2754 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
2755 with array mask instead).
2756 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
2757 setting limit = huge (limit); in the else branch. */
2758
6de9cd9a 2759static void
8fa2df72 2760gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
6de9cd9a
DN
2761{
2762 tree limit;
2763 tree type;
2764 tree tmp;
2765 tree ifbody;
80927a56
JJ
2766 tree nonempty;
2767 tree nonempty_var;
2768 tree lab;
2769 tree fast;
2770 tree huge_cst = NULL, nan_cst = NULL;
6de9cd9a 2771 stmtblock_t body;
80927a56 2772 stmtblock_t block, block2;
6de9cd9a
DN
2773 gfc_loopinfo loop;
2774 gfc_actual_arglist *actual;
2775 gfc_ss *arrayss;
2776 gfc_ss *maskss;
2777 gfc_se arrayse;
2778 gfc_se maskse;
2779 gfc_expr *arrayexpr;
2780 gfc_expr *maskexpr;
2781 int n;
2782
2783 if (se->ss)
2784 {
2785 gfc_conv_intrinsic_funcall (se, expr);
2786 return;
2787 }
2788
2789 type = gfc_typenode_for_spec (&expr->ts);
2790 /* Initialize the result. */
2791 limit = gfc_create_var (type, "limit");
e7a2d5fb 2792 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
6de9cd9a
DN
2793 switch (expr->ts.type)
2794 {
2795 case BT_REAL:
80927a56
JJ
2796 huge_cst = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge,
2797 expr->ts.kind, 0);
2798 if (HONOR_INFINITIES (DECL_MODE (limit)))
2799 {
2800 REAL_VALUE_TYPE real;
2801 real_inf (&real);
2802 tmp = build_real (type, real);
2803 }
2804 else
2805 tmp = huge_cst;
2806 if (HONOR_NANS (DECL_MODE (limit)))
2807 {
2808 REAL_VALUE_TYPE real;
2809 real_nan (&real, "", 1, DECL_MODE (limit));
2810 nan_cst = build_real (type, real);
2811 }
6de9cd9a
DN
2812 break;
2813
2814 case BT_INTEGER:
2815 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
2816 break;
2817
2818 default:
6e45f57b 2819 gcc_unreachable ();
6de9cd9a
DN
2820 }
2821
88116029
TB
2822 /* We start with the most negative possible value for MAXVAL, and the most
2823 positive possible value for MINVAL. The most negative possible value is
2824 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
66e4ab31 2825 possible value is HUGE in both cases. */
6de9cd9a 2826 if (op == GT_EXPR)
80927a56
JJ
2827 {
2828 tmp = fold_build1 (NEGATE_EXPR, TREE_TYPE (tmp), tmp);
2829 if (huge_cst)
2830 huge_cst = fold_build1 (NEGATE_EXPR, TREE_TYPE (huge_cst), huge_cst);
2831 }
88116029
TB
2832
2833 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
44855d8c
TS
2834 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp),
2835 tmp, build_int_cst (type, 1));
88116029 2836
726a989a 2837 gfc_add_modify (&se->pre, limit, tmp);
6de9cd9a
DN
2838
2839 /* Walk the arguments. */
2840 actual = expr->value.function.actual;
2841 arrayexpr = actual->expr;
2842 arrayss = gfc_walk_expr (arrayexpr);
6e45f57b 2843 gcc_assert (arrayss != gfc_ss_terminator);
6de9cd9a
DN
2844
2845 actual = actual->next->next;
6e45f57b 2846 gcc_assert (actual);
6de9cd9a 2847 maskexpr = actual->expr;
80927a56 2848 nonempty = NULL;
eaf618e3 2849 if (maskexpr && maskexpr->rank != 0)
6de9cd9a
DN
2850 {
2851 maskss = gfc_walk_expr (maskexpr);
6e45f57b 2852 gcc_assert (maskss != gfc_ss_terminator);
6de9cd9a
DN
2853 }
2854 else
80927a56
JJ
2855 {
2856 mpz_t asize;
2857 if (gfc_array_size (arrayexpr, &asize) == SUCCESS)
2858 {
2859 nonempty = gfc_conv_mpz_to_tree (asize, gfc_index_integer_kind);
2860 mpz_clear (asize);
2861 nonempty = fold_build2 (GT_EXPR, boolean_type_node, nonempty,
2862 gfc_index_zero_node);
2863 }
2864 maskss = NULL;
2865 }
6de9cd9a
DN
2866
2867 /* Initialize the scalarizer. */
2868 gfc_init_loopinfo (&loop);
2869 gfc_add_ss_to_loop (&loop, arrayss);
2870 if (maskss)
2871 gfc_add_ss_to_loop (&loop, maskss);
2872
2873 /* Initialize the loop. */
2874 gfc_conv_ss_startstride (&loop);
bdfd2ff0 2875 gfc_conv_loop_setup (&loop, &expr->where);
6de9cd9a 2876
80927a56
JJ
2877 if (nonempty == NULL && maskss == NULL
2878 && loop.dimen == 1 && loop.from[0] && loop.to[0])
2879 nonempty = fold_build2 (LE_EXPR, boolean_type_node, loop.from[0],
2880 loop.to[0]);
2881 nonempty_var = NULL;
2882 if (nonempty == NULL
2883 && (HONOR_INFINITIES (DECL_MODE (limit))
2884 || HONOR_NANS (DECL_MODE (limit))))
2885 {
2886 nonempty_var = gfc_create_var (boolean_type_node, "nonempty");
2887 gfc_add_modify (&se->pre, nonempty_var, boolean_false_node);
2888 nonempty = nonempty_var;
2889 }
2890 lab = NULL;
2891 fast = NULL;
2892 if (HONOR_NANS (DECL_MODE (limit)))
2893 {
2894 if (loop.dimen == 1)
2895 {
2896 lab = gfc_build_label_decl (NULL_TREE);
2897 TREE_USED (lab) = 1;
2898 }
2899 else
2900 {
2901 fast = gfc_create_var (boolean_type_node, "fast");
2902 gfc_add_modify (&se->pre, fast, boolean_false_node);
2903 }
2904 }
2905
6de9cd9a
DN
2906 gfc_mark_ss_chain_used (arrayss, 1);
2907 if (maskss)
2908 gfc_mark_ss_chain_used (maskss, 1);
2909 /* Generate the loop body. */
2910 gfc_start_scalarized_body (&loop, &body);
2911
2912 /* If we have a mask, only add this element if the mask is set. */
2913 if (maskss)
2914 {
2915 gfc_init_se (&maskse, NULL);
2916 gfc_copy_loopinfo_to_se (&maskse, &loop);
2917 maskse.ss = maskss;
2918 gfc_conv_expr_val (&maskse, maskexpr);
2919 gfc_add_block_to_block (&body, &maskse.pre);
2920
2921 gfc_start_block (&block);
2922 }
2923 else
2924 gfc_init_block (&block);
2925
2926 /* Compare with the current limit. */
2927 gfc_init_se (&arrayse, NULL);
2928 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2929 arrayse.ss = arrayss;
2930 gfc_conv_expr_val (&arrayse, arrayexpr);
2931 gfc_add_block_to_block (&block, &arrayse.pre);
2932
80927a56
JJ
2933 gfc_init_block (&block2);
2934
2935 if (nonempty_var)
2936 gfc_add_modify (&block2, nonempty_var, boolean_true_node);
2937
2938 if (HONOR_NANS (DECL_MODE (limit)))
2939 {
2940 tmp = fold_build2 (op == GT_EXPR ? GE_EXPR : LE_EXPR,
2941 boolean_type_node, arrayse.expr, limit);
2942 if (lab)
2943 ifbody = build1_v (GOTO_EXPR, lab);
2944 else
2945 {
2946 stmtblock_t ifblock;
2947
2948 gfc_init_block (&ifblock);
2949 gfc_add_modify (&ifblock, limit, arrayse.expr);
2950 gfc_add_modify (&ifblock, fast, boolean_true_node);
2951 ifbody = gfc_finish_block (&ifblock);
2952 }
2953 tmp = build3_v (COND_EXPR, tmp, ifbody,
2954 build_empty_stmt (input_location));
2955 gfc_add_expr_to_block (&block2, tmp);
2956 }
2957 else
2958 {
2959 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
2960 signed zeros. */
2961 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
2962 {
2963 tmp = fold_build2 (op, boolean_type_node, arrayse.expr, limit);
2964 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
2965 tmp = build3_v (COND_EXPR, tmp, ifbody,
2966 build_empty_stmt (input_location));
2967 gfc_add_expr_to_block (&block2, tmp);
2968 }
2969 else
2970 {
2971 tmp = fold_build2 (op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
2972 type, arrayse.expr, limit);
2973 gfc_add_modify (&block2, limit, tmp);
2974 }
2975 }
2976
2977 if (fast)
2978 {
2979 tree elsebody = gfc_finish_block (&block2);
2980
2981 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
2982 signed zeros. */
2983 if (HONOR_NANS (DECL_MODE (limit))
2984 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
2985 {
2986 tmp = fold_build2 (op, boolean_type_node, arrayse.expr, limit);
2987 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
2988 ifbody = build3_v (COND_EXPR, tmp, ifbody,
2989 build_empty_stmt (input_location));
2990 }
2991 else
2992 {
2993 tmp = fold_build2 (op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
2994 type, arrayse.expr, limit);
2995 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
2996 }
2997 tmp = build3_v (COND_EXPR, fast, ifbody, elsebody);
2998 gfc_add_expr_to_block (&block, tmp);
2999 }
3000 else
3001 gfc_add_block_to_block (&block, &block2);
6de9cd9a 3002
6de9cd9a
DN
3003 gfc_add_block_to_block (&block, &arrayse.post);
3004
3005 tmp = gfc_finish_block (&block);
3006 if (maskss)
923ab88c 3007 /* We enclose the above in if (mask) {...}. */
c2255bc4
AH
3008 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3009 build_empty_stmt (input_location));
6de9cd9a
DN
3010 gfc_add_expr_to_block (&body, tmp);
3011
80927a56
JJ
3012 if (lab)
3013 {
3014 gfc_trans_scalarized_loop_end (&loop, 0, &body);
3015
3016 tmp = fold_build3 (COND_EXPR, type, nonempty, nan_cst, huge_cst);
3017 gfc_add_modify (&loop.code[0], limit, tmp);
3018 gfc_add_expr_to_block (&loop.code[0], build1_v (LABEL_EXPR, lab));
3019
3020 gfc_start_block (&body);
3021
3022 /* If we have a mask, only add this element if the mask is set. */
3023 if (maskss)
3024 {
3025 gfc_init_se (&maskse, NULL);
3026 gfc_copy_loopinfo_to_se (&maskse, &loop);
3027 maskse.ss = maskss;
3028 gfc_conv_expr_val (&maskse, maskexpr);
3029 gfc_add_block_to_block (&body, &maskse.pre);
3030
3031 gfc_start_block (&block);
3032 }
3033 else
3034 gfc_init_block (&block);
3035
3036 /* Compare with the current limit. */
3037 gfc_init_se (&arrayse, NULL);
3038 gfc_copy_loopinfo_to_se (&arrayse, &loop);
3039 arrayse.ss = arrayss;
3040 gfc_conv_expr_val (&arrayse, arrayexpr);
3041 gfc_add_block_to_block (&block, &arrayse.pre);
3042
3043 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
3044 signed zeros. */
3045 if (HONOR_NANS (DECL_MODE (limit))
3046 || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
3047 {
3048 tmp = fold_build2 (op, boolean_type_node, arrayse.expr, limit);
3049 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
3050 tmp = build3_v (COND_EXPR, tmp, ifbody,
3051 build_empty_stmt (input_location));
3052 gfc_add_expr_to_block (&block, tmp);
3053 }
3054 else
3055 {
3056 tmp = fold_build2 (op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
3057 type, arrayse.expr, limit);
3058 gfc_add_modify (&block, limit, tmp);
3059 }
3060
3061 gfc_add_block_to_block (&block, &arrayse.post);
3062
3063 tmp = gfc_finish_block (&block);
3064 if (maskss)
3065 /* We enclose the above in if (mask) {...}. */
3066 tmp = build3_v (COND_EXPR, maskse.expr, tmp,
3067 build_empty_stmt (input_location));
3068 gfc_add_expr_to_block (&body, tmp);
3069 /* Avoid initializing loopvar[0] again, it should be left where
3070 it finished by the first loop. */
3071 loop.from[0] = loop.loopvar[0];
3072 }
6de9cd9a
DN
3073 gfc_trans_scalarizing_loops (&loop, &body);
3074
80927a56
JJ
3075 if (fast)
3076 {
3077 tmp = fold_build3 (COND_EXPR, type, nonempty, nan_cst, huge_cst);
3078 ifbody = build2_v (MODIFY_EXPR, limit, tmp);
3079 tmp = build3_v (COND_EXPR, fast, build_empty_stmt (input_location),
3080 ifbody);
3081 gfc_add_expr_to_block (&loop.pre, tmp);
3082 }
3083 else if (HONOR_INFINITIES (DECL_MODE (limit)) && !lab)
3084 {
3085 tmp = fold_build3 (COND_EXPR, type, nonempty, limit, huge_cst);
3086 gfc_add_modify (&loop.pre, limit, tmp);
3087 }
3088
eaf618e3
TK
3089 /* For a scalar mask, enclose the loop in an if statement. */
3090 if (maskexpr && maskss == NULL)
3091 {
80927a56
JJ
3092 tree else_stmt;
3093
eaf618e3
TK
3094 gfc_init_se (&maskse, NULL);
3095 gfc_conv_expr_val (&maskse, maskexpr);
3096 gfc_init_block (&block);
3097 gfc_add_block_to_block (&block, &loop.pre);
3098 gfc_add_block_to_block (&block, &loop.post);
3099 tmp = gfc_finish_block (&block);
3100
80927a56
JJ
3101 if (HONOR_INFINITIES (DECL_MODE (limit)))
3102 else_stmt = build2_v (MODIFY_EXPR, limit, huge_cst);
3103 else
3104 else_stmt = build_empty_stmt (input_location);
3105 tmp = build3_v (COND_EXPR, maskse.expr, tmp, else_stmt);
eaf618e3
TK
3106 gfc_add_expr_to_block (&block, tmp);
3107 gfc_add_block_to_block (&se->pre, &block);
3108 }
3109 else
3110 {
3111 gfc_add_block_to_block (&se->pre, &loop.pre);
3112 gfc_add_block_to_block (&se->pre, &loop.post);
3113 }
3114
6de9cd9a
DN
3115 gfc_cleanup_loop (&loop);
3116
3117 se->expr = limit;
3118}
3119
3120/* BTEST (i, pos) = (i & (1 << pos)) != 0. */
3121static void
3122gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
3123{
55637e51 3124 tree args[2];
6de9cd9a
DN
3125 tree type;
3126 tree tmp;
3127
55637e51
LM
3128 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3129 type = TREE_TYPE (args[0]);
6de9cd9a 3130
44855d8c
TS
3131 tmp = fold_build2 (LSHIFT_EXPR, type, build_int_cst (type, 1), args[1]);
3132 tmp = fold_build2 (BIT_AND_EXPR, type, args[0], tmp);
10c7a96f
SB
3133 tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp,
3134 build_int_cst (type, 0));
6de9cd9a
DN
3135 type = gfc_typenode_for_spec (&expr->ts);
3136 se->expr = convert (type, tmp);
3137}
3138
3139/* Generate code to perform the specified operation. */
3140static void
8fa2df72 3141gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, enum tree_code op)
6de9cd9a 3142{
55637e51 3143 tree args[2];
6de9cd9a 3144
55637e51
LM
3145 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3146 se->expr = fold_build2 (op, TREE_TYPE (args[0]), args[0], args[1]);
6de9cd9a
DN
3147}
3148
3149/* Bitwise not. */
3150static void
3151gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
3152{
3153 tree arg;
3154
55637e51 3155 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
44855d8c 3156 se->expr = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg), arg);
6de9cd9a
DN
3157}
3158
3159/* Set or clear a single bit. */
3160static void
3161gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
3162{
55637e51 3163 tree args[2];
6de9cd9a
DN
3164 tree type;
3165 tree tmp;
8fa2df72 3166 enum tree_code op;
6de9cd9a 3167
55637e51
LM
3168 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3169 type = TREE_TYPE (args[0]);
6de9cd9a 3170
55637e51 3171 tmp = fold_build2 (LSHIFT_EXPR, type, build_int_cst (type, 1), args[1]);
6de9cd9a
DN
3172 if (set)
3173 op = BIT_IOR_EXPR;
3174 else
3175 {
3176 op = BIT_AND_EXPR;
10c7a96f 3177 tmp = fold_build1 (BIT_NOT_EXPR, type, tmp);
6de9cd9a 3178 }
55637e51 3179 se->expr = fold_build2 (op, type, args[0], tmp);
6de9cd9a
DN
3180}
3181
3182/* Extract a sequence of bits.
3183 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
3184static void
3185gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
3186{
55637e51 3187 tree args[3];
6de9cd9a
DN
3188 tree type;
3189 tree tmp;
3190 tree mask;
3191
55637e51
LM
3192 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3193 type = TREE_TYPE (args[0]);
6de9cd9a 3194
b17a1b93 3195 mask = build_int_cst (type, -1);
44855d8c
TS
3196 mask = fold_build2 (LSHIFT_EXPR, type, mask, args[2]);
3197 mask = fold_build1 (BIT_NOT_EXPR, type, mask);
6de9cd9a 3198
44855d8c 3199 tmp = fold_build2 (RSHIFT_EXPR, type, args[0], args[1]);
6de9cd9a 3200
10c7a96f 3201 se->expr = fold_build2 (BIT_AND_EXPR, type, tmp, mask);
6de9cd9a
DN
3202}
3203
a119fc1c
FXC
3204/* RSHIFT (I, SHIFT) = I >> SHIFT
3205 LSHIFT (I, SHIFT) = I << SHIFT */
3206static void
3207gfc_conv_intrinsic_rlshift (gfc_se * se, gfc_expr * expr, int right_shift)
3208{
55637e51 3209 tree args[2];
a119fc1c 3210
55637e51 3211 gfc_conv_intrinsic_function_args (se, expr, args, 2);
a119fc1c
FXC
3212
3213 se->expr = fold_build2 (right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
55637e51 3214 TREE_TYPE (args[0]), args[0], args[1]);
a119fc1c
FXC
3215}
3216
56746a07
TS
3217/* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
3218 ? 0
3219 : ((shift >= 0) ? i << shift : i >> -shift)
3220 where all shifts are logical shifts. */
6de9cd9a
DN
3221static void
3222gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
3223{
55637e51 3224 tree args[2];
6de9cd9a 3225 tree type;
56746a07 3226 tree utype;
6de9cd9a 3227 tree tmp;
56746a07
TS
3228 tree width;
3229 tree num_bits;
3230 tree cond;
6de9cd9a
DN
3231 tree lshift;
3232 tree rshift;
3233
55637e51
LM
3234 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3235 type = TREE_TYPE (args[0]);
ca5ba2a3 3236 utype = unsigned_type_for (type);
6de9cd9a 3237
55637e51 3238 width = fold_build1 (ABS_EXPR, TREE_TYPE (args[1]), args[1]);
6de9cd9a 3239
56746a07 3240 /* Left shift if positive. */
55637e51 3241 lshift = fold_build2 (LSHIFT_EXPR, type, args[0], width);
56746a07 3242
de46b505
TS
3243 /* Right shift if negative.
3244 We convert to an unsigned type because we want a logical shift.
3245 The standard doesn't define the case of shifting negative
3246 numbers, and we try to be compatible with other compilers, most
3247 notably g77, here. */
44855d8c
TS
3248 rshift = fold_convert (type, fold_build2 (RSHIFT_EXPR, utype,
3249 convert (utype, args[0]), width));
56746a07 3250
55637e51
LM
3251 tmp = fold_build2 (GE_EXPR, boolean_type_node, args[1],
3252 build_int_cst (TREE_TYPE (args[1]), 0));
10c7a96f 3253 tmp = fold_build3 (COND_EXPR, type, tmp, lshift, rshift);
56746a07
TS
3254
3255 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
3256 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
3257 special case. */
8dc9f613 3258 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
10c7a96f 3259 cond = fold_build2 (GE_EXPR, boolean_type_node, width, num_bits);
56746a07 3260
10c7a96f
SB
3261 se->expr = fold_build3 (COND_EXPR, type, cond,
3262 build_int_cst (type, 0), tmp);
6de9cd9a
DN
3263}
3264
14b1261a 3265
6de9cd9a 3266/* Circular shift. AKA rotate or barrel shift. */
14b1261a 3267
6de9cd9a
DN
3268static void
3269gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
3270{
55637e51 3271 tree *args;
6de9cd9a
DN
3272 tree type;
3273 tree tmp;
3274 tree lrot;
3275 tree rrot;
e805a599 3276 tree zero;
55637e51 3277 unsigned int num_args;
6de9cd9a 3278
55637e51 3279 num_args = gfc_intrinsic_argument_list_length (expr);
1145e690 3280 args = XALLOCAVEC (tree, num_args);
55637e51
LM
3281
3282 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
3283
3284 if (num_args == 3)
6de9cd9a
DN
3285 {
3286 /* Use a library function for the 3 parameter version. */
56746a07
TS
3287 tree int4type = gfc_get_int_type (4);
3288
55637e51 3289 type = TREE_TYPE (args[0]);
56746a07
TS
3290 /* We convert the first argument to at least 4 bytes, and
3291 convert back afterwards. This removes the need for library
3292 functions for all argument sizes, and function will be
3293 aligned to at least 32 bits, so there's no loss. */
3294 if (expr->ts.kind < 4)
55637e51
LM
3295 args[0] = convert (int4type, args[0]);
3296
56746a07
TS
3297 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
3298 need loads of library functions. They cannot have values >
3299 BIT_SIZE (I) so the conversion is safe. */
55637e51
LM
3300 args[1] = convert (int4type, args[1]);
3301 args[2] = convert (int4type, args[2]);
6de9cd9a
DN
3302
3303 switch (expr->ts.kind)
3304 {
56746a07
TS
3305 case 1:
3306 case 2:
6de9cd9a
DN
3307 case 4:
3308 tmp = gfor_fndecl_math_ishftc4;
3309 break;
3310 case 8:
3311 tmp = gfor_fndecl_math_ishftc8;
3312 break;
644cb69f
FXC
3313 case 16:
3314 tmp = gfor_fndecl_math_ishftc16;
3315 break;
6de9cd9a 3316 default:
6e45f57b 3317 gcc_unreachable ();
6de9cd9a 3318 }
db3927fb
AH
3319 se->expr = build_call_expr_loc (input_location,
3320 tmp, 3, args[0], args[1], args[2]);
56746a07
TS
3321 /* Convert the result back to the original type, if we extended
3322 the first argument's width above. */
3323 if (expr->ts.kind < 4)
3324 se->expr = convert (type, se->expr);
3325
6de9cd9a
DN
3326 return;
3327 }
55637e51 3328 type = TREE_TYPE (args[0]);
6de9cd9a
DN
3329
3330 /* Rotate left if positive. */
55637e51 3331 lrot = fold_build2 (LROTATE_EXPR, type, args[0], args[1]);
6de9cd9a
DN
3332
3333 /* Rotate right if negative. */
55637e51
LM
3334 tmp = fold_build1 (NEGATE_EXPR, TREE_TYPE (args[1]), args[1]);
3335 rrot = fold_build2 (RROTATE_EXPR, type, args[0], tmp);
6de9cd9a 3336
55637e51
LM
3337 zero = build_int_cst (TREE_TYPE (args[1]), 0);
3338 tmp = fold_build2 (GT_EXPR, boolean_type_node, args[1], zero);
10c7a96f 3339 rrot = fold_build3 (COND_EXPR, type, tmp, lrot, rrot);
6de9cd9a
DN
3340
3341 /* Do nothing if shift == 0. */
55637e51
LM
3342 tmp = fold_build2 (EQ_EXPR, boolean_type_node, args[1], zero);
3343 se->expr = fold_build3 (COND_EXPR, type, tmp, args[0], rrot);
6de9cd9a
DN
3344}
3345
414f00e9
SB
3346/* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
3347 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
3348
3349 The conditional expression is necessary because the result of LEADZ(0)
3350 is defined, but the result of __builtin_clz(0) is undefined for most
3351 targets.
3352
3353 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
3354 difference in bit size between the argument of LEADZ and the C int. */
3355
3356static void
3357gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
3358{
3359 tree arg;
3360 tree arg_type;
3361 tree cond;
3362 tree result_type;
3363 tree leadz;
3364 tree bit_size;
3365 tree tmp;
0a05c536
FXC
3366 tree func;
3367 int s, argsize;
414f00e9
SB
3368
3369 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
0a05c536 3370 argsize = TYPE_PRECISION (TREE_TYPE (arg));
414f00e9
SB
3371
3372 /* Which variant of __builtin_clz* should we call? */
0a05c536
FXC
3373 if (argsize <= INT_TYPE_SIZE)
3374 {
3375 arg_type = unsigned_type_node;
3376 func = built_in_decls[BUILT_IN_CLZ];
3377 }
3378 else if (argsize <= LONG_TYPE_SIZE)
3379 {
3380 arg_type = long_unsigned_type_node;
3381 func = built_in_decls[BUILT_IN_CLZL];
3382 }
3383 else if (argsize <= LONG_LONG_TYPE_SIZE)
3384 {
3385 arg_type = long_long_unsigned_type_node;
3386 func = built_in_decls[BUILT_IN_CLZLL];
3387 }
3388 else
3389 {
3390 gcc_assert (argsize == 128);
3391 arg_type = gfc_build_uint_type (argsize);
3392 func = gfor_fndecl_clz128;
414f00e9
SB
3393 }
3394
0a05c536
FXC
3395 /* Convert the actual argument twice: first, to the unsigned type of the
3396 same size; then, to the proper argument type for the built-in
414f00e9 3397 function. But the return type is of the default INTEGER kind. */
0a05c536 3398 arg = fold_convert (gfc_build_uint_type (argsize), arg);
414f00e9
SB
3399 arg = fold_convert (arg_type, arg);
3400 result_type = gfc_get_int_type (gfc_default_integer_kind);
3401
3402 /* Compute LEADZ for the case i .ne. 0. */
0a05c536
FXC
3403 s = TYPE_PRECISION (arg_type) - argsize;
3404 tmp = fold_convert (result_type, build_call_expr (func, 1, arg));
414f00e9
SB
3405 leadz = fold_build2 (MINUS_EXPR, result_type,
3406 tmp, build_int_cst (result_type, s));
3407
3408 /* Build BIT_SIZE. */
0a05c536 3409 bit_size = build_int_cst (result_type, argsize);
414f00e9 3410
414f00e9
SB
3411 cond = fold_build2 (EQ_EXPR, boolean_type_node,
3412 arg, build_int_cst (arg_type, 0));
3413 se->expr = fold_build3 (COND_EXPR, result_type, cond, bit_size, leadz);
3414}
3415
3416/* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
3417
3418 The conditional expression is necessary because the result of TRAILZ(0)
3419 is defined, but the result of __builtin_ctz(0) is undefined for most
3420 targets. */
3421
3422static void
3423gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
3424{
3425 tree arg;
3426 tree arg_type;
3427 tree cond;
3428 tree result_type;
3429 tree trailz;
3430 tree bit_size;
0a05c536
FXC
3431 tree func;
3432 int argsize;
414f00e9
SB
3433
3434 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
0a05c536 3435 argsize = TYPE_PRECISION (TREE_TYPE (arg));
414f00e9 3436
0a05c536
FXC
3437 /* Which variant of __builtin_ctz* should we call? */
3438 if (argsize <= INT_TYPE_SIZE)
3439 {
3440 arg_type = unsigned_type_node;
3441 func = built_in_decls[BUILT_IN_CTZ];
3442 }
3443 else if (argsize <= LONG_TYPE_SIZE)
3444 {
3445 arg_type = long_unsigned_type_node;
3446 func = built_in_decls[BUILT_IN_CTZL];
3447 }
3448 else if (argsize <= LONG_LONG_TYPE_SIZE)
3449 {
3450 arg_type = long_long_unsigned_type_node;
3451 func = built_in_decls[BUILT_IN_CTZLL];
3452 }
3453 else
3454 {
3455 gcc_assert (argsize == 128);
3456 arg_type = gfc_build_uint_type (argsize);
3457 func = gfor_fndecl_ctz128;
414f00e9
SB
3458 }
3459
0a05c536
FXC
3460 /* Convert the actual argument twice: first, to the unsigned type of the
3461 same size; then, to the proper argument type for the built-in
414f00e9 3462 function. But the return type is of the default INTEGER kind. */
0a05c536 3463 arg = fold_convert (gfc_build_uint_type (argsize), arg);
414f00e9
SB
3464 arg = fold_convert (arg_type, arg);
3465 result_type = gfc_get_int_type (gfc_default_integer_kind);
3466
3467 /* Compute TRAILZ for the case i .ne. 0. */
db3927fb
AH
3468 trailz = fold_convert (result_type, build_call_expr_loc (input_location,
3469 func, 1, arg));
414f00e9
SB
3470
3471 /* Build BIT_SIZE. */
0a05c536 3472 bit_size = build_int_cst (result_type, argsize);
414f00e9 3473
414f00e9
SB
3474 cond = fold_build2 (EQ_EXPR, boolean_type_node,
3475 arg, build_int_cst (arg_type, 0));
3476 se->expr = fold_build3 (COND_EXPR, result_type, cond, bit_size, trailz);
3477}
1fbfb0e2 3478
ad5f4de2
FXC
3479/* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
3480 for types larger than "long long", we call the long long built-in for
3481 the lower and higher bits and combine the result. */
3482
3483static void
3484gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
3485{
3486 tree arg;
3487 tree arg_type;
3488 tree result_type;
3489 tree func;
3490 int argsize;
3491
3492 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3493 argsize = TYPE_PRECISION (TREE_TYPE (arg));
3494 result_type = gfc_get_int_type (gfc_default_integer_kind);
3495
3496 /* Which variant of the builtin should we call? */
3497 if (argsize <= INT_TYPE_SIZE)
3498 {
3499 arg_type = unsigned_type_node;
3500 func = built_in_decls[parity ? BUILT_IN_PARITY : BUILT_IN_POPCOUNT];
3501 }
3502 else if (argsize <= LONG_TYPE_SIZE)
3503 {
3504 arg_type = long_unsigned_type_node;
3505 func = built_in_decls[parity ? BUILT_IN_PARITYL : BUILT_IN_POPCOUNTL];
3506 }
3507 else if (argsize <= LONG_LONG_TYPE_SIZE)
3508 {
3509 arg_type = long_long_unsigned_type_node;
3510 func = built_in_decls[parity ? BUILT_IN_PARITYLL : BUILT_IN_POPCOUNTLL];
3511 }
3512 else
3513 {
3514 /* Our argument type is larger than 'long long', which mean none
3515 of the POPCOUNT builtins covers it. We thus call the 'long long'
3516 variant multiple times, and add the results. */
3517 tree utype, arg2, call1, call2;
3518
3519 /* For now, we only cover the case where argsize is twice as large
3520 as 'long long'. */
3521 gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
3522
3523 func = built_in_decls[parity ? BUILT_IN_PARITYLL : BUILT_IN_POPCOUNTLL];
3524
3525 /* Convert it to an integer, and store into a variable. */
3526 utype = gfc_build_uint_type (argsize);
3527 arg = fold_convert (utype, arg);
3528 arg = gfc_evaluate_now (arg, &se->pre);
3529
3530 /* Call the builtin twice. */
3531 call1 = build_call_expr_loc (input_location, func, 1,
3532 fold_convert (long_long_unsigned_type_node,
3533 arg));
3534
3535 arg2 = fold_build2 (RSHIFT_EXPR, utype, arg,
3536 build_int_cst (utype, LONG_LONG_TYPE_SIZE));
3537 call2 = build_call_expr_loc (input_location, func, 1,
3538 fold_convert (long_long_unsigned_type_node,
3539 arg2));
3540
3541 /* Combine the results. */
3542 if (parity)
3543 se->expr = fold_build2 (BIT_XOR_EXPR, result_type, call1, call2);
3544 else
3545 se->expr = fold_build2 (PLUS_EXPR, result_type, call1, call2);
3546
3547 return;
3548 }
3549
3550 /* Convert the actual argument twice: first, to the unsigned type of the
3551 same size; then, to the proper argument type for the built-in
3552 function. */
3553 arg = fold_convert (gfc_build_uint_type (argsize), arg);
3554 arg = fold_convert (arg_type, arg);
3555
3556 se->expr = fold_convert (result_type,
3557 build_call_expr_loc (input_location, func, 1, arg));
3558}
3559
3560
1fbfb0e2
DK
3561/* Process an intrinsic with unspecified argument-types that has an optional
3562 argument (which could be of type character), e.g. EOSHIFT. For those, we
3563 need to append the string length of the optional argument if it is not
3564 present and the type is really character.
3565 primary specifies the position (starting at 1) of the non-optional argument
3566 specifying the type and optional gives the position of the optional
3567 argument in the arglist. */
3568
3569static void
3570conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr,
3571 unsigned primary, unsigned optional)
3572{
3573 gfc_actual_arglist* prim_arg;
3574 gfc_actual_arglist* opt_arg;
3575 unsigned cur_pos;
3576 gfc_actual_arglist* arg;
3577 gfc_symbol* sym;
989ea525 3578 VEC(tree,gc) *append_args;
1fbfb0e2
DK
3579
3580 /* Find the two arguments given as position. */
3581 cur_pos = 0;
3582 prim_arg = NULL;
3583 opt_arg = NULL;
3584 for (arg = expr->value.function.actual; arg; arg = arg->next)
3585 {
3586 ++cur_pos;
3587
3588 if (cur_pos == primary)
3589 prim_arg = arg;
3590 if (cur_pos == optional)
3591 opt_arg = arg;
3592
3593 if (cur_pos >= primary && cur_pos >= optional)
3594 break;
3595 }
3596 gcc_assert (prim_arg);
3597 gcc_assert (prim_arg->expr);
3598 gcc_assert (opt_arg);
3599
3600 /* If we do have type CHARACTER and the optional argument is really absent,
3601 append a dummy 0 as string length. */
989ea525 3602 append_args = NULL;
1fbfb0e2
DK
3603 if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr)
3604 {
3605 tree dummy;
3606
3607 dummy = build_int_cst (gfc_charlen_type_node, 0);
989ea525
NF
3608 append_args = VEC_alloc (tree, gc, 1);
3609 VEC_quick_push (tree, append_args, dummy);
1fbfb0e2
DK
3610 }
3611
3612 /* Build the call itself. */
3613 sym = gfc_get_symbol_for_expr (expr);
713485cc
JW
3614 gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
3615 append_args);
1fbfb0e2
DK
3616 gfc_free (sym);
3617}
3618
3619
6de9cd9a
DN
3620/* The length of a character string. */
3621static void
3622gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
3623{
3624 tree len;
3625 tree type;
3626 tree decl;
3627 gfc_symbol *sym;
3628 gfc_se argse;
3629 gfc_expr *arg;
dd5797cc 3630 gfc_ss *ss;
6de9cd9a 3631
6e45f57b 3632 gcc_assert (!se->ss);
6de9cd9a
DN
3633
3634 arg = expr->value.function.actual->expr;
3635
3636 type = gfc_typenode_for_spec (&expr->ts);
3637 switch (arg->expr_type)
3638 {
3639 case EXPR_CONSTANT:
7d60be94 3640 len = build_int_cst (NULL_TREE, arg->value.character.length);
6de9cd9a
DN
3641 break;
3642
636da744
PT
3643 case EXPR_ARRAY:
3644 /* Obtain the string length from the function used by
3645 trans-array.c(gfc_trans_array_constructor). */
3646 len = NULL_TREE;
0ee8e250 3647 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
636da744
PT
3648 break;
3649
dd5797cc
PT
3650 case EXPR_VARIABLE:
3651 if (arg->ref == NULL
3652 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
3653 {
3654 /* This doesn't catch all cases.
3655 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
3656 and the surrounding thread. */
3657 sym = arg->symtree->n.sym;
3658 decl = gfc_get_symbol_decl (sym);
3659 if (decl == current_function_decl && sym->attr.function
6de9cd9a 3660 && (sym->result == sym))
dd5797cc
PT
3661 decl = gfc_get_fake_result_decl (sym, 0);
3662
bc21d315 3663 len = sym->ts.u.cl->backend_decl;
dd5797cc
PT
3664 gcc_assert (len);
3665 break;
6de9cd9a 3666 }
dd5797cc
PT
3667
3668 /* Otherwise fall through. */
3669
3670 default:
3671 /* Anybody stupid enough to do this deserves inefficient code. */
3672 ss = gfc_walk_expr (arg);
3673 gfc_init_se (&argse, se);
3674 if (ss == gfc_ss_terminator)
3675 gfc_conv_expr (&argse, arg);
3676 else
3677 gfc_conv_expr_descriptor (&argse, arg, ss);
3678 gfc_add_block_to_block (&se->pre, &argse.pre);
3679 gfc_add_block_to_block (&se->post, &argse.post);
3680 len = argse.string_length;
6de9cd9a
DN
3681 break;
3682 }
3683 se->expr = convert (type, len);
3684}
3685
3686/* The length of a character string not including trailing blanks. */
3687static void
3688gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
3689{
374929b2
FXC
3690 int kind = expr->value.function.actual->expr->ts.kind;
3691 tree args[2], type, fndecl;
6de9cd9a 3692
55637e51 3693 gfc_conv_intrinsic_function_args (se, expr, args, 2);
6de9cd9a 3694 type = gfc_typenode_for_spec (&expr->ts);
374929b2
FXC
3695
3696 if (kind == 1)
3697 fndecl = gfor_fndecl_string_len_trim;
3698 else if (kind == 4)
3699 fndecl = gfor_fndecl_string_len_trim_char4;
3700 else
3701 gcc_unreachable ();
3702
db3927fb
AH
3703 se->expr = build_call_expr_loc (input_location,
3704 fndecl, 2, args[0], args[1]);
6de9cd9a
DN
3705 se->expr = convert (type, se->expr);
3706}
3707
3708
3709/* Returns the starting position of a substring within a string. */
3710
3711static void
5cda5098
FXC
3712gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
3713 tree function)
6de9cd9a 3714{
0da87370 3715 tree logical4_type_node = gfc_get_logical_type (4);
6de9cd9a 3716 tree type;
55637e51
LM
3717 tree fndecl;
3718 tree *args;
3719 unsigned int num_args;
6de9cd9a 3720
1145e690 3721 args = XALLOCAVEC (tree, 5);
55637e51 3722
f5dce797 3723 /* Get number of arguments; characters count double due to the
df2fba9e 3724 string length argument. Kind= is not passed to the library
f5dce797
TB
3725 and thus ignored. */
3726 if (expr->value.function.actual->next->next->expr == NULL)
3727 num_args = 4;
3728 else
3729 num_args = 5;
3730
3731 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
6de9cd9a 3732 type = gfc_typenode_for_spec (&expr->ts);
55637e51
LM
3733
3734 if (num_args == 4)
3735 args[4] = build_int_cst (logical4_type_node, 0);
6de9cd9a 3736 else
5cda5098 3737 args[4] = convert (logical4_type_node, args[4]);
6de9cd9a 3738
5cda5098 3739 fndecl = build_addr (function, current_function_decl);
db3927fb
AH
3740 se->expr = build_call_array_loc (input_location,
3741 TREE_TYPE (TREE_TYPE (function)), fndecl,
5cda5098 3742 5, args);
6de9cd9a 3743 se->expr = convert (type, se->expr);
55637e51 3744
6de9cd9a
DN
3745}
3746
3747/* The ascii value for a single character. */
3748static void
3749gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
3750{
374929b2 3751 tree args[2], type, pchartype;
6de9cd9a 3752
55637e51
LM
3753 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3754 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
374929b2
FXC
3755 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
3756 args[1] = fold_build1 (NOP_EXPR, pchartype, args[1]);
6de9cd9a
DN
3757 type = gfc_typenode_for_spec (&expr->ts);
3758
db3927fb
AH
3759 se->expr = build_fold_indirect_ref_loc (input_location,
3760 args[1]);
6de9cd9a
DN
3761 se->expr = convert (type, se->expr);
3762}
3763
3764
3d97b1af
FXC
3765/* Intrinsic ISNAN calls __builtin_isnan. */
3766
3767static void
3768gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
3769{
3770 tree arg;
3771
3772 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
db3927fb
AH
3773 se->expr = build_call_expr_loc (input_location,
3774 built_in_decls[BUILT_IN_ISNAN], 1, arg);
e1332188 3775 STRIP_TYPE_NOPS (se->expr);
3d97b1af
FXC
3776 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3777}
3778
bae89173
FXC
3779
3780/* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
3781 their argument against a constant integer value. */
3782
3783static void
3784gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
3785{
3786 tree arg;
3787
3788 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3789 se->expr = fold_build2 (EQ_EXPR, gfc_typenode_for_spec (&expr->ts),
3790 arg, build_int_cst (TREE_TYPE (arg), value));
3791}
3792
3793
3794
6de9cd9a
DN
3795/* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
3796
3797static void
3798gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
3799{
6de9cd9a
DN
3800 tree tsource;
3801 tree fsource;
3802 tree mask;
3803 tree type;
8c13133c 3804 tree len, len2;
55637e51
LM
3805 tree *args;
3806 unsigned int num_args;
3807
3808 num_args = gfc_intrinsic_argument_list_length (expr);
1145e690 3809 args = XALLOCAVEC (tree, num_args);
6de9cd9a 3810
55637e51 3811 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
c3d0559d
TS
3812 if (expr->ts.type != BT_CHARACTER)
3813 {
55637e51
LM
3814 tsource = args[0];
3815 fsource = args[1];
3816 mask = args[2];
c3d0559d
TS
3817 }
3818 else
3819 {
3820 /* We do the same as in the non-character case, but the argument
3821 list is different because of the string length arguments. We
3822 also have to set the string length for the result. */
55637e51
LM
3823 len = args[0];
3824 tsource = args[1];
8c13133c 3825 len2 = args[2];
55637e51
LM
3826 fsource = args[3];
3827 mask = args[4];
c3d0559d 3828
fb5bc08b
DK
3829 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr->where, len, len2,
3830 &se->pre);
c3d0559d
TS
3831 se->string_length = len;
3832 }
6de9cd9a 3833 type = TREE_TYPE (tsource);
6e1b67b3
RG
3834 se->expr = fold_build3 (COND_EXPR, type, mask, tsource,
3835 fold_convert (type, fsource));
6de9cd9a
DN
3836}
3837
3838
b5a4419c
FXC
3839/* FRACTION (s) is translated into frexp (s, &dummy_int). */
3840static void
3841gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
3842{
2921157d 3843 tree arg, type, tmp, frexp;
b5a4419c 3844
2921157d 3845 frexp = builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
b5a4419c
FXC
3846
3847 type = gfc_typenode_for_spec (&expr->ts);
3848 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3849 tmp = gfc_create_var (integer_type_node, NULL);
2921157d
FXC
3850 se->expr = build_call_expr_loc (input_location, frexp, 2,
3851 fold_convert (type, arg),
3852 gfc_build_addr_expr (NULL_TREE, tmp));
b5a4419c
FXC
3853 se->expr = fold_convert (type, se->expr);
3854}
3855
3856
3857/* NEAREST (s, dir) is translated into
f6d53468 3858 tmp = copysign (HUGE_VAL, dir);
b5a4419c
FXC
3859 return nextafter (s, tmp);
3860 */
3861static void
3862gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
3863{
2921157d 3864 tree args[2], type, tmp, nextafter, copysign, huge_val;
b5a4419c 3865
2921157d
FXC
3866 nextafter = builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
3867 copysign = builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
3868 huge_val = builtin_decl_for_float_kind (BUILT_IN_HUGE_VAL, expr->ts.kind);
b5a4419c
FXC
3869
3870 type = gfc_typenode_for_spec (&expr->ts);
3871 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2921157d
FXC
3872 tmp = build_call_expr_loc (input_location, copysign, 2,
3873 build_call_expr_loc (input_location, huge_val, 0),
3874 fold_convert (type, args[1]));
3875 se->expr = build_call_expr_loc (input_location, nextafter, 2,
3876 fold_convert (type, args[0]), tmp);
b5a4419c
FXC
3877 se->expr = fold_convert (type, se->expr);
3878}
3879
3880
3881/* SPACING (s) is translated into
3882 int e;
3883 if (s == 0)
3884 res = tiny;
3885 else
3886 {
3887 frexp (s, &e);
3888 e = e - prec;
3889 e = MAX_EXPR (e, emin);
3890 res = scalbn (1., e);
3891 }
3892 return res;
3893
3894 where prec is the precision of s, gfc_real_kinds[k].digits,
3895 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
3896 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
3897
3898static void
3899gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
3900{
3901 tree arg, type, prec, emin, tiny, res, e;
2921157d
FXC
3902 tree cond, tmp, frexp, scalbn;
3903 int k;
b5a4419c
FXC
3904 stmtblock_t block;
3905
3906 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
3907 prec = build_int_cst (NULL_TREE, gfc_real_kinds[k].digits);
3908 emin = build_int_cst (NULL_TREE, gfc_real_kinds[k].min_exponent - 1);
346a77d1 3909 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
b5a4419c 3910
2921157d
FXC
3911 frexp = builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
3912 scalbn = builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
b5a4419c
FXC
3913
3914 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3915 arg = gfc_evaluate_now (arg, &se->pre);
3916
3917 type = gfc_typenode_for_spec (&expr->ts);
3918 e = gfc_create_var (integer_type_node, NULL);
3919 res = gfc_create_var (type, NULL);
3920
3921
3922 /* Build the block for s /= 0. */
3923 gfc_start_block (&block);
2921157d
FXC
3924 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
3925 gfc_build_addr_expr (NULL_TREE, e));
b5a4419c
FXC
3926 gfc_add_expr_to_block (&block, tmp);
3927
3928 tmp = fold_build2 (MINUS_EXPR, integer_type_node, e, prec);
726a989a 3929 gfc_add_modify (&block, e, fold_build2 (MAX_EXPR, integer_type_node,
db3927fb 3930 tmp, emin));
b5a4419c 3931
2921157d 3932 tmp = build_call_expr_loc (input_location, scalbn, 2,
b5a4419c 3933 build_real_from_int_cst (type, integer_one_node), e);
726a989a 3934 gfc_add_modify (&block, res, tmp);
b5a4419c
FXC
3935
3936 /* Finish by building the IF statement. */
3937 cond = fold_build2 (EQ_EXPR, boolean_type_node, arg,
3938 build_real_from_int_cst (type, integer_zero_node));
3939 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
3940 gfc_finish_block (&block));
3941
3942 gfc_add_expr_to_block (&se->pre, tmp);
3943 se->expr = res;
3944}
3945
3946
3947/* RRSPACING (s) is translated into
3948 int e;
3949 real x;
3950 x = fabs (s);
3951 if (x != 0)
3952 {
3953 frexp (s, &e);
3954 x = scalbn (x, precision - e);
3955 }
3956 return x;
3957
3958 where precision is gfc_real_kinds[k].digits. */
3959
3960static void
3961gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
3962{
2921157d
FXC
3963 tree arg, type, e, x, cond, stmt, tmp, frexp, scalbn, fabs;
3964 int prec, k;
b5a4419c
FXC
3965 stmtblock_t block;
3966
3967 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
3968 prec = gfc_real_kinds[k].digits;
2921157d
FXC
3969
3970 frexp = builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
3971 scalbn = builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
3972 fabs = builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
b5a4419c
FXC
3973
3974 type = gfc_typenode_for_spec (&expr->ts);
3975 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3976 arg = gfc_evaluate_now (arg, &se->pre);
3977
3978 e = gfc_create_var (integer_type_node, NULL);
3979 x = gfc_create_var (type, NULL);
726a989a 3980 gfc_add_modify (&se->pre, x,
2921157d 3981 build_call_expr_loc (input_location, fabs, 1, arg));
b5a4419c
FXC
3982
3983
3984 gfc_start_block (&block);
2921157d
FXC
3985 tmp = build_call_expr_loc (input_location, frexp, 2, arg,
3986 gfc_build_addr_expr (NULL_TREE, e));
b5a4419c
FXC
3987 gfc_add_expr_to_block (&block, tmp);
3988
3989 tmp = fold_build2 (MINUS_EXPR, integer_type_node,
3990 build_int_cst (NULL_TREE, prec), e);
2921157d 3991 tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
726a989a 3992 gfc_add_modify (&block, x, tmp);
b5a4419c
FXC
3993 stmt = gfc_finish_block (&block);
3994
3995 cond = fold_build2 (NE_EXPR, boolean_type_node, x,
3996 build_real_from_int_cst (type, integer_zero_node));
c2255bc4 3997 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt (input_location));
b5a4419c
FXC
3998 gfc_add_expr_to_block (&se->pre, tmp);
3999
4000 se->expr = fold_convert (type, x);
4001}
4002
4003
4004/* SCALE (s, i) is translated into scalbn (s, i). */
4005static void
4006gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
4007{
2921157d 4008 tree args[2], type, scalbn;
b5a4419c 4009
2921157d 4010 scalbn = builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
b5a4419c
FXC
4011
4012 type = gfc_typenode_for_spec (&expr->ts);
4013 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2921157d
FXC
4014 se->expr = build_call_expr_loc (input_location, scalbn, 2,
4015 fold_convert (type, args[0]),
4016 fold_convert (integer_type_node, args[1]));
b5a4419c
FXC
4017 se->expr = fold_convert (type, se->expr);
4018}
4019
4020
4021/* SET_EXPONENT (s, i) is translated into
4022 scalbn (frexp (s, &dummy_int), i). */
4023static void
4024gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
4025{
2921157d 4026 tree args[2], type, tmp, frexp, scalbn;
b5a4419c 4027
2921157d
FXC
4028 frexp = builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
4029 scalbn = builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
b5a4419c
FXC
4030
4031 type = gfc_typenode_for_spec (&expr->ts);
4032 gfc_conv_intrinsic_function_args (se, expr, args, 2);
4033
4034 tmp = gfc_create_var (integer_type_node, NULL);
2921157d
FXC
4035 tmp = build_call_expr_loc (input_location, frexp, 2,
4036 fold_convert (type, args[0]),
4037 gfc_build_addr_expr (NULL_TREE, tmp));
4038 se->expr = build_call_expr_loc (input_location, scalbn, 2, tmp,
4039 fold_convert (integer_type_node, args[1]));
b5a4419c
FXC
4040 se->expr = fold_convert (type, se->expr);
4041}
4042
4043
6de9cd9a
DN
4044static void
4045gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
4046{
4047 gfc_actual_arglist *actual;
88f206a4 4048 tree arg1;
6de9cd9a 4049 tree type;
88f206a4
TK
4050 tree fncall0;
4051 tree fncall1;
6de9cd9a
DN
4052 gfc_se argse;
4053 gfc_ss *ss;
4054
4055 gfc_init_se (&argse, NULL);
4056 actual = expr->value.function.actual;
4057
4058 ss = gfc_walk_expr (actual->expr);
6e45f57b 4059 gcc_assert (ss != gfc_ss_terminator);
6de9cd9a 4060 argse.want_pointer = 1;
ad5dd90d 4061 argse.data_not_needed = 1;
6de9cd9a
DN
4062 gfc_conv_expr_descriptor (&argse, actual->expr, ss);
4063 gfc_add_block_to_block (&se->pre, &argse.pre);
4064 gfc_add_block_to_block (&se->post, &argse.post);
88f206a4
TK
4065 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
4066
4067 /* Build the call to size0. */
db3927fb
AH
4068 fncall0 = build_call_expr_loc (input_location,
4069 gfor_fndecl_size0, 1, arg1);
6de9cd9a
DN
4070
4071 actual = actual->next;
88f206a4 4072
6de9cd9a
DN
4073 if (actual->expr)
4074 {
4075 gfc_init_se (&argse, NULL);
88f206a4
TK
4076 gfc_conv_expr_type (&argse, actual->expr,
4077 gfc_array_index_type);
6de9cd9a 4078 gfc_add_block_to_block (&se->pre, &argse.pre);
88f206a4 4079
88f206a4
TK
4080 /* Unusually, for an intrinsic, size does not exclude
4081 an optional arg2, so we must test for it. */
4082 if (actual->expr->expr_type == EXPR_VARIABLE
4083 && actual->expr->symtree->n.sym->attr.dummy
4084 && actual->expr->symtree->n.sym->attr.optional)
4085 {
4086 tree tmp;
b41b10e5 4087 /* Build the call to size1. */
db3927fb
AH
4088 fncall1 = build_call_expr_loc (input_location,
4089 gfor_fndecl_size1, 2,
b41b10e5
JJ
4090 arg1, argse.expr);
4091
9c3e90e3
TB
4092 gfc_init_se (&argse, NULL);
4093 argse.want_pointer = 1;
4094 argse.data_not_needed = 1;
4095 gfc_conv_expr (&argse, actual->expr);
4096 gfc_add_block_to_block (&se->pre, &argse.pre);
44855d8c
TS
4097 tmp = fold_build2 (NE_EXPR, boolean_type_node,
4098 argse.expr, null_pointer_node);
88f206a4 4099 tmp = gfc_evaluate_now (tmp, &se->pre);
44855d8c
TS
4100 se->expr = fold_build3 (COND_EXPR, pvoid_type_node,
4101 tmp, fncall1, fncall0);
88f206a4
TK
4102 }
4103 else
b41b10e5
JJ
4104 {
4105 se->expr = NULL_TREE;
8c3ed71e
JJ
4106 argse.expr = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4107 argse.expr, gfc_index_one_node);
b41b10e5
JJ
4108 }
4109 }
4110 else if (expr->value.function.actual->expr->rank == 1)
4111 {
8c3ed71e 4112 argse.expr = gfc_index_zero_node;
b41b10e5 4113 se->expr = NULL_TREE;
6de9cd9a
DN
4114 }
4115 else
88f206a4 4116 se->expr = fncall0;
6de9cd9a 4117
b41b10e5
JJ
4118 if (se->expr == NULL_TREE)
4119 {
4120 tree ubound, lbound;
4121
db3927fb
AH
4122 arg1 = build_fold_indirect_ref_loc (input_location,
4123 arg1);
568e8e1e
PT
4124 ubound = gfc_conv_descriptor_ubound_get (arg1, argse.expr);
4125 lbound = gfc_conv_descriptor_lbound_get (arg1, argse.expr);
b41b10e5
JJ
4126 se->expr = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4127 ubound, lbound);
4128 se->expr = fold_build2 (PLUS_EXPR, gfc_array_index_type, se->expr,
8c3ed71e 4129 gfc_index_one_node);
b41b10e5 4130 se->expr = fold_build2 (MAX_EXPR, gfc_array_index_type, se->expr,
8c3ed71e 4131 gfc_index_zero_node);
b41b10e5
JJ
4132 }
4133
6de9cd9a
DN
4134 type = gfc_typenode_for_spec (&expr->ts);
4135 se->expr = convert (type, se->expr);
4136}
4137
4138
691da334
FXC
4139/* Helper function to compute the size of a character variable,
4140 excluding the terminating null characters. The result has
4141 gfc_array_index_type type. */
4142
4143static tree
4144size_of_string_in_bytes (int kind, tree string_length)
4145{
4146 tree bytesize;
4147 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
4148
4149 bytesize = build_int_cst (gfc_array_index_type,
4150 gfc_character_kinds[i].bit_size / 8);
4151
4152 return fold_build2 (MULT_EXPR, gfc_array_index_type, bytesize,
4153 fold_convert (gfc_array_index_type, string_length));
4154}
4155
4156
fd2157ce
TS
4157static void
4158gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
4159{
4160 gfc_expr *arg;
4161 gfc_ss *ss;
4162 gfc_se argse;
fd2157ce
TS
4163 tree source_bytes;
4164 tree type;
4165 tree tmp;
4166 tree lower;
4167 tree upper;
fd2157ce
TS
4168 int n;
4169
4170 arg = expr->value.function.actual->expr;
4171
4172 gfc_init_se (&argse, NULL);
4173 ss = gfc_walk_expr (arg);
4174
fd2157ce
TS
4175 if (ss == gfc_ss_terminator)
4176 {
048510c8
JW
4177 if (arg->ts.type == BT_CLASS)
4178 gfc_add_component_ref (arg, "$data");
4179
fd2157ce 4180 gfc_conv_expr_reference (&argse, arg);
fd2157ce 4181
db3927fb
AH
4182 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
4183 argse.expr));
fd2157ce
TS
4184
4185 /* Obtain the source word length. */
4186 if (arg->ts.type == BT_CHARACTER)
8d82b242
TB
4187 se->expr = size_of_string_in_bytes (arg->ts.kind,
4188 argse.string_length);
fd2157ce 4189 else
8d82b242 4190 se->expr = fold_convert (gfc_array_index_type, size_in_bytes (type));
fd2157ce
TS
4191 }
4192 else
4193 {
8d82b242 4194 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
fd2157ce
TS
4195 argse.want_pointer = 0;
4196 gfc_conv_expr_descriptor (&argse, arg, ss);
fd2157ce
TS
4197 type = gfc_get_element_type (TREE_TYPE (argse.expr));
4198
4199 /* Obtain the argument's word length. */
4200 if (arg->ts.type == BT_CHARACTER)
691da334 4201 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
fd2157ce
TS
4202 else
4203 tmp = fold_convert (gfc_array_index_type,
4204 size_in_bytes (type));
726a989a 4205 gfc_add_modify (&argse.pre, source_bytes, tmp);
fd2157ce
TS
4206
4207 /* Obtain the size of the array in bytes. */
4208 for (n = 0; n < arg->rank; n++)
4209 {
4210 tree idx;
4211 idx = gfc_rank_cst[n];
568e8e1e
PT
4212 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
4213 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
fd2157ce
TS
4214 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4215 upper, lower);
4216 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4217 tmp, gfc_index_one_node);
4218 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
4219 tmp, source_bytes);
726a989a 4220 gfc_add_modify (&argse.pre, source_bytes, tmp);
fd2157ce 4221 }
8d82b242 4222 se->expr = source_bytes;
fd2157ce
TS
4223 }
4224
4225 gfc_add_block_to_block (&se->pre, &argse.pre);
fd2157ce
TS
4226}
4227
4228
048510c8
JW
4229static void
4230gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr)
4231{
4232 gfc_expr *arg;
4233 gfc_ss *ss;
4234 gfc_se argse,eight;
4235 tree type, result_type, tmp;
4236
4237 arg = expr->value.function.actual->expr;
4238 gfc_init_se (&eight, NULL);
4239 gfc_conv_expr (&eight, gfc_get_int_expr (expr->ts.kind, NULL, 8));
4240
4241 gfc_init_se (&argse, NULL);
4242 ss = gfc_walk_expr (arg);
4243 result_type = gfc_get_int_type (expr->ts.kind);
4244
4245 if (ss == gfc_ss_terminator)
4246 {
4247 if (arg->ts.type == BT_CLASS)
4248 {
4249 gfc_add_component_ref (arg, "$vptr");
4250 gfc_add_component_ref (arg, "$size");
4251 gfc_conv_expr (&argse, arg);
4252 tmp = fold_convert (result_type, argse.expr);
4253 goto done;
4254 }
4255
4256 gfc_conv_expr_reference (&argse, arg);
4257 type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
4258 argse.expr));
4259 }
4260 else
4261 {
4262 argse.want_pointer = 0;
4263 gfc_conv_expr_descriptor (&argse, arg, ss);
4264 type = gfc_get_element_type (TREE_TYPE (argse.expr));
4265 }
4266
4267 /* Obtain the argument's word length. */
4268 if (arg->ts.type == BT_CHARACTER)
4269 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
4270 else
4271 tmp = fold_convert (result_type, size_in_bytes (type));
4272
4273done:
4274 se->expr = fold_build2 (MULT_EXPR, result_type, tmp, eight.expr);
4275 gfc_add_block_to_block (&se->pre, &argse.pre);
4276}
4277
4278
6de9cd9a
DN
4279/* Intrinsic string comparison functions. */
4280
fd2157ce 4281static void
8fa2df72 4282gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, enum tree_code op)
6de9cd9a 4283{
55637e51 4284 tree args[4];
2dbc83d9 4285
55637e51 4286 gfc_conv_intrinsic_function_args (se, expr, args, 4);
6de9cd9a 4287
374929b2
FXC
4288 se->expr
4289 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
23b10420
JJ
4290 expr->value.function.actual->expr->ts.kind,
4291 op);
8a09ef91
FXC
4292 se->expr = fold_build2 (op, gfc_typenode_for_spec (&expr->ts), se->expr,
4293 build_int_cst (TREE_TYPE (se->expr), 0));
6de9cd9a
DN
4294}
4295
4296/* Generate a call to the adjustl/adjustr library function. */
4297static void
4298gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
4299{
55637e51 4300 tree args[3];
6de9cd9a
DN
4301 tree len;
4302 tree type;
4303 tree var;
4304 tree tmp;
4305
55637e51
LM
4306 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
4307 len = args[1];
6de9cd9a 4308
55637e51 4309 type = TREE_TYPE (args[2]);
6de9cd9a 4310 var = gfc_conv_string_tmp (se, type, len);
55637e51 4311 args[0] = var;
6de9cd9a 4312
db3927fb
AH
4313 tmp = build_call_expr_loc (input_location,
4314 fndecl, 3, args[0], args[1], args[2]);
6de9cd9a
DN
4315 gfc_add_expr_to_block (&se->pre, tmp);
4316 se->expr = var;
4317 se->string_length = len;
4318}
4319
4320
c41fea4a
PT
4321/* Generate code for the TRANSFER intrinsic:
4322 For scalar results:
4323 DEST = TRANSFER (SOURCE, MOLD)
4324 where:
4325 typeof<DEST> = typeof<MOLD>
4326 and:
4327 MOLD is scalar.
4328
4329 For array results:
4330 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
4331 where:
4332 typeof<DEST> = typeof<MOLD>
4333 and:
4334 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
0c5a42a6 4335 sizeof (DEST(0) * SIZE). */
0c5a42a6 4336static void
c41fea4a 4337gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
0c5a42a6
PT
4338{
4339 tree tmp;
c41fea4a
PT
4340 tree tmpdecl;
4341 tree ptr;
0c5a42a6
PT
4342 tree extent;
4343 tree source;
1efd1a2f 4344 tree source_type;
0c5a42a6 4345 tree source_bytes;
1efd1a2f 4346 tree mold_type;
0c5a42a6
PT
4347 tree dest_word_len;
4348 tree size_words;
4349 tree size_bytes;
4350 tree upper;
4351 tree lower;
0c5a42a6
PT
4352 tree stmt;
4353 gfc_actual_arglist *arg;
4354 gfc_se argse;
4355 gfc_ss *ss;
4356 gfc_ss_info *info;
4357 stmtblock_t block;
4358 int n;
c41fea4a 4359 bool scalar_mold;
0c5a42a6 4360
c41fea4a
PT
4361 info = NULL;
4362 if (se->loop)
4363 info = &se->ss->data.info;
0c5a42a6
PT
4364
4365 /* Convert SOURCE. The output from this stage is:-
4366 source_bytes = length of the source in bytes
4367 source = pointer to the source data. */
4368 arg = expr->value.function.actual;
c41fea4a
PT
4369
4370 /* Ensure double transfer through LOGICAL preserves all
4371 the needed bits. */
4372 if (arg->expr->expr_type == EXPR_FUNCTION
4373 && arg->expr->value.function.esym == NULL
4374 && arg->expr->value.function.isym != NULL
4375 && arg->expr->value.function.isym->id == GFC_ISYM_TRANSFER
4376 && arg->expr->ts.type == BT_LOGICAL
4377 && expr->ts.type != arg->expr->ts.type)
4378 arg->expr->value.function.name = "__transfer_in_transfer";
4379
0c5a42a6
PT
4380 gfc_init_se (&argse, NULL);
4381 ss = gfc_walk_expr (arg->expr);
4382
4383 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
4384
4385 /* Obtain the pointer to source and the length of source in bytes. */
4386 if (ss == gfc_ss_terminator)
4387 {
4388 gfc_conv_expr_reference (&argse, arg->expr);
4389 source = argse.expr;
4390
db3927fb
AH
4391 source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
4392 argse.expr));
1efd1a2f 4393
0c5a42a6 4394 /* Obtain the source word length. */
1efd1a2f 4395 if (arg->expr->ts.type == BT_CHARACTER)
691da334
FXC
4396 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
4397 argse.string_length);
1efd1a2f
PT
4398 else
4399 tmp = fold_convert (gfc_array_index_type,
4400 size_in_bytes (source_type));
0c5a42a6
PT
4401 }
4402 else
4403 {
0c5a42a6
PT
4404 argse.want_pointer = 0;
4405 gfc_conv_expr_descriptor (&argse, arg->expr, ss);
4406 source = gfc_conv_descriptor_data_get (argse.expr);
1efd1a2f 4407 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
0c5a42a6
PT
4408
4409 /* Repack the source if not a full variable array. */
c41fea4a
PT
4410 if (arg->expr->expr_type == EXPR_VARIABLE
4411 && arg->expr->ref->u.ar.type != AR_FULL)
0c5a42a6 4412 {
628c189e 4413 tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);
bdfd2ff0
TK
4414
4415 if (gfc_option.warn_array_temp)
4416 gfc_warning ("Creating array temporary at %L", &expr->where);
4417
db3927fb
AH
4418 source = build_call_expr_loc (input_location,
4419 gfor_fndecl_in_pack, 1, tmp);
0c5a42a6
PT
4420 source = gfc_evaluate_now (source, &argse.pre);
4421
4422 /* Free the temporary. */
4423 gfc_start_block (&block);
1529b8d9 4424 tmp = gfc_call_free (convert (pvoid_type_node, source));
0c5a42a6
PT
4425 gfc_add_expr_to_block (&block, tmp);
4426 stmt = gfc_finish_block (&block);
4427
4428 /* Clean up if it was repacked. */
4429 gfc_init_block (&block);
4430 tmp = gfc_conv_array_data (argse.expr);
44855d8c 4431 tmp = fold_build2 (NE_EXPR, boolean_type_node, source, tmp);
c2255bc4
AH
4432 tmp = build3_v (COND_EXPR, tmp, stmt,
4433 build_empty_stmt (input_location));
0c5a42a6
PT
4434 gfc_add_expr_to_block (&block, tmp);
4435 gfc_add_block_to_block (&block, &se->post);
4436 gfc_init_block (&se->post);
4437 gfc_add_block_to_block (&se->post, &block);
4438 }
4439
4440 /* Obtain the source word length. */
1efd1a2f 4441 if (arg->expr->ts.type == BT_CHARACTER)
691da334
FXC
4442 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
4443 argse.string_length);
1efd1a2f
PT
4444 else
4445 tmp = fold_convert (gfc_array_index_type,
4446 size_in_bytes (source_type));
0c5a42a6
PT
4447
4448 /* Obtain the size of the array in bytes. */
4449 extent = gfc_create_var (gfc_array_index_type, NULL);
4450 for (n = 0; n < arg->expr->rank; n++)
4451 {
4452 tree idx;
4453 idx = gfc_rank_cst[n];
726a989a 4454 gfc_add_modify (&argse.pre, source_bytes, tmp);
568e8e1e
PT
4455 lower = gfc_conv_descriptor_lbound_get (argse.expr, idx);
4456 upper = gfc_conv_descriptor_ubound_get (argse.expr, idx);
fd2157ce
TS
4457 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4458 upper, lower);
726a989a 4459 gfc_add_modify (&argse.pre, extent, tmp);
fd2157ce
TS
4460 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4461 extent, gfc_index_one_node);
4462 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
4463 tmp, source_bytes);
0c5a42a6
PT
4464 }
4465 }
4466
726a989a 4467 gfc_add_modify (&argse.pre, source_bytes, tmp);
0c5a42a6
PT
4468 gfc_add_block_to_block (&se->pre, &argse.pre);
4469 gfc_add_block_to_block (&se->post, &argse.post);
4470
1efd1a2f
PT
4471 /* Now convert MOLD. The outputs are:
4472 mold_type = the TREE type of MOLD
0c5a42a6
PT
4473 dest_word_len = destination word length in bytes. */
4474 arg = arg->next;
4475
4476 gfc_init_se (&argse, NULL);
4477 ss = gfc_walk_expr (arg->expr);
4478
c41fea4a
PT
4479 scalar_mold = arg->expr->rank == 0;
4480
0c5a42a6
PT
4481 if (ss == gfc_ss_terminator)
4482 {
4483 gfc_conv_expr_reference (&argse, arg->expr);
db3927fb
AH
4484 mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
4485 argse.expr));
0c5a42a6
PT
4486 }
4487 else
4488 {
4489 gfc_init_se (&argse, NULL);
4490 argse.want_pointer = 0;
4491 gfc_conv_expr_descriptor (&argse, arg->expr, ss);
1efd1a2f 4492 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
0c5a42a6
PT
4493 }
4494
c41fea4a
PT
4495 gfc_add_block_to_block (&se->pre, &argse.pre);
4496 gfc_add_block_to_block (&se->post, &argse.post);
4497
27a4e072
JJ
4498 if (strcmp (expr->value.function.name, "__transfer_in_transfer") == 0)
4499 {
4500 /* If this TRANSFER is nested in another TRANSFER, use a type
4501 that preserves all bits. */
4502 if (arg->expr->ts.type == BT_LOGICAL)
4503 mold_type = gfc_get_int_type (arg->expr->ts.kind);
4504 }
4505
1efd1a2f
PT
4506 if (arg->expr->ts.type == BT_CHARACTER)
4507 {
691da334 4508 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
1efd1a2f
PT
4509 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
4510 }
4511 else
4512 tmp = fold_convert (gfc_array_index_type,
4513 size_in_bytes (mold_type));
4514
0c5a42a6 4515 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
726a989a 4516 gfc_add_modify (&se->pre, dest_word_len, tmp);
0c5a42a6
PT
4517
4518 /* Finally convert SIZE, if it is present. */
4519 arg = arg->next;
4520 size_words = gfc_create_var (gfc_array_index_type, NULL);
4521
4522 if (arg->expr)
4523 {
4524 gfc_init_se (&argse, NULL);
4525 gfc_conv_expr_reference (&argse, arg->expr);
4526 tmp = convert (gfc_array_index_type,
db3927fb
AH
4527 build_fold_indirect_ref_loc (input_location,
4528 argse.expr));
0c5a42a6
PT
4529 gfc_add_block_to_block (&se->pre, &argse.pre);
4530 gfc_add_block_to_block (&se->post, &argse.post);
4531 }
4532 else
4533 tmp = NULL_TREE;
4534
c41fea4a
PT
4535 /* Separate array and scalar results. */
4536 if (scalar_mold && tmp == NULL_TREE)
4537 goto scalar_transfer;
4538
0c5a42a6
PT
4539 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
4540 if (tmp != NULL_TREE)
c41fea4a
PT
4541 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
4542 tmp, dest_word_len);
0c5a42a6
PT
4543 else
4544 tmp = source_bytes;
4545
726a989a
RB
4546 gfc_add_modify (&se->pre, size_bytes, tmp);
4547 gfc_add_modify (&se->pre, size_words,
fd2157ce
TS
4548 fold_build2 (CEIL_DIV_EXPR, gfc_array_index_type,
4549 size_bytes, dest_word_len));
0c5a42a6
PT
4550
4551 /* Evaluate the bounds of the result. If the loop range exists, we have
4552 to check if it is too large. If so, we modify loop->to be consistent
4553 with min(size, size(source)). Otherwise, size is made consistent with
4554 the loop range, so that the right number of bytes is transferred.*/
4555 n = se->loop->order[0];
4556 if (se->loop->to[n] != NULL_TREE)
4557 {
4558 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4559 se->loop->to[n], se->loop->from[n]);
fd2157ce
TS
4560 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4561 tmp, gfc_index_one_node);
4562 tmp = fold_build2 (MIN_EXPR, gfc_array_index_type,
4563 tmp, size_words);
726a989a
RB
4564 gfc_add_modify (&se->pre, size_words, tmp);
4565 gfc_add_modify (&se->pre, size_bytes,
fd2157ce
TS
4566 fold_build2 (MULT_EXPR, gfc_array_index_type,
4567 size_words, dest_word_len));
4568 upper = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4569 size_words, se->loop->from[n]);
4570 upper = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4571 upper, gfc_index_one_node);
0c5a42a6
PT
4572 }
4573 else
4574 {
fd2157ce
TS
4575 upper = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4576 size_words, gfc_index_one_node);
0c5a42a6
PT
4577 se->loop->from[n] = gfc_index_zero_node;
4578 }
4579
4580 se->loop->to[n] = upper;
4581
4582 /* Build a destination descriptor, using the pointer, source, as the
c41fea4a 4583 data field. */
0c5a42a6 4584 gfc_trans_create_temp_array (&se->pre, &se->post, se->loop,
12f681a0 4585 info, mold_type, NULL_TREE, false, true, false,
bdfd2ff0 4586 &expr->where);
1efd1a2f
PT
4587
4588 /* Cast the pointer to the result. */
4589 tmp = gfc_conv_descriptor_data_get (info->descriptor);
4590 tmp = fold_convert (pvoid_type_node, tmp);
0c5a42a6 4591
014057c5 4592 /* Use memcpy to do the transfer. */
db3927fb
AH
4593 tmp = build_call_expr_loc (input_location,
4594 built_in_decls[BUILT_IN_MEMCPY],
5039610b 4595 3,
1efd1a2f 4596 tmp,
5039610b 4597 fold_convert (pvoid_type_node, source),
c41fea4a
PT
4598 fold_build2 (MIN_EXPR, gfc_array_index_type,
4599 size_bytes, source_bytes));
014057c5
PT
4600 gfc_add_expr_to_block (&se->pre, tmp);
4601
0c5a42a6
PT
4602 se->expr = info->descriptor;
4603 if (expr->ts.type == BT_CHARACTER)
4604 se->string_length = dest_word_len;
0c5a42a6 4605
c41fea4a 4606 return;
0c5a42a6 4607
c41fea4a
PT
4608/* Deal with scalar results. */
4609scalar_transfer:
4610 extent = fold_build2 (MIN_EXPR, gfc_array_index_type,
4611 dest_word_len, source_bytes);
c0f81f78
PT
4612 extent = fold_build2 (MAX_EXPR, gfc_array_index_type,
4613 extent, gfc_index_zero_node);
6de9cd9a 4614
c41fea4a
PT
4615 if (expr->ts.type == BT_CHARACTER)
4616 {
4617 tree direct;
4618 tree indirect;
6de9cd9a 4619
c41fea4a
PT
4620 ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
4621 tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
4622 "transfer");
6de9cd9a 4623
c41fea4a
PT
4624 /* If source is longer than the destination, use a pointer to
4625 the source directly. */
4626 gfc_init_block (&block);
4627 gfc_add_modify (&block, tmpdecl, ptr);
4628 direct = gfc_finish_block (&block);
85d6cbd3 4629
c41fea4a
PT
4630 /* Otherwise, allocate a string with the length of the destination
4631 and copy the source into it. */
4632 gfc_init_block (&block);
4633 tmp = gfc_get_pchar_type (expr->ts.kind);
4634 tmp = gfc_call_malloc (&block, tmp, dest_word_len);
4635 gfc_add_modify (&block, tmpdecl,
4636 fold_convert (TREE_TYPE (ptr), tmp));
db3927fb
AH
4637 tmp = build_call_expr_loc (input_location,
4638 built_in_decls[BUILT_IN_MEMCPY], 3,
c41fea4a
PT
4639 fold_convert (pvoid_type_node, tmpdecl),
4640 fold_convert (pvoid_type_node, ptr),
4641 extent);
4642 gfc_add_expr_to_block (&block, tmp);
4643 indirect = gfc_finish_block (&block);
4644
4645 /* Wrap it up with the condition. */
4646 tmp = fold_build2 (LE_EXPR, boolean_type_node,
4647 dest_word_len, source_bytes);
4648 tmp = build3_v (COND_EXPR, tmp, direct, indirect);
4649 gfc_add_expr_to_block (&se->pre, tmp);
4650
4651 se->expr = tmpdecl;
4652 se->string_length = dest_word_len;
6de9cd9a
DN
4653 }
4654 else
4655 {
c41fea4a
PT
4656 tmpdecl = gfc_create_var (mold_type, "transfer");
4657
4658 ptr = convert (build_pointer_type (mold_type), source);
85d6cbd3
AP
4659
4660 /* Use memcpy to do the transfer. */
628c189e 4661 tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
db3927fb
AH
4662 tmp = build_call_expr_loc (input_location,
4663 built_in_decls[BUILT_IN_MEMCPY], 3,
5039610b
SL
4664 fold_convert (pvoid_type_node, tmp),
4665 fold_convert (pvoid_type_node, ptr),
c41fea4a 4666 extent);
85d6cbd3
AP
4667 gfc_add_expr_to_block (&se->pre, tmp);
4668
4669 se->expr = tmpdecl;
6de9cd9a
DN
4670 }
4671}
4672
4673
4674/* Generate code for the ALLOCATED intrinsic.
4675 Generate inline code that directly check the address of the argument. */
4676
4677static void
4678gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
4679{
4680 gfc_actual_arglist *arg1;
4681 gfc_se arg1se;
4682 gfc_ss *ss1;
4683 tree tmp;
4684
4685 gfc_init_se (&arg1se, NULL);
4686 arg1 = expr->value.function.actual;
4687 ss1 = gfc_walk_expr (arg1->expr);
6de9cd9a 4688
2fbd4117
JW
4689 if (ss1 == gfc_ss_terminator)
4690 {
4691 /* Allocatable scalar. */
4692 arg1se.want_pointer = 1;
f8dde8af
JW
4693 if (arg1->expr->ts.type == BT_CLASS)
4694 gfc_add_component_ref (arg1->expr, "$data");
2fbd4117
JW
4695 gfc_conv_expr (&arg1se, arg1->expr);
4696 tmp = arg1se.expr;
4697 }
4698 else
4699 {
4700 /* Allocatable array. */
4701 arg1se.descriptor_only = 1;
4702 gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1);
4703 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
4704 }
4705
44855d8c
TS
4706 tmp = fold_build2 (NE_EXPR, boolean_type_node,
4707 tmp, fold_convert (TREE_TYPE (tmp), null_pointer_node));
6de9cd9a
DN
4708 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
4709}
4710
4711
4712/* Generate code for the ASSOCIATED intrinsic.
4713 If both POINTER and TARGET are arrays, generate a call to library function
4714 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
4715 In other cases, generate inline code that directly compare the address of
4716 POINTER with the address of TARGET. */
4717
4718static void
4719gfc_conv_associated (gfc_se *se, gfc_expr *expr)
4720{
4721 gfc_actual_arglist *arg1;
4722 gfc_actual_arglist *arg2;
4723 gfc_se arg1se;
4724 gfc_se arg2se;
4725 tree tmp2;
4726 tree tmp;
f5b854f2
PT
4727 tree nonzero_charlen;
4728 tree nonzero_arraylen;
6de9cd9a
DN
4729 gfc_ss *ss1, *ss2;
4730
4731 gfc_init_se (&arg1se, NULL);
4732 gfc_init_se (&arg2se, NULL);
4733 arg1 = expr->value.function.actual;
e56817db
TB
4734 if (arg1->expr->ts.type == BT_CLASS)
4735 gfc_add_component_ref (arg1->expr, "$data");
6de9cd9a
DN
4736 arg2 = arg1->next;
4737 ss1 = gfc_walk_expr (arg1->expr);
4738
4739 if (!arg2->expr)
4740 {
4741 /* No optional target. */
4742 if (ss1 == gfc_ss_terminator)
4743 {
4744 /* A pointer to a scalar. */
4745 arg1se.want_pointer = 1;
4746 gfc_conv_expr (&arg1se, arg1->expr);
4747 tmp2 = arg1se.expr;
4748 }
4749 else
4750 {
4751 /* A pointer to an array. */
dd5797cc 4752 gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1);
4c73896d 4753 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
6de9cd9a 4754 }
98efaf34
FXC
4755 gfc_add_block_to_block (&se->pre, &arg1se.pre);
4756 gfc_add_block_to_block (&se->post, &arg1se.post);
44855d8c
TS
4757 tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp2,
4758 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
6de9cd9a
DN
4759 se->expr = tmp;
4760 }
4761 else
4762 {
4763 /* An optional target. */
0e3b941e
JW
4764 if (arg2->expr->ts.type == BT_CLASS)
4765 gfc_add_component_ref (arg2->expr, "$data");
6de9cd9a 4766 ss2 = gfc_walk_expr (arg2->expr);
699fa7aa
PT
4767
4768 nonzero_charlen = NULL_TREE;
4769 if (arg1->expr->ts.type == BT_CHARACTER)
44855d8c 4770 nonzero_charlen = fold_build2 (NE_EXPR, boolean_type_node,
bc21d315 4771 arg1->expr->ts.u.cl->backend_decl,
44855d8c 4772 integer_zero_node);
699fa7aa 4773
6de9cd9a
DN
4774 if (ss1 == gfc_ss_terminator)
4775 {
4776 /* A pointer to a scalar. */
6e45f57b 4777 gcc_assert (ss2 == gfc_ss_terminator);
6de9cd9a
DN
4778 arg1se.want_pointer = 1;
4779 gfc_conv_expr (&arg1se, arg1->expr);
4780 arg2se.want_pointer = 1;
4781 gfc_conv_expr (&arg2se, arg2->expr);
98efaf34
FXC
4782 gfc_add_block_to_block (&se->pre, &arg1se.pre);
4783 gfc_add_block_to_block (&se->post, &arg1se.post);
44855d8c
TS
4784 tmp = fold_build2 (EQ_EXPR, boolean_type_node,
4785 arg1se.expr, arg2se.expr);
4786 tmp2 = fold_build2 (NE_EXPR, boolean_type_node,
4787 arg1se.expr, null_pointer_node);
4788 se->expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
4789 tmp, tmp2);
6de9cd9a
DN
4790 }
4791 else
4792 {
699fa7aa
PT
4793 /* An array pointer of zero length is not associated if target is
4794 present. */
4795 arg1se.descriptor_only = 1;
4796 gfc_conv_expr_lhs (&arg1se, arg1->expr);
568e8e1e 4797 tmp = gfc_conv_descriptor_stride_get (arg1se.expr,
699fa7aa 4798 gfc_rank_cst[arg1->expr->rank - 1]);
44855d8c
TS
4799 nonzero_arraylen = fold_build2 (NE_EXPR, boolean_type_node, tmp,
4800 build_int_cst (TREE_TYPE (tmp), 0));
699fa7aa 4801
6de9cd9a 4802 /* A pointer to an array, call library function _gfor_associated. */
6e45f57b 4803 gcc_assert (ss2 != gfc_ss_terminator);
6de9cd9a
DN
4804 arg1se.want_pointer = 1;
4805 gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1);
699fa7aa 4806
6de9cd9a
DN
4807 arg2se.want_pointer = 1;
4808 gfc_conv_expr_descriptor (&arg2se, arg2->expr, ss2);
4809 gfc_add_block_to_block (&se->pre, &arg2se.pre);
4810 gfc_add_block_to_block (&se->post, &arg2se.post);
db3927fb
AH
4811 se->expr = build_call_expr_loc (input_location,
4812 gfor_fndecl_associated, 2,
8a09ef91
FXC
4813 arg1se.expr, arg2se.expr);
4814 se->expr = convert (boolean_type_node, se->expr);
44855d8c
TS
4815 se->expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
4816 se->expr, nonzero_arraylen);
6de9cd9a 4817 }
699fa7aa
PT
4818
4819 /* If target is present zero character length pointers cannot
4820 be associated. */
4821 if (nonzero_charlen != NULL_TREE)
44855d8c
TS
4822 se->expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
4823 se->expr, nonzero_charlen);
699fa7aa
PT
4824 }
4825
6de9cd9a
DN
4826 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
4827}
4828
4829
cf2b3c22
TB
4830/* Generate code for the SAME_TYPE_AS intrinsic.
4831 Generate inline code that directly checks the vindices. */
4832
4833static void
4834gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
4835{
4836 gfc_expr *a, *b;
4837 gfc_se se1, se2;
4838 tree tmp;
4839
4840 gfc_init_se (&se1, NULL);
4841 gfc_init_se (&se2, NULL);
4842
4843 a = expr->value.function.actual->expr;
4844 b = expr->value.function.actual->next->expr;
4845
4846 if (a->ts.type == BT_CLASS)
7c1dab0d
JW
4847 {
4848 gfc_add_component_ref (a, "$vptr");
4849 gfc_add_component_ref (a, "$hash");
4850 }
cf2b3c22 4851 else if (a->ts.type == BT_DERIVED)
b7e75771
JD
4852 a = gfc_get_int_expr (gfc_default_integer_kind, NULL,
4853 a->ts.u.derived->hash_value);
cf2b3c22
TB
4854
4855 if (b->ts.type == BT_CLASS)
7c1dab0d
JW
4856 {
4857 gfc_add_component_ref (b, "$vptr");
4858 gfc_add_component_ref (b, "$hash");
4859 }
cf2b3c22 4860 else if (b->ts.type == BT_DERIVED)
b7e75771
JD
4861 b = gfc_get_int_expr (gfc_default_integer_kind, NULL,
4862 b->ts.u.derived->hash_value);
cf2b3c22
TB
4863
4864 gfc_conv_expr (&se1, a);
4865 gfc_conv_expr (&se2, b);
4866
4867 tmp = fold_build2 (EQ_EXPR, boolean_type_node,
4868 se1.expr, fold_convert (TREE_TYPE (se1.expr), se2.expr));
4869 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
4870}
4871
4872
a39fafac
FXC
4873/* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
4874
4875static void
4876gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
4877{
4878 tree args[2];
4879
4880 gfc_conv_intrinsic_function_args (se, expr, args, 2);
db3927fb
AH
4881 se->expr = build_call_expr_loc (input_location,
4882 gfor_fndecl_sc_kind, 2, args[0], args[1]);
a39fafac
FXC
4883 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
4884}
4885
4886
6de9cd9a
DN
4887/* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
4888
4889static void
26ef8a2c 4890gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
6de9cd9a 4891{
26ef8a2c 4892 tree arg, type;
6de9cd9a 4893
55637e51 4894 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
26ef8a2c
SK
4895
4896 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
4897 type = gfc_get_int_type (4);
628c189e 4898 arg = gfc_build_addr_expr (NULL_TREE, fold_convert (type, arg));
26ef8a2c
SK
4899
4900 /* Convert it to the required type. */
4901 type = gfc_typenode_for_spec (&expr->ts);
db3927fb
AH
4902 se->expr = build_call_expr_loc (input_location,
4903 gfor_fndecl_si_kind, 1, arg);
26ef8a2c 4904 se->expr = fold_convert (type, se->expr);
6de9cd9a
DN
4905}
4906
26ef8a2c 4907
6de9cd9a
DN
4908/* Generate code for SELECTED_REAL_KIND (P, R) intrinsic function. */
4909
4910static void
26ef8a2c 4911gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
6de9cd9a
DN
4912{
4913 gfc_actual_arglist *actual;
3bb06db4 4914 tree type;
6de9cd9a 4915 gfc_se argse;
3bb06db4 4916 VEC(tree,gc) *args = NULL;
6de9cd9a 4917
6de9cd9a
DN
4918 for (actual = expr->value.function.actual; actual; actual = actual->next)
4919 {
4920 gfc_init_se (&argse, se);
4921
4922 /* Pass a NULL pointer for an absent arg. */
4923 if (actual->expr == NULL)
4924 argse.expr = null_pointer_node;
4925 else
26ef8a2c
SK
4926 {
4927 gfc_typespec ts;
44000dbb
JD
4928 gfc_clear_ts (&ts);
4929
26ef8a2c
SK
4930 if (actual->expr->ts.kind != gfc_c_int_kind)
4931 {
4932 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
4933 ts.type = BT_INTEGER;
4934 ts.kind = gfc_c_int_kind;
4935 gfc_convert_type (actual->expr, &ts, 2);
4936 }
4937 gfc_conv_expr_reference (&argse, actual->expr);
4938 }
6de9cd9a
DN
4939
4940 gfc_add_block_to_block (&se->pre, &argse.pre);
4941 gfc_add_block_to_block (&se->post, &argse.post);
3bb06db4 4942 VEC_safe_push (tree, gc, args, argse.expr);
6de9cd9a 4943 }
26ef8a2c
SK
4944
4945 /* Convert it to the required type. */
4946 type = gfc_typenode_for_spec (&expr->ts);
3bb06db4
NF
4947 se->expr = build_call_expr_loc_vec (input_location,
4948 gfor_fndecl_sr_kind, args);
26ef8a2c 4949 se->expr = fold_convert (type, se->expr);
6de9cd9a
DN
4950}
4951
4952
4953/* Generate code for TRIM (A) intrinsic function. */
4954
4955static void
4956gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
4957{
4958 tree var;
4959 tree len;
4960 tree addr;
4961 tree tmp;
6de9cd9a 4962 tree cond;
55637e51 4963 tree fndecl;
374929b2 4964 tree function;
55637e51
LM
4965 tree *args;
4966 unsigned int num_args;
6de9cd9a 4967
55637e51 4968 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1145e690 4969 args = XALLOCAVEC (tree, num_args);
6de9cd9a 4970
691da334 4971 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
6de9cd9a 4972 addr = gfc_build_addr_expr (ppvoid_type_node, var);
6cd8d93a 4973 len = gfc_create_var (gfc_charlen_type_node, "len");
6de9cd9a 4974
55637e51 4975 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
628c189e 4976 args[0] = gfc_build_addr_expr (NULL_TREE, len);
55637e51 4977 args[1] = addr;
b36cd00b 4978
374929b2
FXC
4979 if (expr->ts.kind == 1)
4980 function = gfor_fndecl_string_trim;
4981 else if (expr->ts.kind == 4)
4982 function = gfor_fndecl_string_trim_char4;
4983 else
4984 gcc_unreachable ();
4985
4986 fndecl = build_addr (function, current_function_decl);
db3927fb
AH
4987 tmp = build_call_array_loc (input_location,
4988 TREE_TYPE (TREE_TYPE (function)), fndecl,
374929b2 4989 num_args, args);
6de9cd9a
DN
4990 gfc_add_expr_to_block (&se->pre, tmp);
4991
4992 /* Free the temporary afterwards, if necessary. */
44855d8c
TS
4993 cond = fold_build2 (GT_EXPR, boolean_type_node,
4994 len, build_int_cst (TREE_TYPE (len), 0));
1529b8d9 4995 tmp = gfc_call_free (var);
c2255bc4 4996 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
6de9cd9a
DN
4997 gfc_add_expr_to_block (&se->post, tmp);
4998
4999 se->expr = var;
5000 se->string_length = len;
5001}
5002
5003
5004/* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
5005
5006static void
5007gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
5008{
55637e51 5009 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
f1412ca5 5010 tree type, cond, tmp, count, exit_label, n, max, largest;
d393bbd7 5011 tree size;
f1412ca5
FXC
5012 stmtblock_t block, body;
5013 int i;
6de9cd9a 5014
691da334 5015 /* We store in charsize the size of a character. */
d393bbd7
FXC
5016 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
5017 size = build_int_cst (size_type_node, gfc_character_kinds[i].bit_size / 8);
5018
f1412ca5 5019 /* Get the arguments. */
55637e51
LM
5020 gfc_conv_intrinsic_function_args (se, expr, args, 3);
5021 slen = fold_convert (size_type_node, gfc_evaluate_now (args[0], &se->pre));
5022 src = args[1];
5023 ncopies = gfc_evaluate_now (args[2], &se->pre);
f1412ca5
FXC
5024 ncopies_type = TREE_TYPE (ncopies);
5025
5026 /* Check that NCOPIES is not negative. */
a14fb6fa 5027 cond = fold_build2 (LT_EXPR, boolean_type_node, ncopies,
f1412ca5 5028 build_int_cst (ncopies_type, 0));
0d52899f 5029 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
c8fe94c7
FXC
5030 "Argument NCOPIES of REPEAT intrinsic is negative "
5031 "(its value is %lld)",
5032 fold_convert (long_integer_type_node, ncopies));
a14fb6fa 5033
f1412ca5
FXC
5034 /* If the source length is zero, any non negative value of NCOPIES
5035 is valid, and nothing happens. */
5036 n = gfc_create_var (ncopies_type, "ncopies");
5037 cond = fold_build2 (EQ_EXPR, boolean_type_node, slen,
5038 build_int_cst (size_type_node, 0));
5039 tmp = fold_build3 (COND_EXPR, ncopies_type, cond,
5040 build_int_cst (ncopies_type, 0), ncopies);
726a989a 5041 gfc_add_modify (&se->pre, n, tmp);
f1412ca5
FXC
5042 ncopies = n;
5043
5044 /* Check that ncopies is not too large: ncopies should be less than
5045 (or equal to) MAX / slen, where MAX is the maximal integer of
5046 the gfc_charlen_type_node type. If slen == 0, we need a special
5047 case to avoid the division by zero. */
5048 i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
5049 max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_charlen_int_kind);
5050 max = fold_build2 (TRUNC_DIV_EXPR, size_type_node,
5051 fold_convert (size_type_node, max), slen);
5052 largest = TYPE_PRECISION (size_type_node) > TYPE_PRECISION (ncopies_type)
5053 ? size_type_node : ncopies_type;
5054 cond = fold_build2 (GT_EXPR, boolean_type_node,
5055 fold_convert (largest, ncopies),
5056 fold_convert (largest, max));
5057 tmp = fold_build2 (EQ_EXPR, boolean_type_node, slen,
5058 build_int_cst (size_type_node, 0));
5059 cond = fold_build3 (COND_EXPR, boolean_type_node, tmp, boolean_false_node,
5060 cond);
0d52899f 5061 gfc_trans_runtime_check (true, false, cond, &se->pre, &expr->where,
c8fe94c7 5062 "Argument NCOPIES of REPEAT intrinsic is too large");
f1412ca5 5063
a14fb6fa 5064 /* Compute the destination length. */
553b66ad
RG
5065 dlen = fold_build2 (MULT_EXPR, gfc_charlen_type_node,
5066 fold_convert (gfc_charlen_type_node, slen),
5067 fold_convert (gfc_charlen_type_node, ncopies));
bc21d315 5068 type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
f1412ca5
FXC
5069 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
5070
5071 /* Generate the code to do the repeat operation:
5072 for (i = 0; i < ncopies; i++)
d393bbd7 5073 memmove (dest + (i * slen * size), src, slen*size); */
f1412ca5
FXC
5074 gfc_start_block (&block);
5075 count = gfc_create_var (ncopies_type, "count");
726a989a 5076 gfc_add_modify (&block, count, build_int_cst (ncopies_type, 0));
f1412ca5
FXC
5077 exit_label = gfc_build_label_decl (NULL_TREE);
5078
5079 /* Start the loop body. */
5080 gfc_start_block (&body);
6de9cd9a 5081
f1412ca5
FXC
5082 /* Exit the loop if count >= ncopies. */
5083 cond = fold_build2 (GE_EXPR, boolean_type_node, count, ncopies);
5084 tmp = build1_v (GOTO_EXPR, exit_label);
5085 TREE_USED (exit_label) = 1;
5086 tmp = fold_build3 (COND_EXPR, void_type_node, cond, tmp,
c2255bc4 5087 build_empty_stmt (input_location));
f1412ca5
FXC
5088 gfc_add_expr_to_block (&body, tmp);
5089
d393bbd7 5090 /* Call memmove (dest + (i*slen*size), src, slen*size). */
553b66ad
RG
5091 tmp = fold_build2 (MULT_EXPR, gfc_charlen_type_node,
5092 fold_convert (gfc_charlen_type_node, slen),
f1412ca5 5093 fold_convert (gfc_charlen_type_node, count));
d393bbd7
FXC
5094 tmp = fold_build2 (MULT_EXPR, gfc_charlen_type_node,
5095 tmp, fold_convert (gfc_charlen_type_node, size));
5096 tmp = fold_build2 (POINTER_PLUS_EXPR, pvoid_type_node,
5097 fold_convert (pvoid_type_node, dest),
5be014d5 5098 fold_convert (sizetype, tmp));
db3927fb
AH
5099 tmp = build_call_expr_loc (input_location,
5100 built_in_decls[BUILT_IN_MEMMOVE], 3, tmp, src,
d393bbd7
FXC
5101 fold_build2 (MULT_EXPR, size_type_node, slen,
5102 fold_convert (size_type_node, size)));
f1412ca5
FXC
5103 gfc_add_expr_to_block (&body, tmp);
5104
5105 /* Increment count. */
44855d8c
TS
5106 tmp = fold_build2 (PLUS_EXPR, ncopies_type,
5107 count, build_int_cst (TREE_TYPE (count), 1));
726a989a 5108 gfc_add_modify (&body, count, tmp);
f1412ca5
FXC
5109
5110 /* Build the loop. */
5111 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
5112 gfc_add_expr_to_block (&block, tmp);
5113
5114 /* Add the exit label. */
5115 tmp = build1_v (LABEL_EXPR, exit_label);
5116 gfc_add_expr_to_block (&block, tmp);
5117
5118 /* Finish the block. */
5119 tmp = gfc_finish_block (&block);
6de9cd9a
DN
5120 gfc_add_expr_to_block (&se->pre, tmp);
5121
f1412ca5
FXC
5122 /* Set the result value. */
5123 se->expr = dest;
5124 se->string_length = dlen;
6de9cd9a
DN
5125}
5126
5127
d436d3de 5128/* Generate code for the IARGC intrinsic. */
b41b2534
JB
5129
5130static void
d436d3de 5131gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
b41b2534
JB
5132{
5133 tree tmp;
5134 tree fndecl;
5135 tree type;
5136
5137 /* Call the library function. This always returns an INTEGER(4). */
5138 fndecl = gfor_fndecl_iargc;
db3927fb
AH
5139 tmp = build_call_expr_loc (input_location,
5140 fndecl, 0);
b41b2534
JB
5141
5142 /* Convert it to the required type. */
5143 type = gfc_typenode_for_spec (&expr->ts);
5144 tmp = fold_convert (type, tmp);
5145
b41b2534
JB
5146 se->expr = tmp;
5147}
5148
83d890b9
AL
5149
5150/* The loc intrinsic returns the address of its argument as
5151 gfc_index_integer_kind integer. */
5152
5153static void
0f8bc3e1 5154gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
83d890b9
AL
5155{
5156 tree temp_var;
5157 gfc_expr *arg_expr;
5158 gfc_ss *ss;
5159
5160 gcc_assert (!se->ss);
5161
5162 arg_expr = expr->value.function.actual->expr;
5163 ss = gfc_walk_expr (arg_expr);
5164 if (ss == gfc_ss_terminator)
5165 gfc_conv_expr_reference (se, arg_expr);
5166 else
f7172b55 5167 gfc_conv_array_parameter (se, arg_expr, ss, true, NULL, NULL, NULL);
0f8bc3e1 5168 se->expr= convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
83d890b9
AL
5169
5170 /* Create a temporary variable for loc return value. Without this,
5171 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
0f8bc3e1 5172 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
726a989a 5173 gfc_add_modify (&se->pre, temp_var, se->expr);
83d890b9
AL
5174 se->expr = temp_var;
5175}
5176
6de9cd9a
DN
5177/* Generate code for an intrinsic function. Some map directly to library
5178 calls, others get special handling. In some cases the name of the function
5179 used depends on the type specifiers. */
5180
5181void
5182gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
5183{
6b25a558 5184 const char *name;
374929b2
FXC
5185 int lib, kind;
5186 tree fndecl;
6de9cd9a 5187
6de9cd9a
DN
5188 name = &expr->value.function.name[2];
5189
1524f80b 5190 if (expr->rank > 0 && !expr->inline_noncopying_intrinsic)
6de9cd9a
DN
5191 {
5192 lib = gfc_is_intrinsic_libcall (expr);
5193 if (lib != 0)
5194 {
5195 if (lib == 1)
5196 se->ignore_optional = 1;
1fbfb0e2
DK
5197
5198 switch (expr->value.function.isym->id)
5199 {
5200 case GFC_ISYM_EOSHIFT:
5201 case GFC_ISYM_PACK:
5202 case GFC_ISYM_RESHAPE:
5203 /* For all of those the first argument specifies the type and the
5204 third is optional. */
5205 conv_generic_with_optional_char_arg (se, expr, 1, 3);
5206 break;
5207
5208 default:
5209 gfc_conv_intrinsic_funcall (se, expr);
5210 break;
5211 }
5212
6de9cd9a
DN
5213 return;
5214 }
5215 }
5216
cd5ecab6 5217 switch (expr->value.function.isym->id)
6de9cd9a
DN
5218 {
5219 case GFC_ISYM_NONE:
6e45f57b 5220 gcc_unreachable ();
6de9cd9a
DN
5221
5222 case GFC_ISYM_REPEAT:
5223 gfc_conv_intrinsic_repeat (se, expr);
5224 break;
5225
5226 case GFC_ISYM_TRIM:
5227 gfc_conv_intrinsic_trim (se, expr);
5228 break;
5229
a39fafac
FXC
5230 case GFC_ISYM_SC_KIND:
5231 gfc_conv_intrinsic_sc_kind (se, expr);
5232 break;
5233
6de9cd9a
DN
5234 case GFC_ISYM_SI_KIND:
5235 gfc_conv_intrinsic_si_kind (se, expr);
5236 break;
5237
5238 case GFC_ISYM_SR_KIND:
5239 gfc_conv_intrinsic_sr_kind (se, expr);
5240 break;
5241
5242 case GFC_ISYM_EXPONENT:
5243 gfc_conv_intrinsic_exponent (se, expr);
5244 break;
5245
6de9cd9a 5246 case GFC_ISYM_SCAN:
374929b2
FXC
5247 kind = expr->value.function.actual->expr->ts.kind;
5248 if (kind == 1)
5249 fndecl = gfor_fndecl_string_scan;
5250 else if (kind == 4)
5251 fndecl = gfor_fndecl_string_scan_char4;
5252 else
5253 gcc_unreachable ();
5254
5255 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6de9cd9a
DN
5256 break;
5257
5258 case GFC_ISYM_VERIFY:
374929b2
FXC
5259 kind = expr->value.function.actual->expr->ts.kind;
5260 if (kind == 1)
5261 fndecl = gfor_fndecl_string_verify;
5262 else if (kind == 4)
5263 fndecl = gfor_fndecl_string_verify_char4;
5264 else
5265 gcc_unreachable ();
5266
5267 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6de9cd9a
DN
5268 break;
5269
5270 case GFC_ISYM_ALLOCATED:
5271 gfc_conv_allocated (se, expr);
5272 break;
5273
5274 case GFC_ISYM_ASSOCIATED:
5275 gfc_conv_associated(se, expr);
5276 break;
5277
cf2b3c22
TB
5278 case GFC_ISYM_SAME_TYPE_AS:
5279 gfc_conv_same_type_as (se, expr);
5280 break;
5281
6de9cd9a
DN
5282 case GFC_ISYM_ABS:
5283 gfc_conv_intrinsic_abs (se, expr);
5284 break;
5285
5286 case GFC_ISYM_ADJUSTL:
374929b2
FXC
5287 if (expr->ts.kind == 1)
5288 fndecl = gfor_fndecl_adjustl;
5289 else if (expr->ts.kind == 4)
5290 fndecl = gfor_fndecl_adjustl_char4;
5291 else
5292 gcc_unreachable ();
5293
5294 gfc_conv_intrinsic_adjust (se, expr, fndecl);
6de9cd9a
DN
5295 break;
5296
5297 case GFC_ISYM_ADJUSTR:
374929b2
FXC
5298 if (expr->ts.kind == 1)
5299 fndecl = gfor_fndecl_adjustr;
5300 else if (expr->ts.kind == 4)
5301 fndecl = gfor_fndecl_adjustr_char4;
5302 else
5303 gcc_unreachable ();
5304
5305 gfc_conv_intrinsic_adjust (se, expr, fndecl);
6de9cd9a
DN
5306 break;
5307
5308 case GFC_ISYM_AIMAG:
5309 gfc_conv_intrinsic_imagpart (se, expr);
5310 break;
5311
5312 case GFC_ISYM_AINT:
f9f770a8 5313 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
6de9cd9a
DN
5314 break;
5315
5316 case GFC_ISYM_ALL:
5317 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
5318 break;
5319
5320 case GFC_ISYM_ANINT:
f9f770a8 5321 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
6de9cd9a
DN
5322 break;
5323
5d723e54
FXC
5324 case GFC_ISYM_AND:
5325 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
5326 break;
5327
6de9cd9a
DN
5328 case GFC_ISYM_ANY:
5329 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
5330 break;
5331
5332 case GFC_ISYM_BTEST:
5333 gfc_conv_intrinsic_btest (se, expr);
5334 break;
5335
5336 case GFC_ISYM_ACHAR:
5337 case GFC_ISYM_CHAR:
5338 gfc_conv_intrinsic_char (se, expr);
5339 break;
5340
5341 case GFC_ISYM_CONVERSION:
5342 case GFC_ISYM_REAL:
5343 case GFC_ISYM_LOGICAL:
5344 case GFC_ISYM_DBLE:
5345 gfc_conv_intrinsic_conversion (se, expr);
5346 break;
5347
e7dc5b4f 5348 /* Integer conversions are handled separately to make sure we get the
6de9cd9a
DN
5349 correct rounding mode. */
5350 case GFC_ISYM_INT:
bf3fb7e4
FXC
5351 case GFC_ISYM_INT2:
5352 case GFC_ISYM_INT8:
5353 case GFC_ISYM_LONG:
f9f770a8 5354 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
6de9cd9a
DN
5355 break;
5356
5357 case GFC_ISYM_NINT:
f9f770a8 5358 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
6de9cd9a
DN
5359 break;
5360
5361 case GFC_ISYM_CEILING:
f9f770a8 5362 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
6de9cd9a
DN
5363 break;
5364
5365 case GFC_ISYM_FLOOR:
f9f770a8 5366 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
6de9cd9a
DN
5367 break;
5368
5369 case GFC_ISYM_MOD:
5370 gfc_conv_intrinsic_mod (se, expr, 0);
5371 break;
5372
5373 case GFC_ISYM_MODULO:
5374 gfc_conv_intrinsic_mod (se, expr, 1);
5375 break;
5376
5377 case GFC_ISYM_CMPLX:
5378 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
5379 break;
5380
b41b2534 5381 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
d436d3de 5382 gfc_conv_intrinsic_iargc (se, expr);
b41b2534
JB
5383 break;
5384
5d723e54
FXC
5385 case GFC_ISYM_COMPLEX:
5386 gfc_conv_intrinsic_cmplx (se, expr, 1);
5387 break;
5388
6de9cd9a
DN
5389 case GFC_ISYM_CONJG:
5390 gfc_conv_intrinsic_conjg (se, expr);
5391 break;
5392
5393 case GFC_ISYM_COUNT:
5394 gfc_conv_intrinsic_count (se, expr);
5395 break;
5396
35059811
FXC
5397 case GFC_ISYM_CTIME:
5398 gfc_conv_intrinsic_ctime (se, expr);
5399 break;
5400
6de9cd9a
DN
5401 case GFC_ISYM_DIM:
5402 gfc_conv_intrinsic_dim (se, expr);
5403 break;
5404
61321991
PT
5405 case GFC_ISYM_DOT_PRODUCT:
5406 gfc_conv_intrinsic_dot_product (se, expr);
5407 break;
5408
6de9cd9a
DN
5409 case GFC_ISYM_DPROD:
5410 gfc_conv_intrinsic_dprod (se, expr);
5411 break;
5412
35059811
FXC
5413 case GFC_ISYM_FDATE:
5414 gfc_conv_intrinsic_fdate (se, expr);
5415 break;
5416
b5a4419c
FXC
5417 case GFC_ISYM_FRACTION:
5418 gfc_conv_intrinsic_fraction (se, expr);
5419 break;
5420
6de9cd9a
DN
5421 case GFC_ISYM_IAND:
5422 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
5423 break;
5424
5425 case GFC_ISYM_IBCLR:
5426 gfc_conv_intrinsic_singlebitop (se, expr, 0);
5427 break;
5428
5429 case GFC_ISYM_IBITS:
5430 gfc_conv_intrinsic_ibits (se, expr);
5431 break;
5432
5433 case GFC_ISYM_IBSET:
5434 gfc_conv_intrinsic_singlebitop (se, expr, 1);
5435 break;
5436
5437 case GFC_ISYM_IACHAR:
5438 case GFC_ISYM_ICHAR:
5439 /* We assume ASCII character sequence. */
5440 gfc_conv_intrinsic_ichar (se, expr);
5441 break;
5442
b41b2534 5443 case GFC_ISYM_IARGC:
d436d3de 5444 gfc_conv_intrinsic_iargc (se, expr);
b41b2534
JB
5445 break;
5446
6de9cd9a
DN
5447 case GFC_ISYM_IEOR:
5448 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
5449 break;
5450
5451 case GFC_ISYM_INDEX:
374929b2
FXC
5452 kind = expr->value.function.actual->expr->ts.kind;
5453 if (kind == 1)
5454 fndecl = gfor_fndecl_string_index;
5455 else if (kind == 4)
5456 fndecl = gfor_fndecl_string_index_char4;
5457 else
5458 gcc_unreachable ();
5459
5460 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
6de9cd9a
DN
5461 break;
5462
5463 case GFC_ISYM_IOR:
5464 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
5465 break;
5466
bae89173 5467 case GFC_ISYM_IS_IOSTAT_END:
d74b97cc 5468 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
bae89173
FXC
5469 break;
5470
5471 case GFC_ISYM_IS_IOSTAT_EOR:
d74b97cc 5472 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
bae89173
FXC
5473 break;
5474
3d97b1af
FXC
5475 case GFC_ISYM_ISNAN:
5476 gfc_conv_intrinsic_isnan (se, expr);
5477 break;
5478
a119fc1c
FXC
5479 case GFC_ISYM_LSHIFT:
5480 gfc_conv_intrinsic_rlshift (se, expr, 0);
5481 break;
5482
5483 case GFC_ISYM_RSHIFT:
5484 gfc_conv_intrinsic_rlshift (se, expr, 1);
5485 break;
5486
6de9cd9a
DN
5487 case GFC_ISYM_ISHFT:
5488 gfc_conv_intrinsic_ishft (se, expr);
5489 break;
5490
5491 case GFC_ISYM_ISHFTC:
5492 gfc_conv_intrinsic_ishftc (se, expr);
5493 break;
5494
414f00e9
SB
5495 case GFC_ISYM_LEADZ:
5496 gfc_conv_intrinsic_leadz (se, expr);
5497 break;
5498
5499 case GFC_ISYM_TRAILZ:
5500 gfc_conv_intrinsic_trailz (se, expr);
5501 break;
5502
ad5f4de2
FXC
5503 case GFC_ISYM_POPCNT:
5504 gfc_conv_intrinsic_popcnt_poppar (se, expr, 0);
5505 break;
5506
5507 case GFC_ISYM_POPPAR:
5508 gfc_conv_intrinsic_popcnt_poppar (se, expr, 1);
5509 break;
5510
6de9cd9a
DN
5511 case GFC_ISYM_LBOUND:
5512 gfc_conv_intrinsic_bound (se, expr, 0);
5513 break;
5514
1524f80b
RS
5515 case GFC_ISYM_TRANSPOSE:
5516 if (se->ss && se->ss->useflags)
5517 {
5518 gfc_conv_tmp_array_ref (se);
5519 gfc_advance_se_ss_chain (se);
5520 }
5521 else
5522 gfc_conv_array_transpose (se, expr->value.function.actual->expr);
5523 break;
5524
6de9cd9a
DN
5525 case GFC_ISYM_LEN:
5526 gfc_conv_intrinsic_len (se, expr);
5527 break;
5528
5529 case GFC_ISYM_LEN_TRIM:
5530 gfc_conv_intrinsic_len_trim (se, expr);
5531 break;
5532
5533 case GFC_ISYM_LGE:
5534 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
5535 break;
5536
5537 case GFC_ISYM_LGT:
5538 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
5539 break;
5540
5541 case GFC_ISYM_LLE:
5542 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
5543 break;
5544
5545 case GFC_ISYM_LLT:
5546 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
5547 break;
5548
5549 case GFC_ISYM_MAX:
2263c775
FXC
5550 if (expr->ts.type == BT_CHARACTER)
5551 gfc_conv_intrinsic_minmax_char (se, expr, 1);
5552 else
5553 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
6de9cd9a
DN
5554 break;
5555
5556 case GFC_ISYM_MAXLOC:
5557 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
5558 break;
5559
5560 case GFC_ISYM_MAXVAL:
5561 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
5562 break;
5563
5564 case GFC_ISYM_MERGE:
5565 gfc_conv_intrinsic_merge (se, expr);
5566 break;
5567
5568 case GFC_ISYM_MIN:
2263c775
FXC
5569 if (expr->ts.type == BT_CHARACTER)
5570 gfc_conv_intrinsic_minmax_char (se, expr, -1);
5571 else
5572 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
6de9cd9a
DN
5573 break;
5574
5575 case GFC_ISYM_MINLOC:
5576 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
5577 break;
5578
5579 case GFC_ISYM_MINVAL:
5580 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
5581 break;
5582
b5a4419c
FXC
5583 case GFC_ISYM_NEAREST:
5584 gfc_conv_intrinsic_nearest (se, expr);
5585 break;
5586
0cd0559e
TB
5587 case GFC_ISYM_NORM2:
5588 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, true);
5589 break;
5590
6de9cd9a
DN
5591 case GFC_ISYM_NOT:
5592 gfc_conv_intrinsic_not (se, expr);
5593 break;
5594
5d723e54
FXC
5595 case GFC_ISYM_OR:
5596 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
5597 break;
5598
0cd0559e
TB
5599 case GFC_ISYM_PARITY:
5600 gfc_conv_intrinsic_arith (se, expr, NE_EXPR, false);
5601 break;
5602
6de9cd9a
DN
5603 case GFC_ISYM_PRESENT:
5604 gfc_conv_intrinsic_present (se, expr);
5605 break;
5606
5607 case GFC_ISYM_PRODUCT:
0cd0559e 5608 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
6de9cd9a
DN
5609 break;
5610
b5a4419c
FXC
5611 case GFC_ISYM_RRSPACING:
5612 gfc_conv_intrinsic_rrspacing (se, expr);
5613 break;
5614
5615 case GFC_ISYM_SET_EXPONENT:
5616 gfc_conv_intrinsic_set_exponent (se, expr);
5617 break;
5618
5619 case GFC_ISYM_SCALE:
5620 gfc_conv_intrinsic_scale (se, expr);
5621 break;
5622
6de9cd9a
DN
5623 case GFC_ISYM_SIGN:
5624 gfc_conv_intrinsic_sign (se, expr);
5625 break;
5626
5627 case GFC_ISYM_SIZE:
5628 gfc_conv_intrinsic_size (se, expr);
5629 break;
5630
fd2157ce 5631 case GFC_ISYM_SIZEOF:
048510c8 5632 case GFC_ISYM_C_SIZEOF:
fd2157ce
TS
5633 gfc_conv_intrinsic_sizeof (se, expr);
5634 break;
5635
048510c8
JW
5636 case GFC_ISYM_STORAGE_SIZE:
5637 gfc_conv_intrinsic_storage_size (se, expr);
5638 break;
5639
b5a4419c
FXC
5640 case GFC_ISYM_SPACING:
5641 gfc_conv_intrinsic_spacing (se, expr);
5642 break;
5643
6de9cd9a 5644 case GFC_ISYM_SUM:
0cd0559e 5645 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR, false);
6de9cd9a
DN
5646 break;
5647
5648 case GFC_ISYM_TRANSFER:
27a4e072 5649 if (se->ss && se->ss->useflags)
0c5a42a6 5650 {
27a4e072
JJ
5651 /* Access the previously obtained result. */
5652 gfc_conv_tmp_array_ref (se);
5653 gfc_advance_se_ss_chain (se);
0c5a42a6
PT
5654 }
5655 else
c41fea4a 5656 gfc_conv_intrinsic_transfer (se, expr);
25fc05eb
FXC
5657 break;
5658
5659 case GFC_ISYM_TTYNAM:
5660 gfc_conv_intrinsic_ttynam (se, expr);
6de9cd9a
DN
5661 break;
5662
5663 case GFC_ISYM_UBOUND:
5664 gfc_conv_intrinsic_bound (se, expr, 1);
5665 break;
5666
5d723e54
FXC
5667 case GFC_ISYM_XOR:
5668 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
5669 break;
5670
83d890b9
AL
5671 case GFC_ISYM_LOC:
5672 gfc_conv_intrinsic_loc (se, expr);
5673 break;
5674
a119fc1c 5675 case GFC_ISYM_ACCESS:
f77b6ca3 5676 case GFC_ISYM_CHDIR:
a119fc1c 5677 case GFC_ISYM_CHMOD:
a1ba31ce 5678 case GFC_ISYM_DTIME:
2bd74949 5679 case GFC_ISYM_ETIME:
7c1dab0d 5680 case GFC_ISYM_EXTENDS_TYPE_OF:
5d723e54
FXC
5681 case GFC_ISYM_FGET:
5682 case GFC_ISYM_FGETC:
df65f093 5683 case GFC_ISYM_FNUM:
5d723e54
FXC
5684 case GFC_ISYM_FPUT:
5685 case GFC_ISYM_FPUTC:
df65f093 5686 case GFC_ISYM_FSTAT:
5d723e54 5687 case GFC_ISYM_FTELL:
a8c60d7f 5688 case GFC_ISYM_GETCWD:
4c0c6b9f
SK
5689 case GFC_ISYM_GETGID:
5690 case GFC_ISYM_GETPID:
5691 case GFC_ISYM_GETUID:
f77b6ca3
FXC
5692 case GFC_ISYM_HOSTNM:
5693 case GFC_ISYM_KILL:
5694 case GFC_ISYM_IERRNO:
df65f093 5695 case GFC_ISYM_IRAND:
ae8b8789 5696 case GFC_ISYM_ISATTY:
47b99694 5697 case GFC_ISYM_JN2:
f77b6ca3 5698 case GFC_ISYM_LINK:
bf3fb7e4 5699 case GFC_ISYM_LSTAT:
0d519038 5700 case GFC_ISYM_MALLOC:
df65f093 5701 case GFC_ISYM_MATMUL:
bf3fb7e4
FXC
5702 case GFC_ISYM_MCLOCK:
5703 case GFC_ISYM_MCLOCK8:
df65f093 5704 case GFC_ISYM_RAND:
f77b6ca3 5705 case GFC_ISYM_RENAME:
df65f093 5706 case GFC_ISYM_SECOND:
53096259 5707 case GFC_ISYM_SECNDS:
185d7d97 5708 case GFC_ISYM_SIGNAL:
df65f093 5709 case GFC_ISYM_STAT:
f77b6ca3 5710 case GFC_ISYM_SYMLNK:
5b1374e9 5711 case GFC_ISYM_SYSTEM:
f77b6ca3
FXC
5712 case GFC_ISYM_TIME:
5713 case GFC_ISYM_TIME8:
d8fe26b2
SK
5714 case GFC_ISYM_UMASK:
5715 case GFC_ISYM_UNLINK:
47b99694 5716 case GFC_ISYM_YN2:
6de9cd9a
DN
5717 gfc_conv_intrinsic_funcall (se, expr);
5718 break;
5719
1fbfb0e2
DK
5720 case GFC_ISYM_EOSHIFT:
5721 case GFC_ISYM_PACK:
5722 case GFC_ISYM_RESHAPE:
5723 /* For those, expr->rank should always be >0 and thus the if above the
5724 switch should have matched. */
5725 gcc_unreachable ();
5726 break;
5727
6de9cd9a
DN
5728 default:
5729 gfc_conv_intrinsic_lib_function (se, expr);
5730 break;
5731 }
5732}
5733
5734
5735/* This generates code to execute before entering the scalarization loop.
5736 Currently does nothing. */
5737
5738void
5739gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
5740{
cd5ecab6 5741 switch (ss->expr->value.function.isym->id)
6de9cd9a
DN
5742 {
5743 case GFC_ISYM_UBOUND:
5744 case GFC_ISYM_LBOUND:
5745 break;
5746
5747 default:
6e45f57b 5748 gcc_unreachable ();
6de9cd9a
DN
5749 }
5750}
5751
5752
5753/* UBOUND and LBOUND intrinsics with one parameter are expanded into code
5754 inside the scalarization loop. */
5755
5756static gfc_ss *
5757gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
5758{
5759 gfc_ss *newss;
5760
5761 /* The two argument version returns a scalar. */
5762 if (expr->value.function.actual->next->expr)
5763 return ss;
5764
5765 newss = gfc_get_ss ();
5766 newss->type = GFC_SS_INTRINSIC;
5767 newss->expr = expr;
5768 newss->next = ss;
f5f701ad 5769 newss->data.info.dimen = 1;
6de9cd9a
DN
5770
5771 return newss;
5772}
5773
5774
5775/* Walk an intrinsic array libcall. */
5776
5777static gfc_ss *
5778gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
5779{
5780 gfc_ss *newss;
5781
6e45f57b 5782 gcc_assert (expr->rank > 0);
6de9cd9a
DN
5783
5784 newss = gfc_get_ss ();
5785 newss->type = GFC_SS_FUNCTION;
5786 newss->expr = expr;
5787 newss->next = ss;
5788 newss->data.info.dimen = expr->rank;
5789
5790 return newss;
5791}
5792
5793
df2fba9e 5794/* Returns nonzero if the specified intrinsic function call maps directly to
6de9cd9a
DN
5795 an external library call. Should only be used for functions that return
5796 arrays. */
5797
5798int
5799gfc_is_intrinsic_libcall (gfc_expr * expr)
5800{
6e45f57b
PB
5801 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
5802 gcc_assert (expr->rank > 0);
6de9cd9a 5803
cd5ecab6 5804 switch (expr->value.function.isym->id)
6de9cd9a
DN
5805 {
5806 case GFC_ISYM_ALL:
5807 case GFC_ISYM_ANY:
5808 case GFC_ISYM_COUNT:
47b99694 5809 case GFC_ISYM_JN2:
6de9cd9a
DN
5810 case GFC_ISYM_MATMUL:
5811 case GFC_ISYM_MAXLOC:
5812 case GFC_ISYM_MAXVAL:
5813 case GFC_ISYM_MINLOC:
5814 case GFC_ISYM_MINVAL:
0cd0559e
TB
5815 case GFC_ISYM_NORM2:
5816 case GFC_ISYM_PARITY:
6de9cd9a
DN
5817 case GFC_ISYM_PRODUCT:
5818 case GFC_ISYM_SUM:
5819 case GFC_ISYM_SHAPE:
5820 case GFC_ISYM_SPREAD:
5821 case GFC_ISYM_TRANSPOSE:
47b99694 5822 case GFC_ISYM_YN2:
6de9cd9a
DN
5823 /* Ignore absent optional parameters. */
5824 return 1;
5825
5826 case GFC_ISYM_RESHAPE:
5827 case GFC_ISYM_CSHIFT:
5828 case GFC_ISYM_EOSHIFT:
5829 case GFC_ISYM_PACK:
5830 case GFC_ISYM_UNPACK:
5831 /* Pass absent optional parameters. */
5832 return 2;
5833
5834 default:
5835 return 0;
5836 }
5837}
5838
5839/* Walk an intrinsic function. */
5840gfc_ss *
5841gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
5842 gfc_intrinsic_sym * isym)
5843{
6e45f57b 5844 gcc_assert (isym);
6de9cd9a
DN
5845
5846 if (isym->elemental)
48474141 5847 return gfc_walk_elemental_function_args (ss, expr->value.function.actual, GFC_SS_SCALAR);
6de9cd9a
DN
5848
5849 if (expr->rank == 0)
5850 return ss;
5851
5852 if (gfc_is_intrinsic_libcall (expr))
5853 return gfc_walk_intrinsic_libfunc (ss, expr);
5854
5855 /* Special cases. */
cd5ecab6 5856 switch (isym->id)
6de9cd9a
DN
5857 {
5858 case GFC_ISYM_LBOUND:
5859 case GFC_ISYM_UBOUND:
5860 return gfc_walk_intrinsic_bound (ss, expr);
5861
0c5a42a6
PT
5862 case GFC_ISYM_TRANSFER:
5863 return gfc_walk_intrinsic_libfunc (ss, expr);
5864
6de9cd9a
DN
5865 default:
5866 /* This probably meant someone forgot to add an intrinsic to the above
ca39e6f2
FXC
5867 list(s) when they implemented it, or something's gone horribly
5868 wrong. */
5869 gcc_unreachable ();
6de9cd9a
DN
5870 }
5871}
5872
b2a5eb75
JW
5873
5874tree
5875gfc_conv_intrinsic_move_alloc (gfc_code *code)
5876{
5877 if (code->ext.actual->expr->rank == 0)
5878 {
5879 /* Scalar arguments: Generate pointer assignments. */
5880 gfc_expr *from, *to;
5881 stmtblock_t block;
5882 tree tmp;
5883
5884 from = code->ext.actual->expr;
5885 to = code->ext.actual->next->expr;
5886
5887 gfc_start_block (&block);
5888
5889 if (to->ts.type == BT_CLASS)
5890 tmp = gfc_trans_class_assign (to, from, EXEC_POINTER_ASSIGN);
5891 else
5892 tmp = gfc_trans_pointer_assignment (to, from);
5893 gfc_add_expr_to_block (&block, tmp);
5894
5895 if (from->ts.type == BT_CLASS)
5896 tmp = gfc_trans_class_assign (from, gfc_get_null_expr (NULL),
5897 EXEC_POINTER_ASSIGN);
5898 else
5899 tmp = gfc_trans_pointer_assignment (from,
5900 gfc_get_null_expr (NULL));
5901 gfc_add_expr_to_block (&block, tmp);
5902
5903 return gfc_finish_block (&block);
5904 }
5905 else
5906 /* Array arguments: Generate library code. */
5907 return gfc_trans_call (code, false, NULL_TREE, NULL_TREE, false);
5908}
5909
5910
6de9cd9a 5911#include "gt-fortran-trans-intrinsic.h"