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