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