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