1 /* Intrinsic translation
2 Copyright (C) 2002-2025 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* trans-intrinsic.cc-- generate GENERIC trees for calls to intrinsics. */
26 #include "coretypes.h"
28 #include "tm.h" /* For UNITS_PER_WORD. */
32 #include "stringpool.h"
33 #include "fold-const.h"
34 #include "internal-fn.h"
35 #include "tree-nested.h"
36 #include "stor-layout.h"
37 #include "toplev.h" /* For rest_of_decl_compilation. */
39 #include "trans-const.h"
40 #include "trans-types.h"
41 #include "trans-array.h"
42 #include "dependency.h" /* For CAF array alias analysis. */
45 #include "constructor.h"
47 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
49 /* This maps Fortran intrinsic math functions to external library or GCC
51 typedef struct GTY(()) gfc_intrinsic_map_t
{
52 /* The explicit enum is required to work around inadequacies in the
53 garbage collection/gengtype parsing mechanism. */
56 /* Enum value from the "language-independent", aka C-centric, part
57 of gcc, or END_BUILTINS of no such value set. */
58 enum built_in_function float_built_in
;
59 enum built_in_function double_built_in
;
60 enum built_in_function long_double_built_in
;
61 enum built_in_function complex_float_built_in
;
62 enum built_in_function complex_double_built_in
;
63 enum built_in_function complex_long_double_built_in
;
65 /* True if the naming pattern is to prepend "c" for complex and
66 append "f" for kind=4. False if the naming pattern is to
67 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
70 /* True if a complex version of the function exists. */
71 bool complex_available
;
73 /* True if the function should be marked const. */
76 /* The base library name of this function. */
79 /* Cache decls created for the various operand types. */
91 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
92 defines complex variants of all of the entries in mathbuiltins.def
94 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
95 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
96 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
97 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
98 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
100 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
101 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
102 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
103 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
104 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
106 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
107 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
108 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
109 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
110 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
112 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
113 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
114 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
115 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
116 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
118 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map
[] =
120 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
121 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
122 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
123 #include "mathbuiltins.def"
125 /* Functions in libgfortran. */
126 LIB_FUNCTION (ERFC_SCALED
, "erfc_scaled", false),
127 LIB_FUNCTION (SIND
, "sind", false),
128 LIB_FUNCTION (COSD
, "cosd", false),
129 LIB_FUNCTION (TAND
, "tand", false),
132 LIB_FUNCTION (NONE
, NULL
, false)
137 #undef DEFINE_MATH_BUILTIN
138 #undef DEFINE_MATH_BUILTIN_C
141 enum rounding_mode
{ RND_ROUND
, RND_TRUNC
, RND_CEIL
, RND_FLOOR
};
144 /* Find the correct variant of a given builtin from its argument. */
146 builtin_decl_for_precision (enum built_in_function base_built_in
,
149 enum built_in_function i
= END_BUILTINS
;
151 gfc_intrinsic_map_t
*m
;
152 for (m
= gfc_intrinsic_map
; m
->double_built_in
!= base_built_in
; m
++)
155 if (precision
== TYPE_PRECISION (float_type_node
))
156 i
= m
->float_built_in
;
157 else if (precision
== TYPE_PRECISION (double_type_node
))
158 i
= m
->double_built_in
;
159 else if (precision
== TYPE_PRECISION (long_double_type_node
)
160 && (!gfc_real16_is_float128
161 || long_double_type_node
!= gfc_float128_type_node
))
162 i
= m
->long_double_built_in
;
163 else if (precision
== TYPE_PRECISION (gfc_float128_type_node
))
165 /* Special treatment, because it is not exactly a built-in, but
166 a library function. */
167 return m
->real16_decl
;
170 return (i
== END_BUILTINS
? NULL_TREE
: builtin_decl_explicit (i
));
175 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in
,
178 int i
= gfc_validate_kind (BT_REAL
, kind
, false);
180 if (gfc_real_kinds
[i
].c_float128
)
182 /* For _Float128, the story is a bit different, because we return
183 a decl to a library function rather than a built-in. */
184 gfc_intrinsic_map_t
*m
;
185 for (m
= gfc_intrinsic_map
; m
->double_built_in
!= double_built_in
; m
++)
188 return m
->real16_decl
;
191 return builtin_decl_for_precision (double_built_in
,
192 gfc_real_kinds
[i
].mode_precision
);
196 /* Evaluate the arguments to an intrinsic function. The value
197 of NARGS may be less than the actual number of arguments in EXPR
198 to allow optional "KIND" arguments that are not included in the
199 generated code to be ignored. */
202 gfc_conv_intrinsic_function_args (gfc_se
*se
, gfc_expr
*expr
,
203 tree
*argarray
, int nargs
)
205 gfc_actual_arglist
*actual
;
207 gfc_intrinsic_arg
*formal
;
211 formal
= expr
->value
.function
.isym
->formal
;
212 actual
= expr
->value
.function
.actual
;
214 for (curr_arg
= 0; curr_arg
< nargs
; curr_arg
++,
215 actual
= actual
->next
,
216 formal
= formal
? formal
->next
: NULL
)
220 /* Skip omitted optional arguments. */
227 /* Evaluate the parameter. This will substitute scalarized
228 references automatically. */
229 gfc_init_se (&argse
, se
);
231 if (e
->ts
.type
== BT_CHARACTER
)
233 gfc_conv_expr (&argse
, e
);
234 gfc_conv_string_parameter (&argse
);
235 argarray
[curr_arg
++] = argse
.string_length
;
236 gcc_assert (curr_arg
< nargs
);
239 gfc_conv_expr_val (&argse
, e
);
241 /* If an optional argument is itself an optional dummy argument,
242 check its presence and substitute a null if absent. */
243 if (e
->expr_type
== EXPR_VARIABLE
244 && e
->symtree
->n
.sym
->attr
.optional
247 gfc_conv_missing_dummy (&argse
, e
, formal
->ts
, 0);
249 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
250 gfc_add_block_to_block (&se
->post
, &argse
.post
);
251 argarray
[curr_arg
] = argse
.expr
;
255 /* Count the number of actual arguments to the intrinsic function EXPR
256 including any "hidden" string length arguments. */
259 gfc_intrinsic_argument_list_length (gfc_expr
*expr
)
262 gfc_actual_arglist
*actual
;
264 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
269 if (actual
->expr
->ts
.type
== BT_CHARACTER
)
279 /* Conversions between different types are output by the frontend as
280 intrinsic functions. We implement these directly with inline code. */
283 gfc_conv_intrinsic_conversion (gfc_se
* se
, gfc_expr
* expr
)
289 nargs
= gfc_intrinsic_argument_list_length (expr
);
290 args
= XALLOCAVEC (tree
, nargs
);
292 /* Evaluate all the arguments passed. Whilst we're only interested in the
293 first one here, there are other parts of the front-end that assume this
294 and will trigger an ICE if it's not the case. */
295 type
= gfc_typenode_for_spec (&expr
->ts
);
296 gcc_assert (expr
->value
.function
.actual
->expr
);
297 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
299 /* Conversion between character kinds involves a call to a library
301 if (expr
->ts
.type
== BT_CHARACTER
)
303 tree fndecl
, var
, addr
, tmp
;
305 if (expr
->ts
.kind
== 1
306 && expr
->value
.function
.actual
->expr
->ts
.kind
== 4)
307 fndecl
= gfor_fndecl_convert_char4_to_char1
;
308 else if (expr
->ts
.kind
== 4
309 && expr
->value
.function
.actual
->expr
->ts
.kind
== 1)
310 fndecl
= gfor_fndecl_convert_char1_to_char4
;
314 /* Create the variable storing the converted value. */
315 type
= gfc_get_pchar_type (expr
->ts
.kind
);
316 var
= gfc_create_var (type
, "str");
317 addr
= gfc_build_addr_expr (build_pointer_type (type
), var
);
319 /* Call the library function that will perform the conversion. */
320 gcc_assert (nargs
>= 2);
321 tmp
= build_call_expr_loc (input_location
,
322 fndecl
, 3, addr
, args
[0], args
[1]);
323 gfc_add_expr_to_block (&se
->pre
, tmp
);
325 /* Free the temporary afterwards. */
326 tmp
= gfc_call_free (var
);
327 gfc_add_expr_to_block (&se
->post
, tmp
);
330 se
->string_length
= args
[0];
335 /* Conversion from complex to non-complex involves taking the real
336 component of the value. */
337 if (TREE_CODE (TREE_TYPE (args
[0])) == COMPLEX_TYPE
338 && expr
->ts
.type
!= BT_COMPLEX
)
342 artype
= TREE_TYPE (TREE_TYPE (args
[0]));
343 args
[0] = fold_build1_loc (input_location
, REALPART_EXPR
, artype
,
347 se
->expr
= convert (type
, args
[0]);
350 /* This is needed because the gcc backend only implements
351 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
352 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
353 Similarly for CEILING. */
356 build_fixbound_expr (stmtblock_t
* pblock
, tree arg
, tree type
, int up
)
363 argtype
= TREE_TYPE (arg
);
364 arg
= gfc_evaluate_now (arg
, pblock
);
366 intval
= convert (type
, arg
);
367 intval
= gfc_evaluate_now (intval
, pblock
);
369 tmp
= convert (argtype
, intval
);
370 cond
= fold_build2_loc (input_location
, up
? GE_EXPR
: LE_EXPR
,
371 logical_type_node
, tmp
, arg
);
373 tmp
= fold_build2_loc (input_location
, up
? PLUS_EXPR
: MINUS_EXPR
, type
,
374 intval
, build_int_cst (type
, 1));
375 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
, intval
, tmp
);
380 /* Round to nearest integer, away from zero. */
383 build_round_expr (tree arg
, tree restype
)
387 int argprec
, resprec
;
389 argtype
= TREE_TYPE (arg
);
390 argprec
= TYPE_PRECISION (argtype
);
391 resprec
= TYPE_PRECISION (restype
);
393 /* Depending on the type of the result, choose the int intrinsic (iround,
394 available only as a builtin, therefore cannot use it for _Float128), long
395 int intrinsic (lround family) or long long intrinsic (llround). If we
396 don't have an appropriate function that converts directly to the integer
397 type (such as kind == 16), just use ROUND, and then convert the result to
398 an integer. We might also need to convert the result afterwards. */
399 if (resprec
<= INT_TYPE_SIZE
400 && argprec
<= TYPE_PRECISION (long_double_type_node
))
401 fn
= builtin_decl_for_precision (BUILT_IN_IROUND
, argprec
);
402 else if (resprec
<= LONG_TYPE_SIZE
)
403 fn
= builtin_decl_for_precision (BUILT_IN_LROUND
, argprec
);
404 else if (resprec
<= LONG_LONG_TYPE_SIZE
)
405 fn
= builtin_decl_for_precision (BUILT_IN_LLROUND
, argprec
);
406 else if (resprec
>= argprec
)
407 fn
= builtin_decl_for_precision (BUILT_IN_ROUND
, argprec
);
411 return convert (restype
, build_call_expr_loc (input_location
,
416 /* Convert a real to an integer using a specific rounding mode.
417 Ideally we would just build the corresponding GENERIC node,
418 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
421 build_fix_expr (stmtblock_t
* pblock
, tree arg
, tree type
,
422 enum rounding_mode op
)
427 return build_fixbound_expr (pblock
, arg
, type
, 0);
430 return build_fixbound_expr (pblock
, arg
, type
, 1);
433 return build_round_expr (arg
, type
);
436 return fold_build1_loc (input_location
, FIX_TRUNC_EXPR
, type
, arg
);
444 /* Round a real value using the specified rounding mode.
445 We use a temporary integer of that same kind size as the result.
446 Values larger than those that can be represented by this kind are
447 unchanged, as they will not be accurate enough to represent the
449 huge = HUGE (KIND (a))
450 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
454 gfc_conv_intrinsic_aint (gfc_se
* se
, gfc_expr
* expr
, enum rounding_mode op
)
466 kind
= expr
->ts
.kind
;
467 nargs
= gfc_intrinsic_argument_list_length (expr
);
470 /* We have builtin functions for some cases. */
474 decl
= gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND
, kind
);
478 decl
= gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC
, kind
);
485 /* Evaluate the argument. */
486 gcc_assert (expr
->value
.function
.actual
->expr
);
487 gfc_conv_intrinsic_function_args (se
, expr
, arg
, nargs
);
489 /* Use a builtin function if one exists. */
490 if (decl
!= NULL_TREE
)
492 se
->expr
= build_call_expr_loc (input_location
, decl
, 1, arg
[0]);
496 /* This code is probably redundant, but we'll keep it lying around just
498 type
= gfc_typenode_for_spec (&expr
->ts
);
499 arg
[0] = gfc_evaluate_now (arg
[0], &se
->pre
);
501 /* Test if the value is too large to handle sensibly. */
502 gfc_set_model_kind (kind
);
504 n
= gfc_validate_kind (BT_INTEGER
, kind
, false);
505 mpfr_set_z (huge
, gfc_integer_kinds
[n
].huge
, GFC_RND_MODE
);
506 tmp
= gfc_conv_mpfr_to_tree (huge
, kind
, 0);
507 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
, arg
[0],
510 mpfr_neg (huge
, huge
, GFC_RND_MODE
);
511 tmp
= gfc_conv_mpfr_to_tree (huge
, kind
, 0);
512 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
, arg
[0],
514 cond
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
, logical_type_node
,
516 itype
= gfc_get_int_type (kind
);
518 tmp
= build_fix_expr (&se
->pre
, arg
[0], itype
, op
);
519 tmp
= convert (type
, tmp
);
520 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
, tmp
,
526 /* Convert to an integer using the specified rounding mode. */
529 gfc_conv_intrinsic_int (gfc_se
* se
, gfc_expr
* expr
, enum rounding_mode op
)
535 nargs
= gfc_intrinsic_argument_list_length (expr
);
536 args
= XALLOCAVEC (tree
, nargs
);
538 /* Evaluate the argument, we process all arguments even though we only
539 use the first one for code generation purposes. */
540 type
= gfc_typenode_for_spec (&expr
->ts
);
541 gcc_assert (expr
->value
.function
.actual
->expr
);
542 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
544 if (TREE_CODE (TREE_TYPE (args
[0])) == INTEGER_TYPE
)
546 /* Conversion to a different integer kind. */
547 se
->expr
= convert (type
, args
[0]);
551 /* Conversion from complex to non-complex involves taking the real
552 component of the value. */
553 if (TREE_CODE (TREE_TYPE (args
[0])) == COMPLEX_TYPE
554 && expr
->ts
.type
!= BT_COMPLEX
)
558 artype
= TREE_TYPE (TREE_TYPE (args
[0]));
559 args
[0] = fold_build1_loc (input_location
, REALPART_EXPR
, artype
,
563 se
->expr
= build_fix_expr (&se
->pre
, args
[0], type
, op
);
568 /* Get the imaginary component of a value. */
571 gfc_conv_intrinsic_imagpart (gfc_se
* se
, gfc_expr
* expr
)
575 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
576 se
->expr
= fold_build1_loc (input_location
, IMAGPART_EXPR
,
577 TREE_TYPE (TREE_TYPE (arg
)), arg
);
581 /* Get the complex conjugate of a value. */
584 gfc_conv_intrinsic_conjg (gfc_se
* se
, gfc_expr
* expr
)
588 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
589 se
->expr
= fold_build1_loc (input_location
, CONJ_EXPR
, TREE_TYPE (arg
), arg
);
595 define_quad_builtin (const char *name
, tree type
, bool is_const
)
598 fndecl
= build_decl (input_location
, FUNCTION_DECL
, get_identifier (name
),
601 /* Mark the decl as external. */
602 DECL_EXTERNAL (fndecl
) = 1;
603 TREE_PUBLIC (fndecl
) = 1;
605 /* Mark it __attribute__((const)). */
606 TREE_READONLY (fndecl
) = is_const
;
608 rest_of_decl_compilation (fndecl
, 1, 0);
613 /* Add SIMD attribute for FNDECL built-in if the built-in
614 name is in VECTORIZED_BUILTINS. */
617 add_simd_flag_for_built_in (tree fndecl
)
619 if (gfc_vectorized_builtins
== NULL
620 || fndecl
== NULL_TREE
)
623 const char *name
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
624 int *clauses
= gfc_vectorized_builtins
->get (name
);
627 for (unsigned i
= 0; i
< 3; i
++)
628 if (*clauses
& (1 << i
))
630 gfc_simd_clause simd_type
= (gfc_simd_clause
)*clauses
;
631 tree omp_clause
= NULL_TREE
;
632 if (simd_type
== SIMD_NONE
)
633 ; /* No SIMD clause. */
637 = (simd_type
== SIMD_INBRANCH
638 ? OMP_CLAUSE_INBRANCH
: OMP_CLAUSE_NOTINBRANCH
);
639 omp_clause
= build_omp_clause (UNKNOWN_LOCATION
, code
);
640 omp_clause
= build_tree_list (NULL_TREE
, omp_clause
);
643 DECL_ATTRIBUTES (fndecl
)
644 = tree_cons (get_identifier ("omp declare simd"), omp_clause
,
645 DECL_ATTRIBUTES (fndecl
));
650 /* Set SIMD attribute to all built-in functions that are mentioned
651 in gfc_vectorized_builtins vector. */
654 gfc_adjust_builtins (void)
656 gfc_intrinsic_map_t
*m
;
657 for (m
= gfc_intrinsic_map
;
658 m
->id
!= GFC_ISYM_NONE
|| m
->double_built_in
!= END_BUILTINS
; m
++)
660 add_simd_flag_for_built_in (m
->real4_decl
);
661 add_simd_flag_for_built_in (m
->complex4_decl
);
662 add_simd_flag_for_built_in (m
->real8_decl
);
663 add_simd_flag_for_built_in (m
->complex8_decl
);
664 add_simd_flag_for_built_in (m
->real10_decl
);
665 add_simd_flag_for_built_in (m
->complex10_decl
);
666 add_simd_flag_for_built_in (m
->real16_decl
);
667 add_simd_flag_for_built_in (m
->complex16_decl
);
668 add_simd_flag_for_built_in (m
->real16_decl
);
669 add_simd_flag_for_built_in (m
->complex16_decl
);
672 /* Release all strings. */
673 if (gfc_vectorized_builtins
!= NULL
)
675 for (hash_map
<nofree_string_hash
, int>::iterator it
676 = gfc_vectorized_builtins
->begin ();
677 it
!= gfc_vectorized_builtins
->end (); ++it
)
678 free (CONST_CAST (char *, (*it
).first
));
680 delete gfc_vectorized_builtins
;
681 gfc_vectorized_builtins
= NULL
;
685 /* Initialize function decls for library functions. The external functions
686 are created as required. Builtin functions are added here. */
689 gfc_build_intrinsic_lib_fndecls (void)
691 gfc_intrinsic_map_t
*m
;
692 tree quad_decls
[END_BUILTINS
+ 1];
694 if (gfc_real16_is_float128
)
696 /* If we have soft-float types, we create the decls for their
697 C99-like library functions. For now, we only handle _Float128
698 q-suffixed or IEC 60559 f128-suffixed functions. */
700 tree type
, complex_type
, func_1
, func_2
, func_3
, func_cabs
, func_frexp
;
701 tree func_iround
, func_lround
, func_llround
, func_scalbn
, func_cpow
;
703 memset (quad_decls
, 0, sizeof(tree
) * (END_BUILTINS
+ 1));
705 type
= gfc_float128_type_node
;
706 complex_type
= gfc_complex_float128_type_node
;
707 /* type (*) (type) */
708 func_1
= build_function_type_list (type
, type
, NULL_TREE
);
710 func_iround
= build_function_type_list (integer_type_node
,
712 /* long (*) (type) */
713 func_lround
= build_function_type_list (long_integer_type_node
,
715 /* long long (*) (type) */
716 func_llround
= build_function_type_list (long_long_integer_type_node
,
718 /* type (*) (type, type) */
719 func_2
= build_function_type_list (type
, type
, type
, NULL_TREE
);
720 /* type (*) (type, type, type) */
721 func_3
= build_function_type_list (type
, type
, type
, type
, NULL_TREE
);
722 /* type (*) (type, &int) */
724 = build_function_type_list (type
,
726 build_pointer_type (integer_type_node
),
728 /* type (*) (type, int) */
729 func_scalbn
= build_function_type_list (type
,
730 type
, integer_type_node
, NULL_TREE
);
731 /* type (*) (complex type) */
732 func_cabs
= build_function_type_list (type
, complex_type
, NULL_TREE
);
733 /* complex type (*) (complex type, complex type) */
735 = build_function_type_list (complex_type
,
736 complex_type
, complex_type
, NULL_TREE
);
738 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
739 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
740 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
742 /* Only these built-ins are actually needed here. These are used directly
743 from the code, when calling builtin_decl_for_precision() or
744 builtin_decl_for_float_type(). The others are all constructed by
745 gfc_get_intrinsic_lib_fndecl(). */
746 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
747 quad_decls[BUILT_IN_ ## ID] \
748 = define_quad_builtin (gfc_real16_use_iec_60559 \
749 ? NAME "f128" : NAME "q", func_ ## TYPE, \
752 #include "mathbuiltins.def"
756 #undef DEFINE_MATH_BUILTIN
757 #undef DEFINE_MATH_BUILTIN_C
759 /* There is one built-in we defined manually, because it gets called
760 with builtin_decl_for_precision() or builtin_decl_for_float_type()
761 even though it is not an OTHER_BUILTIN: it is SQRT. */
762 quad_decls
[BUILT_IN_SQRT
]
763 = define_quad_builtin (gfc_real16_use_iec_60559
764 ? "sqrtf128" : "sqrtq", func_1
, true);
767 /* Add GCC builtin functions. */
768 for (m
= gfc_intrinsic_map
;
769 m
->id
!= GFC_ISYM_NONE
|| m
->double_built_in
!= END_BUILTINS
; m
++)
771 if (m
->float_built_in
!= END_BUILTINS
)
772 m
->real4_decl
= builtin_decl_explicit (m
->float_built_in
);
773 if (m
->complex_float_built_in
!= END_BUILTINS
)
774 m
->complex4_decl
= builtin_decl_explicit (m
->complex_float_built_in
);
775 if (m
->double_built_in
!= END_BUILTINS
)
776 m
->real8_decl
= builtin_decl_explicit (m
->double_built_in
);
777 if (m
->complex_double_built_in
!= END_BUILTINS
)
778 m
->complex8_decl
= builtin_decl_explicit (m
->complex_double_built_in
);
780 /* If real(kind=10) exists, it is always long double. */
781 if (m
->long_double_built_in
!= END_BUILTINS
)
782 m
->real10_decl
= builtin_decl_explicit (m
->long_double_built_in
);
783 if (m
->complex_long_double_built_in
!= END_BUILTINS
)
785 = builtin_decl_explicit (m
->complex_long_double_built_in
);
787 if (!gfc_real16_is_float128
)
789 if (m
->long_double_built_in
!= END_BUILTINS
)
790 m
->real16_decl
= builtin_decl_explicit (m
->long_double_built_in
);
791 if (m
->complex_long_double_built_in
!= END_BUILTINS
)
793 = builtin_decl_explicit (m
->complex_long_double_built_in
);
795 else if (quad_decls
[m
->double_built_in
] != NULL_TREE
)
797 /* Quad-precision function calls are constructed when first
798 needed by builtin_decl_for_precision(), except for those
799 that will be used directly (define by OTHER_BUILTIN). */
800 m
->real16_decl
= quad_decls
[m
->double_built_in
];
802 else if (quad_decls
[m
->complex_double_built_in
] != NULL_TREE
)
804 /* Same thing for the complex ones. */
805 m
->complex16_decl
= quad_decls
[m
->double_built_in
];
811 /* Create a fndecl for a simple intrinsic library function. */
814 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t
* m
, gfc_expr
* expr
)
817 vec
<tree
, va_gc
> *argtypes
;
819 gfc_actual_arglist
*actual
;
822 char name
[GFC_MAX_SYMBOL_LEN
+ 3];
825 if (ts
->type
== BT_REAL
)
830 pdecl
= &m
->real4_decl
;
833 pdecl
= &m
->real8_decl
;
836 pdecl
= &m
->real10_decl
;
839 pdecl
= &m
->real16_decl
;
845 else if (ts
->type
== BT_COMPLEX
)
847 gcc_assert (m
->complex_available
);
852 pdecl
= &m
->complex4_decl
;
855 pdecl
= &m
->complex8_decl
;
858 pdecl
= &m
->complex10_decl
;
861 pdecl
= &m
->complex16_decl
;
875 int n
= gfc_validate_kind (BT_REAL
, ts
->kind
, false);
876 if (gfc_real_kinds
[n
].c_float
)
877 snprintf (name
, sizeof (name
), "%s%s%s",
878 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
, "f");
879 else if (gfc_real_kinds
[n
].c_double
)
880 snprintf (name
, sizeof (name
), "%s%s",
881 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
);
882 else if (gfc_real_kinds
[n
].c_long_double
)
883 snprintf (name
, sizeof (name
), "%s%s%s",
884 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
, "l");
885 else if (gfc_real_kinds
[n
].c_float128
)
886 snprintf (name
, sizeof (name
), "%s%s%s",
887 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
,
888 gfc_real_kinds
[n
].use_iec_60559
? "f128" : "q");
894 snprintf (name
, sizeof (name
), PREFIX ("%s_%c%d"), m
->name
,
895 ts
->type
== BT_COMPLEX
? 'c' : 'r',
896 gfc_type_abi_kind (ts
));
900 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
902 type
= gfc_typenode_for_spec (&actual
->expr
->ts
);
903 vec_safe_push (argtypes
, type
);
905 type
= build_function_type_vec (gfc_typenode_for_spec (ts
), argtypes
);
906 fndecl
= build_decl (input_location
,
907 FUNCTION_DECL
, get_identifier (name
), type
);
909 /* Mark the decl as external. */
910 DECL_EXTERNAL (fndecl
) = 1;
911 TREE_PUBLIC (fndecl
) = 1;
913 /* Mark it __attribute__((const)), if possible. */
914 TREE_READONLY (fndecl
) = m
->is_constant
;
916 rest_of_decl_compilation (fndecl
, 1, 0);
923 /* Convert an intrinsic function into an external or builtin call. */
926 gfc_conv_intrinsic_lib_function (gfc_se
* se
, gfc_expr
* expr
)
928 gfc_intrinsic_map_t
*m
;
932 unsigned int num_args
;
935 id
= expr
->value
.function
.isym
->id
;
936 /* Find the entry for this function. */
937 for (m
= gfc_intrinsic_map
;
938 m
->id
!= GFC_ISYM_NONE
|| m
->double_built_in
!= END_BUILTINS
; m
++)
944 if (m
->id
== GFC_ISYM_NONE
)
946 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
947 expr
->value
.function
.name
, id
);
950 /* Get the decl and generate the call. */
951 num_args
= gfc_intrinsic_argument_list_length (expr
);
952 args
= XALLOCAVEC (tree
, num_args
);
954 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
955 fndecl
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
956 rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
958 fndecl
= build_addr (fndecl
);
959 se
->expr
= build_call_array_loc (input_location
, rettype
, fndecl
, num_args
, args
);
963 /* If bounds-checking is enabled, create code to verify at runtime that the
964 string lengths for both expressions are the same (needed for e.g. MERGE).
965 If bounds-checking is not enabled, does nothing. */
968 gfc_trans_same_strlen_check (const char* intr_name
, locus
* where
,
969 tree a
, tree b
, stmtblock_t
* target
)
974 /* If bounds-checking is disabled, do nothing. */
975 if (!(gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
))
978 /* Compare the two string lengths. */
979 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, a
, b
);
981 /* Output the runtime-check. */
982 name
= gfc_build_cstring_const (intr_name
);
983 name
= gfc_build_addr_expr (pchar_type_node
, name
);
984 gfc_trans_runtime_check (true, false, cond
, target
, where
,
985 "Unequal character lengths (%ld/%ld) in %s",
986 fold_convert (long_integer_type_node
, a
),
987 fold_convert (long_integer_type_node
, b
), name
);
991 /* The EXPONENT(X) intrinsic function is translated into
993 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
994 so that if X is a NaN or infinity, the result is HUGE(0).
998 gfc_conv_intrinsic_exponent (gfc_se
*se
, gfc_expr
*expr
)
1000 tree arg
, type
, res
, tmp
, frexp
, cond
, huge
;
1003 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
,
1004 expr
->value
.function
.actual
->expr
->ts
.kind
);
1006 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
1007 arg
= gfc_evaluate_now (arg
, &se
->pre
);
1009 i
= gfc_validate_kind (BT_INTEGER
, gfc_c_int_kind
, false);
1010 huge
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].huge
, gfc_c_int_kind
);
1011 cond
= build_call_expr_loc (input_location
,
1012 builtin_decl_explicit (BUILT_IN_ISFINITE
),
1015 res
= gfc_create_var (integer_type_node
, NULL
);
1016 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
1017 gfc_build_addr_expr (NULL_TREE
, res
));
1018 tmp
= fold_build2_loc (input_location
, COMPOUND_EXPR
, integer_type_node
,
1020 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
1023 type
= gfc_typenode_for_spec (&expr
->ts
);
1024 se
->expr
= fold_convert (type
, se
->expr
);
1028 /* Fill in the following structure
1029 struct caf_vector_t {
1030 size_t nvec; // size of the vector
1037 ptrdiff_t lower_bound;
1038 ptrdiff_t upper_bound;
1045 conv_caf_vector_subscript_elem (stmtblock_t
*block
, int i
, tree desc
,
1046 tree lower
, tree upper
, tree stride
,
1047 tree vector
, int kind
, tree nvec
)
1049 tree field
, type
, tmp
;
1051 desc
= gfc_build_array_ref (desc
, gfc_rank_cst
[i
], NULL_TREE
);
1052 type
= TREE_TYPE (desc
);
1054 field
= gfc_advance_chain (TYPE_FIELDS (type
), 0);
1055 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1056 desc
, field
, NULL_TREE
);
1057 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), nvec
));
1060 field
= gfc_advance_chain (TYPE_FIELDS (type
), 1);
1061 desc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1062 desc
, field
, NULL_TREE
);
1063 type
= TREE_TYPE (desc
);
1065 /* Access the inner struct. */
1066 field
= gfc_advance_chain (TYPE_FIELDS (type
), vector
!= NULL_TREE
? 0 : 1);
1067 desc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1068 desc
, field
, NULL_TREE
);
1069 type
= TREE_TYPE (desc
);
1071 if (vector
!= NULL_TREE
)
1073 /* Set vector and kind. */
1074 field
= gfc_advance_chain (TYPE_FIELDS (type
), 0);
1075 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1076 desc
, field
, NULL_TREE
);
1077 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), vector
));
1078 field
= gfc_advance_chain (TYPE_FIELDS (type
), 1);
1079 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1080 desc
, field
, NULL_TREE
);
1081 gfc_add_modify (block
, tmp
, build_int_cst (integer_type_node
, kind
));
1085 /* Set dim.lower/upper/stride. */
1086 field
= gfc_advance_chain (TYPE_FIELDS (type
), 0);
1087 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1088 desc
, field
, NULL_TREE
);
1089 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), lower
));
1091 field
= gfc_advance_chain (TYPE_FIELDS (type
), 1);
1092 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1093 desc
, field
, NULL_TREE
);
1094 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), upper
));
1096 field
= gfc_advance_chain (TYPE_FIELDS (type
), 2);
1097 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1098 desc
, field
, NULL_TREE
);
1099 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), stride
));
1105 conv_caf_vector_subscript (stmtblock_t
*block
, tree desc
, gfc_array_ref
*ar
)
1108 tree var
, lower
, upper
= NULL_TREE
, stride
= NULL_TREE
, vector
, nvec
;
1109 tree lbound
, ubound
, tmp
;
1112 var
= gfc_create_var (gfc_get_caf_vector_type (ar
->dimen
), "vector");
1114 for (i
= 0; i
< ar
->dimen
; i
++)
1115 switch (ar
->dimen_type
[i
])
1120 gfc_init_se (&argse
, NULL
);
1121 gfc_conv_expr (&argse
, ar
->end
[i
]);
1122 gfc_add_block_to_block (block
, &argse
.pre
);
1123 upper
= gfc_evaluate_now (argse
.expr
, block
);
1126 upper
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[i
]);
1129 gfc_init_se (&argse
, NULL
);
1130 gfc_conv_expr (&argse
, ar
->stride
[i
]);
1131 gfc_add_block_to_block (block
, &argse
.pre
);
1132 stride
= gfc_evaluate_now (argse
.expr
, block
);
1135 stride
= gfc_index_one_node
;
1141 gfc_init_se (&argse
, NULL
);
1142 gfc_conv_expr (&argse
, ar
->start
[i
]);
1143 gfc_add_block_to_block (block
, &argse
.pre
);
1144 lower
= gfc_evaluate_now (argse
.expr
, block
);
1147 lower
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[i
]);
1148 if (ar
->dimen_type
[i
] == DIMEN_ELEMENT
)
1151 stride
= gfc_index_one_node
;
1154 nvec
= size_zero_node
;
1155 conv_caf_vector_subscript_elem (block
, i
, var
, lower
, upper
, stride
,
1160 gfc_init_se (&argse
, NULL
);
1161 argse
.descriptor_only
= 1;
1162 gfc_conv_expr_descriptor (&argse
, ar
->start
[i
]);
1163 gfc_add_block_to_block (block
, &argse
.pre
);
1164 vector
= argse
.expr
;
1165 lbound
= gfc_conv_descriptor_lbound_get (vector
, gfc_rank_cst
[0]);
1166 ubound
= gfc_conv_descriptor_ubound_get (vector
, gfc_rank_cst
[0]);
1167 nvec
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
1168 tmp
= gfc_conv_descriptor_stride_get (vector
, gfc_rank_cst
[0]);
1169 nvec
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
1170 TREE_TYPE (nvec
), nvec
, tmp
);
1171 lower
= gfc_index_zero_node
;
1172 upper
= gfc_index_zero_node
;
1173 stride
= gfc_index_zero_node
;
1174 vector
= gfc_conv_descriptor_data_get (vector
);
1175 conv_caf_vector_subscript_elem (block
, i
, var
, lower
, upper
, stride
,
1176 vector
, ar
->start
[i
]->ts
.kind
, nvec
);
1181 return gfc_build_addr_expr (NULL_TREE
, var
);
1186 compute_component_offset (tree field
, tree type
)
1189 if (DECL_FIELD_BIT_OFFSET (field
) != NULL_TREE
1190 && !integer_zerop (DECL_FIELD_BIT_OFFSET (field
)))
1192 tmp
= fold_build2 (TRUNC_DIV_EXPR
, type
,
1193 DECL_FIELD_BIT_OFFSET (field
),
1195 return fold_build2 (PLUS_EXPR
, type
, DECL_FIELD_OFFSET (field
), tmp
);
1198 return DECL_FIELD_OFFSET (field
);
1203 conv_expr_ref_to_caf_ref (stmtblock_t
*block
, gfc_expr
*expr
)
1205 gfc_ref
*ref
= expr
->ref
, *last_comp_ref
;
1206 tree caf_ref
= NULL_TREE
, prev_caf_ref
= NULL_TREE
, reference_type
, tmp
, tmp2
,
1207 field
, last_type
, inner_struct
, mode
, mode_rhs
, dim_array
, dim
, dim_type
,
1208 start
, end
, stride
, vector
, nvec
;
1210 bool ref_static_array
= false;
1211 tree last_component_ref_tree
= NULL_TREE
;
1216 last_component_ref_tree
= expr
->symtree
->n
.sym
->backend_decl
;
1217 ref_static_array
= !expr
->symtree
->n
.sym
->attr
.allocatable
1218 && !expr
->symtree
->n
.sym
->attr
.pointer
;
1221 /* Prevent uninit-warning. */
1222 reference_type
= NULL_TREE
;
1224 /* Skip refs upto the first coarray-ref. */
1225 last_comp_ref
= NULL
;
1226 while (ref
&& (ref
->type
!= REF_ARRAY
|| ref
->u
.ar
.codimen
== 0))
1228 /* Remember the type of components skipped. */
1229 if (ref
->type
== REF_COMPONENT
)
1230 last_comp_ref
= ref
;
1233 /* When a component was skipped, get the type information of the last
1234 component ref, else get the type from the symbol. */
1237 last_type
= gfc_typenode_for_spec (&last_comp_ref
->u
.c
.component
->ts
);
1238 last_type_n
= last_comp_ref
->u
.c
.component
->ts
.type
;
1242 last_type
= gfc_typenode_for_spec (&expr
->symtree
->n
.sym
->ts
);
1243 last_type_n
= expr
->symtree
->n
.sym
->ts
.type
;
1248 if (ref
->type
== REF_ARRAY
&& ref
->u
.ar
.codimen
> 0
1249 && ref
->u
.ar
.dimen
== 0)
1251 /* Skip pure coindexes. */
1255 tmp
= gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
1256 reference_type
= TREE_TYPE (tmp
);
1258 if (caf_ref
== NULL_TREE
)
1261 /* Construct the chain of refs. */
1262 if (prev_caf_ref
!= NULL_TREE
)
1264 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 0);
1265 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1266 TREE_TYPE (field
), prev_caf_ref
, field
,
1268 gfc_add_modify (block
, tmp2
, gfc_build_addr_expr (TREE_TYPE (field
),
1276 last_type
= gfc_typenode_for_spec (&ref
->u
.c
.component
->ts
);
1277 last_type_n
= ref
->u
.c
.component
->ts
.type
;
1278 /* Set the type of the ref. */
1279 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 1);
1280 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1281 TREE_TYPE (field
), prev_caf_ref
, field
,
1283 gfc_add_modify (block
, tmp
, build_int_cst (integer_type_node
,
1284 GFC_CAF_REF_COMPONENT
));
1286 /* Ref the c in union u. */
1287 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 3);
1288 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1289 TREE_TYPE (field
), prev_caf_ref
, field
,
1291 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field
)), 0);
1292 inner_struct
= fold_build3_loc (input_location
, COMPONENT_REF
,
1293 TREE_TYPE (field
), tmp
, field
,
1296 /* Set the offset. */
1297 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)), 0);
1298 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1299 TREE_TYPE (field
), inner_struct
, field
,
1301 /* Computing the offset is somewhat harder. The bit_offset has to be
1302 taken into account. When the bit_offset in the field_decl is non-
1303 null, divide it by the bitsize_unit and add it to the regular
1305 tmp2
= compute_component_offset (ref
->u
.c
.component
->backend_decl
,
1307 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (tmp
), tmp2
));
1309 /* Set caf_token_offset. */
1310 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)), 1);
1311 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1312 TREE_TYPE (field
), inner_struct
, field
,
1314 if ((ref
->u
.c
.component
->attr
.allocatable
1315 || ref
->u
.c
.component
->attr
.pointer
)
1316 && ref
->u
.c
.component
->attr
.dimension
)
1318 tree arr_desc_token_offset
;
1319 /* Get the token field from the descriptor. */
1320 arr_desc_token_offset
= TREE_OPERAND (
1321 gfc_conv_descriptor_token (ref
->u
.c
.component
->backend_decl
), 1);
1322 arr_desc_token_offset
1323 = compute_component_offset (arr_desc_token_offset
,
1325 tmp2
= fold_build2_loc (input_location
, PLUS_EXPR
,
1326 TREE_TYPE (tmp2
), tmp2
,
1327 arr_desc_token_offset
);
1329 else if (ref
->u
.c
.component
->caf_token
)
1330 tmp2
= compute_component_offset (gfc_comp_caf_token (
1331 ref
->u
.c
.component
),
1334 tmp2
= integer_zero_node
;
1335 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (tmp
), tmp2
));
1337 /* Remember whether this ref was to a non-allocatable/non-pointer
1338 component so the next array ref can be tailored correctly. */
1339 ref_static_array
= !ref
->u
.c
.component
->attr
.allocatable
1340 && !ref
->u
.c
.component
->attr
.pointer
;
1341 last_component_ref_tree
= ref_static_array
1342 ? ref
->u
.c
.component
->backend_decl
: NULL_TREE
;
1345 if (ref_static_array
&& ref
->u
.ar
.as
->type
== AS_DEFERRED
)
1346 ref_static_array
= false;
1347 /* Set the type of the ref. */
1348 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 1);
1349 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1350 TREE_TYPE (field
), prev_caf_ref
, field
,
1352 gfc_add_modify (block
, tmp
, build_int_cst (integer_type_node
,
1354 ? GFC_CAF_REF_STATIC_ARRAY
1355 : GFC_CAF_REF_ARRAY
));
1357 /* Ref the a in union u. */
1358 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 3);
1359 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1360 TREE_TYPE (field
), prev_caf_ref
, field
,
1362 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field
)), 1);
1363 inner_struct
= fold_build3_loc (input_location
, COMPONENT_REF
,
1364 TREE_TYPE (field
), tmp
, field
,
1367 /* Set the static_array_type in a for static arrays. */
1368 if (ref_static_array
)
1370 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)),
1372 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1373 TREE_TYPE (field
), inner_struct
, field
,
1375 gfc_add_modify (block
, tmp
, build_int_cst (TREE_TYPE (tmp
),
1378 /* Ref the mode in the inner_struct. */
1379 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)), 0);
1380 mode
= fold_build3_loc (input_location
, COMPONENT_REF
,
1381 TREE_TYPE (field
), inner_struct
, field
,
1383 /* Ref the dim in the inner_struct. */
1384 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)), 2);
1385 dim_array
= fold_build3_loc (input_location
, COMPONENT_REF
,
1386 TREE_TYPE (field
), inner_struct
, field
,
1388 for (i
= 0; i
< ref
->u
.ar
.dimen
; ++i
)
1391 dim
= gfc_build_array_ref (dim_array
, gfc_rank_cst
[i
], NULL_TREE
);
1392 dim_type
= TREE_TYPE (dim
);
1393 mode_rhs
= start
= end
= stride
= NULL_TREE
;
1394 switch (ref
->u
.ar
.dimen_type
[i
])
1397 if (ref
->u
.ar
.end
[i
])
1399 gfc_init_se (&se
, NULL
);
1400 gfc_conv_expr (&se
, ref
->u
.ar
.end
[i
]);
1401 gfc_add_block_to_block (block
, &se
.pre
);
1402 if (ref_static_array
)
1404 /* Make the index zero-based, when reffing a static
1407 gfc_init_se (&se
, NULL
);
1408 gfc_conv_expr (&se
, ref
->u
.ar
.as
->lower
[i
]);
1409 gfc_add_block_to_block (block
, &se
.pre
);
1410 se
.expr
= fold_build2 (MINUS_EXPR
,
1411 gfc_array_index_type
,
1413 gfc_array_index_type
,
1416 end
= gfc_evaluate_now (fold_convert (
1417 gfc_array_index_type
,
1421 else if (ref_static_array
)
1422 end
= fold_build2 (MINUS_EXPR
,
1423 gfc_array_index_type
,
1424 gfc_conv_array_ubound (
1425 last_component_ref_tree
, i
),
1426 gfc_conv_array_lbound (
1427 last_component_ref_tree
, i
));
1431 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1432 GFC_CAF_ARR_REF_OPEN_END
);
1434 if (ref
->u
.ar
.stride
[i
])
1436 gfc_init_se (&se
, NULL
);
1437 gfc_conv_expr (&se
, ref
->u
.ar
.stride
[i
]);
1438 gfc_add_block_to_block (block
, &se
.pre
);
1439 stride
= gfc_evaluate_now (fold_convert (
1440 gfc_array_index_type
,
1443 if (ref_static_array
)
1445 /* Make the index zero-based, when reffing a static
1447 stride
= fold_build2 (MULT_EXPR
,
1448 gfc_array_index_type
,
1449 gfc_conv_array_stride (
1450 last_component_ref_tree
,
1453 gcc_assert (end
!= NULL_TREE
);
1454 /* Multiply with the product of array's stride and
1455 the step of the ref to a virtual upper bound.
1456 We cannot compute the actual upper bound here or
1457 the caflib would compute the extend
1459 end
= fold_build2 (MULT_EXPR
, gfc_array_index_type
,
1460 end
, gfc_conv_array_stride (
1461 last_component_ref_tree
,
1463 end
= gfc_evaluate_now (end
, block
);
1464 stride
= gfc_evaluate_now (stride
, block
);
1467 else if (ref_static_array
)
1469 stride
= gfc_conv_array_stride (last_component_ref_tree
,
1471 end
= fold_build2 (MULT_EXPR
, gfc_array_index_type
,
1473 end
= gfc_evaluate_now (end
, block
);
1476 /* Always set a ref stride of one to make caflib's
1478 stride
= gfc_index_one_node
;
1482 if (ref
->u
.ar
.start
[i
])
1484 gfc_init_se (&se
, NULL
);
1485 gfc_conv_expr (&se
, ref
->u
.ar
.start
[i
]);
1486 gfc_add_block_to_block (block
, &se
.pre
);
1487 if (ref_static_array
)
1489 /* Make the index zero-based, when reffing a static
1491 start
= fold_convert (gfc_array_index_type
, se
.expr
);
1492 gfc_init_se (&se
, NULL
);
1493 gfc_conv_expr (&se
, ref
->u
.ar
.as
->lower
[i
]);
1494 gfc_add_block_to_block (block
, &se
.pre
);
1495 se
.expr
= fold_build2 (MINUS_EXPR
,
1496 gfc_array_index_type
,
1497 start
, fold_convert (
1498 gfc_array_index_type
,
1500 /* Multiply with the stride. */
1501 se
.expr
= fold_build2 (MULT_EXPR
,
1502 gfc_array_index_type
,
1504 gfc_conv_array_stride (
1505 last_component_ref_tree
,
1508 start
= gfc_evaluate_now (fold_convert (
1509 gfc_array_index_type
,
1512 if (mode_rhs
== NULL_TREE
)
1513 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1514 ref
->u
.ar
.dimen_type
[i
]
1516 ? GFC_CAF_ARR_REF_SINGLE
1517 : GFC_CAF_ARR_REF_RANGE
);
1519 else if (ref_static_array
)
1521 start
= integer_zero_node
;
1522 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1523 ref
->u
.ar
.start
[i
] == NULL
1524 ? GFC_CAF_ARR_REF_FULL
1525 : GFC_CAF_ARR_REF_RANGE
);
1527 else if (end
== NULL_TREE
)
1528 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1529 GFC_CAF_ARR_REF_FULL
);
1531 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1532 GFC_CAF_ARR_REF_OPEN_START
);
1534 /* Ref the s in dim. */
1535 field
= gfc_advance_chain (TYPE_FIELDS (dim_type
), 0);
1536 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1537 TREE_TYPE (field
), dim
, field
,
1540 /* Set start in s. */
1541 if (start
!= NULL_TREE
)
1543 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)),
1545 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1546 TREE_TYPE (field
), tmp
, field
,
1548 gfc_add_modify (block
, tmp2
,
1549 fold_convert (TREE_TYPE (tmp2
), start
));
1553 if (end
!= NULL_TREE
)
1555 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)),
1557 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1558 TREE_TYPE (field
), tmp
, field
,
1560 gfc_add_modify (block
, tmp2
,
1561 fold_convert (TREE_TYPE (tmp2
), end
));
1565 if (stride
!= NULL_TREE
)
1567 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)),
1569 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1570 TREE_TYPE (field
), tmp
, field
,
1572 gfc_add_modify (block
, tmp2
,
1573 fold_convert (TREE_TYPE (tmp2
), stride
));
1577 /* TODO: In case of static array. */
1578 gcc_assert (!ref_static_array
);
1579 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1580 GFC_CAF_ARR_REF_VECTOR
);
1581 gfc_init_se (&se
, NULL
);
1582 se
.descriptor_only
= 1;
1583 gfc_conv_expr_descriptor (&se
, ref
->u
.ar
.start
[i
]);
1584 gfc_add_block_to_block (block
, &se
.pre
);
1586 tmp
= gfc_conv_descriptor_lbound_get (vector
,
1588 tmp2
= gfc_conv_descriptor_ubound_get (vector
,
1590 nvec
= gfc_conv_array_extent_dim (tmp
, tmp2
, NULL
);
1591 tmp
= gfc_conv_descriptor_stride_get (vector
,
1593 nvec
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
1594 TREE_TYPE (nvec
), nvec
, tmp
);
1595 vector
= gfc_conv_descriptor_data_get (vector
);
1597 /* Ref the v in dim. */
1598 field
= gfc_advance_chain (TYPE_FIELDS (dim_type
), 1);
1599 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1600 TREE_TYPE (field
), dim
, field
,
1603 /* Set vector in v. */
1604 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)), 0);
1605 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1606 TREE_TYPE (field
), tmp
, field
,
1608 gfc_add_modify (block
, tmp2
, fold_convert (TREE_TYPE (tmp2
),
1611 /* Set nvec in v. */
1612 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)), 1);
1613 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1614 TREE_TYPE (field
), tmp
, field
,
1616 gfc_add_modify (block
, tmp2
, fold_convert (TREE_TYPE (tmp2
),
1619 /* Set kind in v. */
1620 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)), 2);
1621 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1622 TREE_TYPE (field
), tmp
, field
,
1624 gfc_add_modify (block
, tmp2
, build_int_cst (integer_type_node
,
1625 ref
->u
.ar
.start
[i
]->ts
.kind
));
1630 /* Set the mode for dim i. */
1631 tmp
= gfc_build_array_ref (mode
, gfc_rank_cst
[i
], NULL_TREE
);
1632 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (tmp
),
1636 /* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
1637 if (i
< GFC_MAX_DIMENSIONS
)
1639 tmp
= gfc_build_array_ref (mode
, gfc_rank_cst
[i
], NULL_TREE
);
1640 gfc_add_modify (block
, tmp
,
1641 build_int_cst (unsigned_char_type_node
,
1642 GFC_CAF_ARR_REF_NONE
));
1649 /* Set the size of the current type. */
1650 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 2);
1651 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1652 prev_caf_ref
, field
, NULL_TREE
);
1653 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
),
1654 TYPE_SIZE_UNIT (last_type
)));
1659 if (prev_caf_ref
!= NULL_TREE
)
1661 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 0);
1662 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1663 prev_caf_ref
, field
, NULL_TREE
);
1664 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
),
1665 null_pointer_node
));
1667 return caf_ref
!= NULL_TREE
? gfc_build_addr_expr (NULL_TREE
, caf_ref
)
1672 conv_shape_to_cst (gfc_expr
*e
)
1675 for (int d
= 0; d
< e
->rank
; ++d
)
1678 tmp
= gfc_conv_mpz_to_tree (e
->shape
[d
], gfc_size_kind
);
1680 tmp
= fold_build2 (MULT_EXPR
, TREE_TYPE (tmp
), tmp
,
1681 gfc_conv_mpz_to_tree (e
->shape
[d
], gfc_size_kind
));
1683 return fold_convert (size_type_node
, tmp
);
1686 /* Get data from a remote coarray. */
1689 gfc_conv_intrinsic_caf_get (gfc_se
*se
, gfc_expr
*expr
, tree lhs
,
1690 bool may_realloc
, symbol_attribute
*caf_attr
)
1692 static int call_cnt
= 0;
1693 gfc_expr
*array_expr
, *tmp_stat
;
1695 tree caf_decl
, token
, image_index
, tmp
, res_var
, type
, stat
, dest_size
,
1696 dest_data
, opt_dest_desc
, rget_index_tree
, rget_data_tree
, rget_data_size
,
1697 opt_src_desc
, opt_src_charlen
, opt_dest_charlen
;
1698 symbol_attribute caf_attr_store
;
1700 gfc_expr
*rget_hash
= expr
->value
.function
.actual
->next
->expr
,
1701 *rget_fn_expr
= expr
->value
.function
.actual
->next
->next
->expr
;
1702 gfc_symbol
*gdata_sym
1703 = rget_fn_expr
->symtree
->n
.sym
->formal
->next
->next
->next
->sym
;
1704 gfc_expr rget_data
, rget_data_init
, rget_index
;
1706 gfc_symtree
*data_st
, *index_st
;
1707 gfc_constructor
*con
;
1710 gcc_assert (flag_coarray
== GFC_FCOARRAY_LIB
);
1712 if (se
->ss
&& se
->ss
->info
->useflags
)
1714 /* Access the previously obtained result. */
1715 gfc_conv_tmp_array_ref (se
);
1719 array_expr
= expr
->value
.function
.actual
->expr
;
1720 ns
= array_expr
->expr_type
== EXPR_VARIABLE
1721 && !array_expr
->symtree
->n
.sym
->attr
.associate_var
1722 ? array_expr
->symtree
->n
.sym
->ns
1724 type
= gfc_typenode_for_spec (&array_expr
->ts
);
1726 if (caf_attr
== NULL
)
1728 caf_attr_store
= gfc_caf_attr (array_expr
);
1729 caf_attr
= &caf_attr_store
;
1734 tmp_stat
= gfc_find_stat_co (expr
);
1739 gfc_init_se (&stat_se
, NULL
);
1740 gfc_conv_expr_reference (&stat_se
, tmp_stat
);
1741 stat
= stat_se
.expr
;
1742 gfc_add_block_to_block (&se
->pre
, &stat_se
.pre
);
1743 gfc_add_block_to_block (&se
->post
, &stat_se
.post
);
1746 stat
= null_pointer_node
;
1748 memset (&rget_data
, 0, sizeof (gfc_expr
));
1749 gfc_clear_ts (&rget_data
.ts
);
1750 rget_data
.expr_type
= EXPR_VARIABLE
;
1751 name
= xasprintf ("__caf_rget_data_%d", call_cnt
);
1752 gcc_assert (!gfc_get_sym_tree (name
, ns
, &data_st
, false));
1753 name
= xasprintf ("__caf_rget_index_%d", call_cnt
);
1755 gcc_assert (!gfc_get_sym_tree (name
, ns
, &index_st
, false));
1757 data_st
->n
.sym
->attr
.flavor
= FL_VARIABLE
;
1758 data_st
->n
.sym
->ts
= gdata_sym
->ts
;
1759 rget_data
.symtree
= data_st
;
1760 gfc_set_sym_referenced (rget_data
.symtree
->n
.sym
);
1761 rget_data
.ts
= data_st
->n
.sym
->ts
;
1762 gfc_commit_symbol (data_st
->n
.sym
);
1764 memset (&rget_data_init
, 0, sizeof (gfc_expr
));
1765 gfc_clear_ts (&rget_data_init
.ts
);
1766 rget_data_init
.expr_type
= EXPR_STRUCTURE
;
1767 rget_data_init
.ts
= rget_data
.ts
;
1768 for (gfc_component
*comp
= rget_data
.ts
.u
.derived
->components
; comp
;
1771 con
= gfc_constructor_get ();
1772 con
->expr
= comp
->initializer
;
1773 comp
->initializer
= NULL
;
1774 gfc_constructor_append (&rget_data_init
.value
.constructor
, con
);
1777 index_st
->n
.sym
->attr
.flavor
= FL_VARIABLE
;
1778 index_st
->n
.sym
->attr
.save
= SAVE_EXPLICIT
;
1779 index_st
->n
.sym
->value
1780 = gfc_get_constant_expr (BT_INTEGER
, gfc_default_integer_kind
,
1781 &gfc_current_locus
);
1782 mpz_init_set_si (index_st
->n
.sym
->value
->value
.integer
, -1);
1783 index_st
->n
.sym
->ts
.type
= BT_INTEGER
;
1784 index_st
->n
.sym
->ts
.kind
= gfc_default_integer_kind
;
1785 gfc_set_sym_referenced (index_st
->n
.sym
);
1786 memset (&rget_index
, 0, sizeof (gfc_expr
));
1787 gfc_clear_ts (&rget_index
.ts
);
1788 rget_index
.expr_type
= EXPR_VARIABLE
;
1789 rget_index
.symtree
= index_st
;
1790 rget_index
.ts
= index_st
->n
.sym
->ts
;
1791 gfc_commit_symbol (index_st
->n
.sym
);
1793 gfc_init_se (&argse
, NULL
);
1794 gfc_conv_expr (&argse
, &rget_index
);
1795 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1796 rget_index_tree
= argse
.expr
;
1798 gfc_init_se (&argse
, NULL
);
1799 gfc_conv_expr (&argse
, rget_hash
);
1801 gfc_init_block (&blk
);
1802 tmp
= build_call_expr (gfor_fndecl_caf_get_remote_function_index
, 1,
1805 gfc_add_modify (&blk
, rget_index_tree
, tmp
);
1806 gfc_add_expr_to_block (
1808 build3 (COND_EXPR
, void_type_node
,
1809 gfc_likely (build2 (EQ_EXPR
, logical_type_node
, rget_index_tree
,
1810 build_int_cst (integer_type_node
, -1)),
1812 gfc_finish_block (&blk
), NULL_TREE
));
1814 if (rget_data
.ts
.u
.derived
->components
)
1816 gfc_init_se (&argse
, NULL
);
1817 gfc_conv_expr (&argse
, &rget_data
);
1818 rget_data_tree
= argse
.expr
;
1819 gfc_add_expr_to_block (&se
->pre
,
1820 gfc_trans_structure_assign (rget_data_tree
,
1821 &rget_data_init
, true,
1823 gfc_constructor_free (rget_data_init
.value
.constructor
);
1824 rget_data_size
= TREE_TYPE (rget_data_tree
)->type_common
.size_unit
;
1825 rget_data_tree
= gfc_build_addr_expr (pvoid_type_node
, rget_data_tree
);
1829 rget_data_tree
= build_zero_cst (pvoid_type_node
);
1830 rget_data_size
= build_zero_cst (size_type_node
);
1833 if (array_expr
->rank
== 0)
1835 res_var
= gfc_create_var (type
, "caf_res");
1836 if (array_expr
->ts
.type
== BT_CHARACTER
)
1838 gfc_conv_string_length (array_expr
->ts
.u
.cl
, array_expr
, &se
->pre
);
1839 argse
.string_length
= array_expr
->ts
.u
.cl
->backend_decl
;
1840 opt_src_charlen
= gfc_build_addr_expr (
1841 NULL_TREE
, gfc_trans_force_lval (&se
->pre
, argse
.string_length
));
1842 dest_size
= build_int_cstu (size_type_node
, array_expr
->ts
.kind
);
1846 dest_size
= res_var
->typed
.type
->type_common
.size_unit
;
1848 = build_zero_cst (build_pointer_type (size_type_node
));
1851 = gfc_evaluate_now (gfc_build_addr_expr (NULL_TREE
, res_var
), &se
->pre
);
1852 res_var
= build_fold_indirect_ref (dest_data
);
1853 dest_data
= gfc_build_addr_expr (pvoid_type_node
, dest_data
);
1854 opt_dest_desc
= build_zero_cst (pvoid_type_node
);
1858 /* Create temporary. */
1859 may_realloc
= gfc_trans_create_temp_array (&se
->pre
, &se
->post
, se
->ss
,
1860 type
, NULL_TREE
, false, false,
1861 false, &array_expr
->where
)
1863 res_var
= se
->ss
->info
->data
.array
.descriptor
;
1864 if (array_expr
->ts
.type
== BT_CHARACTER
)
1866 argse
.string_length
= array_expr
->ts
.u
.cl
->backend_decl
;
1867 opt_src_charlen
= gfc_build_addr_expr (
1868 NULL_TREE
, gfc_trans_force_lval (&se
->pre
, argse
.string_length
));
1869 dest_size
= build_int_cstu (size_type_node
, array_expr
->ts
.kind
);
1874 = build_zero_cst (build_pointer_type (size_type_node
));
1875 dest_size
= fold_build2 (
1876 MULT_EXPR
, size_type_node
,
1877 fold_convert (size_type_node
,
1879 ? conv_shape_to_cst (array_expr
)
1880 : gfc_conv_descriptor_size (res_var
,
1882 fold_convert (size_type_node
,
1883 gfc_conv_descriptor_span_get (res_var
)));
1885 opt_dest_desc
= res_var
;
1886 dest_data
= gfc_conv_descriptor_data_get (res_var
);
1887 opt_dest_desc
= gfc_build_addr_expr (NULL_TREE
, opt_dest_desc
);
1890 tmp
= gfc_conv_descriptor_data_get (res_var
);
1891 tmp
= gfc_deallocate_with_status (tmp
, NULL_TREE
, NULL_TREE
,
1892 NULL_TREE
, NULL_TREE
, true, NULL
,
1893 GFC_CAF_COARRAY_NOCOARRAY
);
1894 gfc_add_expr_to_block (&se
->post
, tmp
);
1897 = gfc_build_addr_expr (NULL_TREE
,
1898 gfc_trans_force_lval (&se
->pre
, dest_data
));
1901 opt_dest_charlen
= opt_src_charlen
;
1902 caf_decl
= gfc_get_tree_for_caf_expr (array_expr
);
1903 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
1904 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
1906 if (!TYPE_LANG_SPECIFIC (TREE_TYPE (caf_decl
))->rank
1907 || GFC_ARRAY_TYPE_P (TREE_TYPE (caf_decl
)))
1908 opt_src_desc
= build_zero_cst (pvoid_type_node
);
1910 opt_src_desc
= gfc_build_addr_expr (pvoid_type_node
, caf_decl
);
1912 image_index
= gfc_caf_get_image_index (&se
->pre
, array_expr
, caf_decl
);
1913 gfc_get_caf_token_offset (se
, &token
, NULL
, caf_decl
, NULL
, array_expr
);
1915 /* It guarantees memory consistency within the same segment. */
1916 tmp
= gfc_build_string_const (strlen ("memory") + 1, "memory");
1917 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
1918 gfc_build_string_const (1, ""), NULL_TREE
, NULL_TREE
,
1919 tree_cons (NULL_TREE
, tmp
, NULL_TREE
), NULL_TREE
);
1920 ASM_VOLATILE_P (tmp
) = 1;
1921 gfc_add_expr_to_block (&se
->pre
, tmp
);
1923 tmp
= build_call_expr_loc (
1924 input_location
, gfor_fndecl_caf_get_by_ct
, 15, token
, opt_src_desc
,
1925 opt_src_charlen
, image_index
, dest_size
, dest_data
, opt_dest_charlen
,
1926 opt_dest_desc
, constant_boolean_node (may_realloc
, boolean_type_node
),
1927 rget_index_tree
, rget_data_tree
, rget_data_size
, stat
, null_pointer_node
,
1930 gfc_add_expr_to_block (&se
->pre
, tmp
);
1933 gfc_advance_se_ss_chain (se
);
1936 if (array_expr
->ts
.type
== BT_CHARACTER
)
1937 se
->string_length
= argse
.string_length
;
1943 has_ref_after_cafref (gfc_expr
*expr
)
1945 for (gfc_ref
*ref
= expr
->ref
; ref
; ref
= ref
->next
)
1946 if (ref
->type
== REF_ARRAY
&& ref
->u
.ar
.codimen
)
1951 /* Send data to a remote coarray. */
1954 conv_caf_send (gfc_code
*code
) {
1955 gfc_expr
*lhs_expr
, *rhs_expr
, *tmp_stat
, *tmp_team
;
1956 gfc_se lhs_se
, rhs_se
;
1958 tree caf_decl
, token
, offset
, image_index
, tmp
, lhs_kind
, rhs_kind
;
1959 tree may_require_tmp
, src_stat
, dst_stat
, dst_team
;
1960 tree lhs_type
= NULL_TREE
;
1961 tree vec
= null_pointer_node
, rhs_vec
= null_pointer_node
;
1962 symbol_attribute lhs_caf_attr
, rhs_caf_attr
;
1963 bool lhs_is_coindexed
, rhs_is_coindexed
;
1965 gcc_assert (flag_coarray
== GFC_FCOARRAY_LIB
);
1968 = code
->ext
.actual
->expr
->expr_type
== EXPR_FUNCTION
1969 && code
->ext
.actual
->expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
1970 ? code
->ext
.actual
->expr
->value
.function
.actual
->expr
1971 : code
->ext
.actual
->expr
;
1972 rhs_expr
= code
->ext
.actual
->next
->expr
->expr_type
== EXPR_FUNCTION
1973 && code
->ext
.actual
->next
->expr
->value
.function
.isym
->id
1975 ? code
->ext
.actual
->next
->expr
->value
.function
.actual
->expr
1976 : code
->ext
.actual
->next
->expr
;
1977 lhs_is_coindexed
= gfc_is_coindexed (lhs_expr
);
1978 rhs_is_coindexed
= gfc_is_coindexed (rhs_expr
);
1979 may_require_tmp
= gfc_check_dependency (lhs_expr
, rhs_expr
, true) == 0
1980 ? boolean_false_node
: boolean_true_node
;
1981 gfc_init_block (&block
);
1983 lhs_caf_attr
= gfc_caf_attr (lhs_expr
);
1984 rhs_caf_attr
= gfc_caf_attr (rhs_expr
);
1985 src_stat
= dst_stat
= null_pointer_node
;
1986 dst_team
= null_pointer_node
;
1989 gfc_init_se (&lhs_se
, NULL
);
1990 if (lhs_expr
->rank
== 0)
1992 if (lhs_expr
->ts
.type
== BT_CHARACTER
&& lhs_expr
->ts
.deferred
)
1994 lhs_se
.expr
= gfc_get_tree_for_caf_expr (lhs_expr
);
1995 if (!POINTER_TYPE_P (TREE_TYPE (lhs_se
.expr
)))
1996 lhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, lhs_se
.expr
);
2000 symbol_attribute attr
;
2001 gfc_clear_attr (&attr
);
2002 gfc_conv_expr (&lhs_se
, lhs_expr
);
2003 lhs_type
= TREE_TYPE (lhs_se
.expr
);
2004 if (lhs_is_coindexed
)
2005 lhs_se
.expr
= gfc_conv_scalar_to_descriptor (&lhs_se
, lhs_se
.expr
,
2007 lhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, lhs_se
.expr
);
2010 else if ((lhs_caf_attr
.alloc_comp
|| lhs_caf_attr
.pointer_comp
)
2011 && lhs_caf_attr
.codimension
)
2013 lhs_se
.want_pointer
= 1;
2014 gfc_conv_expr_descriptor (&lhs_se
, lhs_expr
);
2015 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2016 has the wrong type if component references are done. */
2017 lhs_type
= gfc_typenode_for_spec (&lhs_expr
->ts
);
2018 tmp
= build_fold_indirect_ref_loc (input_location
, lhs_se
.expr
);
2019 gfc_add_modify (&lhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
2020 gfc_get_dtype_rank_type (
2021 gfc_has_vector_subscript (lhs_expr
)
2022 ? gfc_find_array_ref (lhs_expr
)->dimen
2028 bool has_vector
= gfc_has_vector_subscript (lhs_expr
);
2030 if (lhs_is_coindexed
|| !has_vector
)
2032 /* If has_vector, pass descriptor for whole array and the
2033 vector bounds separately. */
2034 gfc_array_ref
*ar
, ar2
;
2035 bool has_tmp_lhs_array
= false;
2038 has_tmp_lhs_array
= true;
2039 ar
= gfc_find_array_ref (lhs_expr
);
2041 memset (ar
, '\0', sizeof (*ar
));
2045 lhs_se
.want_pointer
= 1;
2046 gfc_conv_expr_descriptor (&lhs_se
, lhs_expr
);
2047 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but
2048 that has the wrong type if component references are done. */
2049 lhs_type
= gfc_typenode_for_spec (&lhs_expr
->ts
);
2050 tmp
= build_fold_indirect_ref_loc (input_location
, lhs_se
.expr
);
2051 gfc_add_modify (&lhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
2052 gfc_get_dtype_rank_type (has_vector
? ar2
.dimen
2055 if (has_tmp_lhs_array
)
2057 vec
= conv_caf_vector_subscript (&block
, lhs_se
.expr
, &ar2
);
2061 else if (rhs_is_coindexed
)
2063 /* Special casing for arr1 ([...]) = arr2[...], i.e. caf_get to
2064 indexed array expression. This is rewritten to:
2066 tmp_array = arr2[...]
2067 arr1 ([...]) = tmp_array
2069 because using the standard gfc_conv_expr (lhs_expr) did the
2070 assignment with lhs and rhs exchanged. */
2072 gfc_ss
*lss_for_tmparray
, *lss_real
;
2076 tree tmparr_desc
, src
;
2077 tree index
= gfc_index_zero_node
;
2078 tree stride
= gfc_index_zero_node
;
2081 /* Walk both sides of the assignment, once to get the shape of the
2082 temporary array to create right. */
2083 lss_for_tmparray
= gfc_walk_expr (lhs_expr
);
2084 /* And a second time to be able to create an assignment of the
2085 temporary to the lhs_expr. gfc_trans_create_temp_array replaces
2086 the tree in the descriptor with the one for the temporary
2088 lss_real
= gfc_walk_expr (lhs_expr
);
2089 gfc_init_loopinfo (&loop
);
2090 gfc_add_ss_to_loop (&loop
, lss_for_tmparray
);
2091 gfc_add_ss_to_loop (&loop
, lss_real
);
2092 gfc_conv_ss_startstride (&loop
);
2093 gfc_conv_loop_setup (&loop
, &lhs_expr
->where
);
2094 lhs_type
= gfc_typenode_for_spec (&lhs_expr
->ts
);
2095 gfc_trans_create_temp_array (&lhs_se
.pre
, &lhs_se
.post
,
2096 lss_for_tmparray
, lhs_type
, NULL_TREE
,
2099 tmparr_desc
= lss_for_tmparray
->info
->data
.array
.descriptor
;
2100 gfc_start_scalarized_body (&loop
, &body
);
2101 gfc_init_se (&se
, NULL
);
2102 gfc_copy_loopinfo_to_se (&se
, &loop
);
2104 gfc_conv_expr (&se
, lhs_expr
);
2105 gfc_add_block_to_block (&body
, &se
.pre
);
2107 /* Walk over all indexes of the loop. */
2108 for (n
= loop
.dimen
- 1; n
> 0; --n
)
2110 tmp
= loop
.loopvar
[n
];
2111 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
2112 gfc_array_index_type
, tmp
, loop
.from
[n
]);
2113 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
2114 gfc_array_index_type
, tmp
, index
);
2116 stride
= fold_build2_loc (input_location
, MINUS_EXPR
,
2117 gfc_array_index_type
,
2118 loop
.to
[n
- 1], loop
.from
[n
- 1]);
2119 stride
= fold_build2_loc (input_location
, PLUS_EXPR
,
2120 gfc_array_index_type
,
2121 stride
, gfc_index_one_node
);
2123 index
= fold_build2_loc (input_location
, MULT_EXPR
,
2124 gfc_array_index_type
, tmp
, stride
);
2127 index
= fold_build2_loc (input_location
, MINUS_EXPR
,
2128 gfc_array_index_type
,
2129 index
, loop
.from
[0]);
2131 index
= fold_build2_loc (input_location
, PLUS_EXPR
,
2132 gfc_array_index_type
,
2133 loop
.loopvar
[0], index
);
2135 src
= build_fold_indirect_ref (gfc_conv_array_data (tmparr_desc
));
2136 src
= gfc_build_array_ref (src
, index
, NULL
);
2137 /* Now create the assignment of lhs_expr = tmp_array. */
2138 gfc_add_modify (&body
, se
.expr
, src
);
2139 gfc_add_block_to_block (&body
, &se
.post
);
2140 lhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, tmparr_desc
);
2141 gfc_trans_scalarizing_loops (&loop
, &body
);
2142 gfc_add_block_to_block (&loop
.pre
, &loop
.post
);
2143 gfc_add_expr_to_block (&lhs_se
.post
, gfc_finish_block (&loop
.pre
));
2144 gfc_free_ss (lss_for_tmparray
);
2145 gfc_free_ss (lss_real
);
2149 lhs_kind
= build_int_cst (integer_type_node
, lhs_expr
->ts
.kind
);
2151 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
2152 temporary and a loop. */
2153 if (!lhs_is_coindexed
&& rhs_is_coindexed
2154 && (!lhs_caf_attr
.codimension
2155 || !(lhs_expr
->rank
> 0
2156 && (lhs_caf_attr
.allocatable
|| lhs_caf_attr
.pointer
))))
2158 bool lhs_may_realloc
= lhs_expr
->rank
> 0 && lhs_caf_attr
.allocatable
;
2159 gfc_init_se (&rhs_se
, NULL
);
2160 if (lhs_expr
->rank
== 0 && lhs_caf_attr
.allocatable
)
2163 gfc_init_se (&scal_se
, NULL
);
2164 scal_se
.want_pointer
= 1;
2165 gfc_conv_expr (&scal_se
, lhs_expr
);
2166 /* Ensure scalar on lhs is allocated. */
2167 gfc_add_block_to_block (&block
, &scal_se
.pre
);
2169 gfc_allocate_using_malloc (&scal_se
.pre
, scal_se
.expr
,
2171 gfc_typenode_for_spec (&lhs_expr
->ts
)),
2173 tmp
= fold_build2 (EQ_EXPR
, logical_type_node
, scal_se
.expr
,
2175 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
2176 tmp
, gfc_finish_block (&scal_se
.pre
),
2177 build_empty_stmt (input_location
));
2178 gfc_add_expr_to_block (&block
, tmp
);
2181 lhs_may_realloc
= lhs_may_realloc
2182 && gfc_full_array_ref_p (lhs_expr
->ref
, NULL
);
2183 gfc_add_block_to_block (&block
, &lhs_se
.pre
);
2184 gfc_conv_intrinsic_caf_get (&rhs_se
, code
->ext
.actual
->next
->expr
,
2185 lhs_se
.expr
, lhs_may_realloc
, &rhs_caf_attr
);
2186 gfc_add_block_to_block (&block
, &rhs_se
.pre
);
2187 gfc_add_block_to_block (&block
, &rhs_se
.post
);
2188 gfc_add_block_to_block (&block
, &lhs_se
.post
);
2189 return gfc_finish_block (&block
);
2192 gfc_add_block_to_block (&block
, &lhs_se
.pre
);
2194 /* Obtain token, offset and image index for the LHS. */
2195 caf_decl
= gfc_get_tree_for_caf_expr (lhs_expr
);
2196 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
2197 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
2198 image_index
= gfc_caf_get_image_index (&block
, lhs_expr
, caf_decl
);
2200 if (lhs_caf_attr
.alloc_comp
)
2201 gfc_get_caf_token_offset (&lhs_se
, &token
, NULL
, caf_decl
, NULL_TREE
,
2204 gfc_get_caf_token_offset (&lhs_se
, &token
, &offset
, caf_decl
, tmp
,
2209 gfc_init_se (&rhs_se
, NULL
);
2210 if (rhs_expr
->expr_type
== EXPR_FUNCTION
&& rhs_expr
->value
.function
.isym
2211 && rhs_expr
->value
.function
.isym
->id
== GFC_ISYM_CONVERSION
)
2212 rhs_expr
= rhs_expr
->value
.function
.actual
->expr
;
2213 if (rhs_expr
->rank
== 0)
2215 symbol_attribute attr
;
2216 gfc_clear_attr (&attr
);
2217 gfc_conv_expr (&rhs_se
, rhs_expr
);
2218 rhs_se
.expr
= gfc_conv_scalar_to_descriptor (&rhs_se
, rhs_se
.expr
, attr
);
2219 rhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, rhs_se
.expr
);
2221 else if ((rhs_caf_attr
.alloc_comp
|| rhs_caf_attr
.pointer_comp
)
2222 && rhs_caf_attr
.codimension
)
2225 rhs_se
.want_pointer
= 1;
2226 gfc_conv_expr_descriptor (&rhs_se
, rhs_expr
);
2227 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2228 has the wrong type if component references are done. */
2229 tmp2
= gfc_typenode_for_spec (&rhs_expr
->ts
);
2230 tmp
= build_fold_indirect_ref_loc (input_location
, rhs_se
.expr
);
2231 gfc_add_modify (&rhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
2232 gfc_get_dtype_rank_type (
2233 gfc_has_vector_subscript (rhs_expr
)
2234 ? gfc_find_array_ref (rhs_expr
)->dimen
2240 /* If has_vector, pass descriptor for whole array and the
2241 vector bounds separately. */
2242 gfc_array_ref
*ar
, ar2
;
2243 bool has_vector
= false;
2246 if (rhs_is_coindexed
&& gfc_has_vector_subscript (rhs_expr
))
2249 ar
= gfc_find_array_ref (rhs_expr
);
2251 memset (ar
, '\0', sizeof (*ar
));
2255 rhs_se
.want_pointer
= 1;
2256 gfc_conv_expr_descriptor (&rhs_se
, rhs_expr
);
2257 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2258 has the wrong type if component references are done. */
2259 tmp
= build_fold_indirect_ref_loc (input_location
, rhs_se
.expr
);
2260 tmp2
= gfc_typenode_for_spec (&rhs_expr
->ts
);
2261 gfc_add_modify (&rhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
2262 gfc_get_dtype_rank_type (has_vector
? ar2
.dimen
2267 rhs_vec
= conv_caf_vector_subscript (&block
, rhs_se
.expr
, &ar2
);
2272 gfc_add_block_to_block (&block
, &rhs_se
.pre
);
2274 rhs_kind
= build_int_cst (integer_type_node
, rhs_expr
->ts
.kind
);
2276 tmp_stat
= gfc_find_stat_co (lhs_expr
);
2281 gfc_init_se (&stat_se
, NULL
);
2282 gfc_conv_expr_reference (&stat_se
, tmp_stat
);
2283 dst_stat
= stat_se
.expr
;
2284 gfc_add_block_to_block (&block
, &stat_se
.pre
);
2285 gfc_add_block_to_block (&block
, &stat_se
.post
);
2288 tmp_team
= gfc_find_team_co (lhs_expr
);
2293 gfc_init_se (&team_se
, NULL
);
2294 gfc_conv_expr_reference (&team_se
, tmp_team
);
2295 dst_team
= team_se
.expr
;
2296 gfc_add_block_to_block (&block
, &team_se
.pre
);
2297 gfc_add_block_to_block (&block
, &team_se
.post
);
2300 if (!rhs_is_coindexed
)
2302 if (lhs_caf_attr
.alloc_comp
|| lhs_caf_attr
.pointer_comp
2303 || has_ref_after_cafref (lhs_expr
))
2305 tree reference
, dst_realloc
;
2306 reference
= conv_expr_ref_to_caf_ref (&block
, lhs_expr
);
2308 = lhs_caf_attr
.allocatable
? boolean_true_node
: boolean_false_node
;
2309 tmp
= build_call_expr_loc (input_location
,
2310 gfor_fndecl_caf_send_by_ref
,
2311 10, token
, image_index
, rhs_se
.expr
,
2312 reference
, lhs_kind
, rhs_kind
,
2313 may_require_tmp
, dst_realloc
, src_stat
,
2314 build_int_cst (integer_type_node
,
2315 lhs_expr
->ts
.type
));
2318 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_send
, 11,
2319 token
, offset
, image_index
, lhs_se
.expr
, vec
,
2320 rhs_se
.expr
, lhs_kind
, rhs_kind
,
2321 may_require_tmp
, src_stat
, dst_team
);
2325 tree rhs_token
, rhs_offset
, rhs_image_index
;
2327 /* It guarantees memory consistency within the same segment. */
2328 tmp
= gfc_build_string_const (strlen ("memory") + 1, "memory");
2329 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
2330 gfc_build_string_const (1, ""), NULL_TREE
, NULL_TREE
,
2331 tree_cons (NULL_TREE
, tmp
, NULL_TREE
), NULL_TREE
);
2332 ASM_VOLATILE_P (tmp
) = 1;
2333 gfc_add_expr_to_block (&block
, tmp
);
2335 caf_decl
= gfc_get_tree_for_caf_expr (rhs_expr
);
2336 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
2337 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
2338 rhs_image_index
= gfc_caf_get_image_index (&block
, rhs_expr
, caf_decl
);
2340 if (rhs_caf_attr
.alloc_comp
|| rhs_caf_attr
.pointer_comp
2341 || has_ref_after_cafref (lhs_expr
))
2343 tmp_stat
= gfc_find_stat_co (lhs_expr
);
2348 gfc_init_se (&stat_se
, NULL
);
2349 gfc_conv_expr_reference (&stat_se
, tmp_stat
);
2350 src_stat
= stat_se
.expr
;
2351 gfc_add_block_to_block (&block
, &stat_se
.pre
);
2352 gfc_add_block_to_block (&block
, &stat_se
.post
);
2355 gfc_get_caf_token_offset (&rhs_se
, &rhs_token
, NULL
, caf_decl
,
2357 tree lhs_reference
, rhs_reference
;
2358 lhs_reference
= conv_expr_ref_to_caf_ref (&block
, lhs_expr
);
2359 rhs_reference
= conv_expr_ref_to_caf_ref (&block
, rhs_expr
);
2360 tmp
= build_call_expr_loc (input_location
,
2361 gfor_fndecl_caf_sendget_by_ref
, 13,
2362 token
, image_index
, lhs_reference
,
2363 rhs_token
, rhs_image_index
, rhs_reference
,
2364 lhs_kind
, rhs_kind
, may_require_tmp
,
2366 build_int_cst (integer_type_node
,
2368 build_int_cst (integer_type_node
,
2369 rhs_expr
->ts
.type
));
2373 gfc_get_caf_token_offset (&rhs_se
, &rhs_token
, &rhs_offset
, caf_decl
,
2375 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_sendget
,
2376 14, token
, offset
, image_index
,
2377 lhs_se
.expr
, vec
, rhs_token
, rhs_offset
,
2378 rhs_image_index
, tmp
, rhs_vec
, lhs_kind
,
2379 rhs_kind
, may_require_tmp
, src_stat
);
2382 gfc_add_expr_to_block (&block
, tmp
);
2383 gfc_add_block_to_block (&block
, &lhs_se
.post
);
2384 gfc_add_block_to_block (&block
, &rhs_se
.post
);
2386 /* It guarantees memory consistency within the same segment. */
2387 tmp
= gfc_build_string_const (strlen ("memory") + 1, "memory");
2388 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
2389 gfc_build_string_const (1, ""), NULL_TREE
, NULL_TREE
,
2390 tree_cons (NULL_TREE
, tmp
, NULL_TREE
), NULL_TREE
);
2391 ASM_VOLATILE_P (tmp
) = 1;
2392 gfc_add_expr_to_block (&block
, tmp
);
2394 return gfc_finish_block (&block
);
2399 trans_this_image (gfc_se
* se
, gfc_expr
*expr
)
2402 tree type
, desc
, dim_arg
, cond
, tmp
, m
, loop_var
, exit_label
, min_var
,
2403 lbound
, ubound
, extent
, ml
;
2406 gfc_expr
*distance
= expr
->value
.function
.actual
->next
->next
->expr
;
2408 if (expr
->value
.function
.actual
->expr
2409 && !gfc_is_coarray (expr
->value
.function
.actual
->expr
))
2410 distance
= expr
->value
.function
.actual
->expr
;
2412 /* The case -fcoarray=single is handled elsewhere. */
2413 gcc_assert (flag_coarray
!= GFC_FCOARRAY_SINGLE
);
2415 /* Argument-free version: THIS_IMAGE(). */
2416 if (distance
|| expr
->value
.function
.actual
->expr
== NULL
)
2420 gfc_init_se (&argse
, NULL
);
2421 gfc_conv_expr_val (&argse
, distance
);
2422 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2423 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2424 tmp
= fold_convert (integer_type_node
, argse
.expr
);
2427 tmp
= integer_zero_node
;
2428 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_this_image
, 1,
2430 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
),
2435 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2437 type
= gfc_get_int_type (gfc_default_integer_kind
);
2438 corank
= expr
->value
.function
.actual
->expr
->corank
;
2439 rank
= expr
->value
.function
.actual
->expr
->rank
;
2441 /* Obtain the descriptor of the COARRAY. */
2442 gfc_init_se (&argse
, NULL
);
2443 argse
.want_coarray
= 1;
2444 gfc_conv_expr_descriptor (&argse
, expr
->value
.function
.actual
->expr
);
2445 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2446 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2451 /* Create an implicit second parameter from the loop variable. */
2452 gcc_assert (!expr
->value
.function
.actual
->next
->expr
);
2453 gcc_assert (corank
> 0);
2454 gcc_assert (se
->loop
->dimen
== 1);
2455 gcc_assert (se
->ss
->info
->expr
== expr
);
2457 dim_arg
= se
->loop
->loopvar
[0];
2458 dim_arg
= fold_build2_loc (input_location
, PLUS_EXPR
,
2459 gfc_array_index_type
, dim_arg
,
2460 build_int_cst (TREE_TYPE (dim_arg
), 1));
2461 gfc_advance_se_ss_chain (se
);
2465 /* Use the passed DIM= argument. */
2466 gcc_assert (expr
->value
.function
.actual
->next
->expr
);
2467 gfc_init_se (&argse
, NULL
);
2468 gfc_conv_expr_type (&argse
, expr
->value
.function
.actual
->next
->expr
,
2469 gfc_array_index_type
);
2470 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2471 dim_arg
= argse
.expr
;
2473 if (INTEGER_CST_P (dim_arg
))
2475 if (wi::ltu_p (wi::to_wide (dim_arg
), 1)
2476 || wi::gtu_p (wi::to_wide (dim_arg
),
2477 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))))
2478 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2479 "dimension index", expr
->value
.function
.isym
->name
,
2482 else if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
2484 dim_arg
= gfc_evaluate_now (dim_arg
, &se
->pre
);
2485 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
2487 build_int_cst (TREE_TYPE (dim_arg
), 1));
2488 tmp
= gfc_rank_cst
[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))];
2489 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
2491 cond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
2492 logical_type_node
, cond
, tmp
);
2493 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
2498 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2499 one always has a dim_arg argument.
2501 m = this_image() - 1
2504 sub(1) = m + lcobound(corank)
2508 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2511 extent = gfc_extent(i)
2519 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2520 : m + lcobound(corank)
2523 /* this_image () - 1. */
2524 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_this_image
, 1,
2526 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, type
,
2527 fold_convert (type
, tmp
), build_int_cst (type
, 1));
2530 /* sub(1) = m + lcobound(corank). */
2531 lbound
= gfc_conv_descriptor_lbound_get (desc
,
2532 build_int_cst (TREE_TYPE (gfc_array_index_type
),
2534 lbound
= fold_convert (type
, lbound
);
2535 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, tmp
, lbound
);
2541 m
= gfc_create_var (type
, NULL
);
2542 ml
= gfc_create_var (type
, NULL
);
2543 loop_var
= gfc_create_var (integer_type_node
, NULL
);
2544 min_var
= gfc_create_var (integer_type_node
, NULL
);
2546 /* m = this_image () - 1. */
2547 gfc_add_modify (&se
->pre
, m
, tmp
);
2549 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2550 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, integer_type_node
,
2551 fold_convert (integer_type_node
, dim_arg
),
2552 build_int_cst (integer_type_node
, rank
- 1));
2553 tmp
= fold_build2_loc (input_location
, MIN_EXPR
, integer_type_node
,
2554 build_int_cst (integer_type_node
, rank
+ corank
- 2),
2556 gfc_add_modify (&se
->pre
, min_var
, tmp
);
2559 tmp
= build_int_cst (integer_type_node
, rank
);
2560 gfc_add_modify (&se
->pre
, loop_var
, tmp
);
2562 exit_label
= gfc_build_label_decl (NULL_TREE
);
2563 TREE_USED (exit_label
) = 1;
2566 gfc_init_block (&loop
);
2569 gfc_add_modify (&loop
, ml
, m
);
2572 lbound
= gfc_conv_descriptor_lbound_get (desc
, loop_var
);
2573 ubound
= gfc_conv_descriptor_ubound_get (desc
, loop_var
);
2574 extent
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
2575 extent
= fold_convert (type
, extent
);
2578 gfc_add_modify (&loop
, m
,
2579 fold_build2_loc (input_location
, TRUNC_DIV_EXPR
, type
,
2582 /* Exit condition: if (i >= min_var) goto exit_label. */
2583 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, loop_var
,
2585 tmp
= build1_v (GOTO_EXPR
, exit_label
);
2586 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
, tmp
,
2587 build_empty_stmt (input_location
));
2588 gfc_add_expr_to_block (&loop
, tmp
);
2590 /* Increment loop variable: i++. */
2591 gfc_add_modify (&loop
, loop_var
,
2592 fold_build2_loc (input_location
, PLUS_EXPR
, integer_type_node
,
2596 /* Making the loop... actually loop! */
2597 tmp
= gfc_finish_block (&loop
);
2598 tmp
= build1_v (LOOP_EXPR
, tmp
);
2599 gfc_add_expr_to_block (&se
->pre
, tmp
);
2601 /* The exit label. */
2602 tmp
= build1_v (LABEL_EXPR
, exit_label
);
2603 gfc_add_expr_to_block (&se
->pre
, tmp
);
2605 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2606 : m + lcobound(corank) */
2608 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
, dim_arg
,
2609 build_int_cst (TREE_TYPE (dim_arg
), corank
));
2611 lbound
= gfc_conv_descriptor_lbound_get (desc
,
2612 fold_build2_loc (input_location
, PLUS_EXPR
,
2613 gfc_array_index_type
, dim_arg
,
2614 build_int_cst (TREE_TYPE (dim_arg
), rank
-1)));
2615 lbound
= fold_convert (type
, lbound
);
2617 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, type
, ml
,
2618 fold_build2_loc (input_location
, MULT_EXPR
, type
,
2620 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, tmp
, lbound
);
2622 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
, tmp
,
2623 fold_build2_loc (input_location
, PLUS_EXPR
, type
,
2628 /* Convert a call to image_status. */
2631 conv_intrinsic_image_status (gfc_se
*se
, gfc_expr
*expr
)
2633 unsigned int num_args
;
2636 num_args
= gfc_intrinsic_argument_list_length (expr
);
2637 args
= XALLOCAVEC (tree
, num_args
);
2638 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
2639 /* In args[0] the number of the image the status is desired for has to be
2642 if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
2645 arg
= gfc_evaluate_now (args
[0], &se
->pre
);
2646 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
2647 fold_convert (integer_type_node
, arg
),
2649 tmp
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
2650 tmp
, integer_zero_node
,
2651 build_int_cst (integer_type_node
,
2652 GFC_STAT_STOPPED_IMAGE
));
2654 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
2655 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_image_status
, 2,
2656 args
[0], build_int_cst (integer_type_node
, -1));
2660 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
), tmp
);
2664 conv_intrinsic_team_number (gfc_se
*se
, gfc_expr
*expr
)
2666 unsigned int num_args
;
2670 num_args
= gfc_intrinsic_argument_list_length (expr
);
2671 args
= XALLOCAVEC (tree
, num_args
);
2672 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
2675 GFC_FCOARRAY_SINGLE
&& expr
->value
.function
.actual
->expr
)
2679 arg
= gfc_evaluate_now (args
[0], &se
->pre
);
2680 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
2681 fold_convert (integer_type_node
, arg
),
2683 tmp
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
2684 tmp
, integer_zero_node
,
2685 build_int_cst (integer_type_node
,
2686 GFC_STAT_STOPPED_IMAGE
));
2688 else if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
2690 // the value -1 represents that no team has been created yet
2691 tmp
= build_int_cst (integer_type_node
, -1);
2693 else if (flag_coarray
== GFC_FCOARRAY_LIB
&& expr
->value
.function
.actual
->expr
)
2694 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_team_number
, 1,
2695 args
[0], build_int_cst (integer_type_node
, -1));
2696 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
2697 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_team_number
, 1,
2698 integer_zero_node
, build_int_cst (integer_type_node
, -1));
2702 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
), tmp
);
2707 trans_image_index (gfc_se
* se
, gfc_expr
*expr
)
2709 tree num_images
, cond
, coindex
, type
, lbound
, ubound
, desc
, subdesc
,
2711 gfc_se argse
, subse
;
2712 int rank
, corank
, codim
;
2714 type
= gfc_get_int_type (gfc_default_integer_kind
);
2715 corank
= expr
->value
.function
.actual
->expr
->corank
;
2716 rank
= expr
->value
.function
.actual
->expr
->rank
;
2718 /* Obtain the descriptor of the COARRAY. */
2719 gfc_init_se (&argse
, NULL
);
2720 argse
.want_coarray
= 1;
2721 gfc_conv_expr_descriptor (&argse
, expr
->value
.function
.actual
->expr
);
2722 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2723 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2726 /* Obtain a handle to the SUB argument. */
2727 gfc_init_se (&subse
, NULL
);
2728 gfc_conv_expr_descriptor (&subse
, expr
->value
.function
.actual
->next
->expr
);
2729 gfc_add_block_to_block (&se
->pre
, &subse
.pre
);
2730 gfc_add_block_to_block (&se
->post
, &subse
.post
);
2731 subdesc
= build_fold_indirect_ref_loc (input_location
,
2732 gfc_conv_descriptor_data_get (subse
.expr
));
2734 /* Fortran 2008 does not require that the values remain in the cobounds,
2735 thus we need explicitly check this - and return 0 if they are exceeded. */
2737 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[rank
+corank
-1]);
2738 tmp
= gfc_build_array_ref (subdesc
, gfc_rank_cst
[corank
-1], NULL
);
2739 invalid_bound
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
2740 fold_convert (gfc_array_index_type
, tmp
),
2743 for (codim
= corank
+ rank
- 2; codim
>= rank
; codim
--)
2745 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[codim
]);
2746 ubound
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[codim
]);
2747 tmp
= gfc_build_array_ref (subdesc
, gfc_rank_cst
[codim
-rank
], NULL
);
2748 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
2749 fold_convert (gfc_array_index_type
, tmp
),
2751 invalid_bound
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
2752 logical_type_node
, invalid_bound
, cond
);
2753 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
2754 fold_convert (gfc_array_index_type
, tmp
),
2756 invalid_bound
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
2757 logical_type_node
, invalid_bound
, cond
);
2760 invalid_bound
= gfc_unlikely (invalid_bound
, PRED_FORTRAN_INVALID_BOUND
);
2762 /* See Fortran 2008, C.10 for the following algorithm. */
2764 /* coindex = sub(corank) - lcobound(n). */
2765 coindex
= fold_convert (gfc_array_index_type
,
2766 gfc_build_array_ref (subdesc
, gfc_rank_cst
[corank
-1],
2768 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[rank
+corank
-1]);
2769 coindex
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
2770 fold_convert (gfc_array_index_type
, coindex
),
2773 for (codim
= corank
+ rank
- 2; codim
>= rank
; codim
--)
2775 tree extent
, ubound
;
2777 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2778 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[codim
]);
2779 ubound
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[codim
]);
2780 extent
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
2782 /* coindex *= extent. */
2783 coindex
= fold_build2_loc (input_location
, MULT_EXPR
,
2784 gfc_array_index_type
, coindex
, extent
);
2786 /* coindex += sub(codim). */
2787 tmp
= gfc_build_array_ref (subdesc
, gfc_rank_cst
[codim
-rank
], NULL
);
2788 coindex
= fold_build2_loc (input_location
, PLUS_EXPR
,
2789 gfc_array_index_type
, coindex
,
2790 fold_convert (gfc_array_index_type
, tmp
));
2792 /* coindex -= lbound(codim). */
2793 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[codim
]);
2794 coindex
= fold_build2_loc (input_location
, MINUS_EXPR
,
2795 gfc_array_index_type
, coindex
, lbound
);
2798 coindex
= fold_build2_loc (input_location
, PLUS_EXPR
, type
,
2799 fold_convert(type
, coindex
),
2800 build_int_cst (type
, 1));
2802 /* Return 0 if "coindex" exceeds num_images(). */
2804 if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
2805 num_images
= build_int_cst (type
, 1);
2808 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
, 2,
2810 build_int_cst (integer_type_node
, -1));
2811 num_images
= fold_convert (type
, tmp
);
2814 tmp
= gfc_create_var (type
, NULL
);
2815 gfc_add_modify (&se
->pre
, tmp
, coindex
);
2817 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
, tmp
,
2819 cond
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
, logical_type_node
,
2821 fold_convert (logical_type_node
, invalid_bound
));
2822 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
2823 build_int_cst (type
, 0), tmp
);
2827 trans_num_images (gfc_se
* se
, gfc_expr
*expr
)
2829 tree tmp
, distance
, failed
;
2832 if (expr
->value
.function
.actual
->expr
)
2834 gfc_init_se (&argse
, NULL
);
2835 gfc_conv_expr_val (&argse
, expr
->value
.function
.actual
->expr
);
2836 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2837 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2838 distance
= fold_convert (integer_type_node
, argse
.expr
);
2841 distance
= integer_zero_node
;
2843 if (expr
->value
.function
.actual
->next
->expr
)
2845 gfc_init_se (&argse
, NULL
);
2846 gfc_conv_expr_val (&argse
, expr
->value
.function
.actual
->next
->expr
);
2847 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2848 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2849 failed
= fold_convert (integer_type_node
, argse
.expr
);
2852 failed
= build_int_cst (integer_type_node
, -1);
2853 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
, 2,
2855 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
), tmp
);
2860 gfc_conv_intrinsic_rank (gfc_se
*se
, gfc_expr
*expr
)
2864 gfc_init_se (&argse
, NULL
);
2865 argse
.data_not_needed
= 1;
2866 argse
.descriptor_only
= 1;
2868 gfc_conv_expr_descriptor (&argse
, expr
->value
.function
.actual
->expr
);
2869 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2870 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2872 se
->expr
= gfc_conv_descriptor_rank (argse
.expr
);
2873 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
),
2879 gfc_conv_intrinsic_is_contiguous (gfc_se
* se
, gfc_expr
* expr
)
2882 arg
= expr
->value
.function
.actual
->expr
;
2883 gfc_conv_is_contiguous_expr (se
, arg
);
2884 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
2887 /* This function does the work for gfc_conv_intrinsic_is_contiguous,
2888 plus it can be called directly. */
2891 gfc_conv_is_contiguous_expr (gfc_se
*se
, gfc_expr
*arg
)
2895 tree desc
, tmp
, stride
, extent
, cond
;
2900 if (arg
->ts
.type
== BT_CLASS
)
2901 gfc_add_class_array_ref (arg
);
2903 ss
= gfc_walk_expr (arg
);
2904 gcc_assert (ss
!= gfc_ss_terminator
);
2905 gfc_init_se (&argse
, NULL
);
2906 argse
.data_not_needed
= 1;
2907 gfc_conv_expr_descriptor (&argse
, arg
);
2909 as
= gfc_get_full_arrayspec_from_expr (arg
);
2911 /* Create: stride[0] == 1 && stride[1] == extend[0]*stride[0] && ...
2912 Note in addition that zero-sized arrays don't count as contiguous. */
2914 if (as
&& as
->type
== AS_ASSUMED_RANK
)
2916 /* Build the call to is_contiguous0. */
2917 argse
.want_pointer
= 1;
2918 gfc_conv_expr_descriptor (&argse
, arg
);
2919 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2920 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2921 desc
= gfc_evaluate_now (argse
.expr
, &se
->pre
);
2922 fncall0
= build_call_expr_loc (input_location
,
2923 gfor_fndecl_is_contiguous0
, 1, desc
);
2925 se
->expr
= convert (logical_type_node
, se
->expr
);
2929 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2930 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2931 desc
= gfc_evaluate_now (argse
.expr
, &se
->pre
);
2933 stride
= gfc_conv_descriptor_stride_get (desc
, gfc_rank_cst
[0]);
2934 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
2935 stride
, build_int_cst (TREE_TYPE (stride
), 1));
2937 for (i
= 0; i
< arg
->rank
- 1; i
++)
2939 tmp
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[i
]);
2940 extent
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[i
]);
2941 extent
= fold_build2_loc (input_location
, MINUS_EXPR
,
2942 gfc_array_index_type
, extent
, tmp
);
2943 extent
= fold_build2_loc (input_location
, PLUS_EXPR
,
2944 gfc_array_index_type
, extent
,
2945 gfc_index_one_node
);
2946 tmp
= gfc_conv_descriptor_stride_get (desc
, gfc_rank_cst
[i
]);
2947 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, TREE_TYPE (tmp
),
2949 stride
= gfc_conv_descriptor_stride_get (desc
, gfc_rank_cst
[i
+1]);
2950 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
2952 cond
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
2953 boolean_type_node
, cond
, tmp
);
2960 /* Evaluate a single upper or lower bound. */
2961 /* TODO: bound intrinsic generates way too much unnecessary code. */
2964 gfc_conv_intrinsic_bound (gfc_se
* se
, gfc_expr
* expr
, enum gfc_isym_id op
)
2966 gfc_actual_arglist
*arg
;
2967 gfc_actual_arglist
*arg2
;
2977 gfc_array_spec
* as
;
2978 bool assumed_rank_lb_one
;
2980 arg
= expr
->value
.function
.actual
;
2985 /* Create an implicit second parameter from the loop variable. */
2986 gcc_assert (!arg2
->expr
|| op
== GFC_ISYM_SHAPE
);
2987 gcc_assert (se
->loop
->dimen
== 1);
2988 gcc_assert (se
->ss
->info
->expr
== expr
);
2989 gfc_advance_se_ss_chain (se
);
2990 bound
= se
->loop
->loopvar
[0];
2991 bound
= fold_build2_loc (input_location
, MINUS_EXPR
,
2992 gfc_array_index_type
, bound
,
2997 /* use the passed argument. */
2998 gcc_assert (arg2
->expr
);
2999 gfc_init_se (&argse
, NULL
);
3000 gfc_conv_expr_type (&argse
, arg2
->expr
, gfc_array_index_type
);
3001 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3003 /* Convert from one based to zero based. */
3004 bound
= fold_build2_loc (input_location
, MINUS_EXPR
,
3005 gfc_array_index_type
, bound
,
3006 gfc_index_one_node
);
3009 /* TODO: don't re-evaluate the descriptor on each iteration. */
3010 /* Get a descriptor for the first parameter. */
3011 gfc_init_se (&argse
, NULL
);
3012 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
3013 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3014 gfc_add_block_to_block (&se
->post
, &argse
.post
);
3018 as
= gfc_get_full_arrayspec_from_expr (arg
->expr
);
3020 if (INTEGER_CST_P (bound
))
3022 gcc_assert (op
!= GFC_ISYM_SHAPE
);
3023 if (((!as
|| as
->type
!= AS_ASSUMED_RANK
)
3024 && wi::geu_p (wi::to_wide (bound
),
3025 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc
))))
3026 || wi::gtu_p (wi::to_wide (bound
), GFC_MAX_DIMENSIONS
))
3027 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3029 (op
== GFC_ISYM_UBOUND
) ? "UBOUND" : "LBOUND",
3033 if (!INTEGER_CST_P (bound
) || (as
&& as
->type
== AS_ASSUMED_RANK
))
3035 if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
3037 bound
= gfc_evaluate_now (bound
, &se
->pre
);
3038 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3039 bound
, build_int_cst (TREE_TYPE (bound
), 0));
3040 if (as
&& as
->type
== AS_ASSUMED_RANK
)
3041 tmp
= gfc_conv_descriptor_rank (desc
);
3043 tmp
= gfc_rank_cst
[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc
))];
3044 tmp
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
3045 bound
, fold_convert(TREE_TYPE (bound
), tmp
));
3046 cond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
3047 logical_type_node
, cond
, tmp
);
3048 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
3053 /* Take care of the lbound shift for assumed-rank arrays that are
3054 nonallocatable and nonpointers. Those have a lbound of 1. */
3055 assumed_rank_lb_one
= as
&& as
->type
== AS_ASSUMED_RANK
3056 && ((arg
->expr
->ts
.type
!= BT_CLASS
3057 && !arg
->expr
->symtree
->n
.sym
->attr
.allocatable
3058 && !arg
->expr
->symtree
->n
.sym
->attr
.pointer
)
3059 || (arg
->expr
->ts
.type
== BT_CLASS
3060 && !CLASS_DATA (arg
->expr
)->attr
.allocatable
3061 && !CLASS_DATA (arg
->expr
)->attr
.class_pointer
));
3063 ubound
= gfc_conv_descriptor_ubound_get (desc
, bound
);
3064 lbound
= gfc_conv_descriptor_lbound_get (desc
, bound
);
3065 size
= fold_build2_loc (input_location
, MINUS_EXPR
,
3066 gfc_array_index_type
, ubound
, lbound
);
3067 size
= fold_build2_loc (input_location
, PLUS_EXPR
,
3068 gfc_array_index_type
, size
, gfc_index_one_node
);
3070 /* 13.14.53: Result value for LBOUND
3072 Case (i): For an array section or for an array expression other than a
3073 whole array or array structure component, LBOUND(ARRAY, DIM)
3074 has the value 1. For a whole array or array structure
3075 component, LBOUND(ARRAY, DIM) has the value:
3076 (a) equal to the lower bound for subscript DIM of ARRAY if
3077 dimension DIM of ARRAY does not have extent zero
3078 or if ARRAY is an assumed-size array of rank DIM,
3081 13.14.113: Result value for UBOUND
3083 Case (i): For an array section or for an array expression other than a
3084 whole array or array structure component, UBOUND(ARRAY, DIM)
3085 has the value equal to the number of elements in the given
3086 dimension; otherwise, it has a value equal to the upper bound
3087 for subscript DIM of ARRAY if dimension DIM of ARRAY does
3088 not have size zero and has value zero if dimension DIM has
3091 if (op
== GFC_ISYM_LBOUND
&& assumed_rank_lb_one
)
3092 se
->expr
= gfc_index_one_node
;
3095 if (op
== GFC_ISYM_UBOUND
)
3097 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3098 size
, gfc_index_zero_node
);
3099 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
3100 gfc_array_index_type
, cond
,
3101 (assumed_rank_lb_one
? size
: ubound
),
3102 gfc_index_zero_node
);
3104 else if (op
== GFC_ISYM_LBOUND
)
3106 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3107 size
, gfc_index_zero_node
);
3108 if (as
->type
== AS_ASSUMED_SIZE
)
3110 cond1
= fold_build2_loc (input_location
, EQ_EXPR
,
3111 logical_type_node
, bound
,
3112 build_int_cst (TREE_TYPE (bound
),
3113 arg
->expr
->rank
- 1));
3114 cond
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
3115 logical_type_node
, cond
, cond1
);
3117 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
3118 gfc_array_index_type
, cond
,
3119 lbound
, gfc_index_one_node
);
3121 else if (op
== GFC_ISYM_SHAPE
)
3122 se
->expr
= fold_build2_loc (input_location
, MAX_EXPR
,
3123 gfc_array_index_type
, size
,
3124 gfc_index_zero_node
);
3128 /* According to F2018 16.9.172, para 5, an assumed rank object,
3129 argument associated with and assumed size array, has the ubound
3130 of the final dimension set to -1 and UBOUND must return this.
3131 Similarly for the SHAPE intrinsic. */
3132 if (op
!= GFC_ISYM_LBOUND
&& assumed_rank_lb_one
)
3134 tree minus_one
= build_int_cst (gfc_array_index_type
, -1);
3135 tree rank
= fold_convert (gfc_array_index_type
,
3136 gfc_conv_descriptor_rank (desc
));
3137 rank
= fold_build2_loc (input_location
, PLUS_EXPR
,
3138 gfc_array_index_type
, rank
, minus_one
);
3140 /* Fix the expression to stop it from becoming even more
3142 se
->expr
= gfc_evaluate_now (se
->expr
, &se
->pre
);
3144 /* Descriptors for assumed-size arrays have ubound = -1
3145 in the last dimension. */
3146 cond1
= fold_build2_loc (input_location
, EQ_EXPR
,
3147 logical_type_node
, ubound
, minus_one
);
3148 cond
= fold_build2_loc (input_location
, EQ_EXPR
,
3149 logical_type_node
, bound
, rank
);
3150 cond
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
3151 logical_type_node
, cond
, cond1
);
3152 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
3153 gfc_array_index_type
, cond
,
3154 minus_one
, se
->expr
);
3157 else /* as is null; this is an old-fashioned 1-based array. */
3159 if (op
!= GFC_ISYM_LBOUND
)
3161 se
->expr
= fold_build2_loc (input_location
, MAX_EXPR
,
3162 gfc_array_index_type
, size
,
3163 gfc_index_zero_node
);
3166 se
->expr
= gfc_index_one_node
;
3170 type
= gfc_typenode_for_spec (&expr
->ts
);
3171 se
->expr
= convert (type
, se
->expr
);
3176 conv_intrinsic_cobound (gfc_se
* se
, gfc_expr
* expr
)
3178 gfc_actual_arglist
*arg
;
3179 gfc_actual_arglist
*arg2
;
3181 tree bound
, resbound
, resbound2
, desc
, cond
, tmp
;
3185 gcc_assert (expr
->value
.function
.isym
->id
== GFC_ISYM_LCOBOUND
3186 || expr
->value
.function
.isym
->id
== GFC_ISYM_UCOBOUND
3187 || expr
->value
.function
.isym
->id
== GFC_ISYM_THIS_IMAGE
);
3189 arg
= expr
->value
.function
.actual
;
3192 gcc_assert (arg
->expr
->expr_type
== EXPR_VARIABLE
);
3193 corank
= arg
->expr
->corank
;
3195 gfc_init_se (&argse
, NULL
);
3196 argse
.want_coarray
= 1;
3198 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
3199 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3200 gfc_add_block_to_block (&se
->post
, &argse
.post
);
3205 /* Create an implicit second parameter from the loop variable. */
3206 gcc_assert (!arg2
->expr
);
3207 gcc_assert (corank
> 0);
3208 gcc_assert (se
->loop
->dimen
== 1);
3209 gcc_assert (se
->ss
->info
->expr
== expr
);
3211 bound
= se
->loop
->loopvar
[0];
3212 bound
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
3213 bound
, gfc_rank_cst
[arg
->expr
->rank
]);
3214 gfc_advance_se_ss_chain (se
);
3218 /* use the passed argument. */
3219 gcc_assert (arg2
->expr
);
3220 gfc_init_se (&argse
, NULL
);
3221 gfc_conv_expr_type (&argse
, arg2
->expr
, gfc_array_index_type
);
3222 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3225 if (INTEGER_CST_P (bound
))
3227 if (wi::ltu_p (wi::to_wide (bound
), 1)
3228 || wi::gtu_p (wi::to_wide (bound
),
3229 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))))
3230 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3231 "dimension index", expr
->value
.function
.isym
->name
,
3234 else if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
3236 bound
= gfc_evaluate_now (bound
, &se
->pre
);
3237 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3238 bound
, build_int_cst (TREE_TYPE (bound
), 1));
3239 tmp
= gfc_rank_cst
[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))];
3240 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3242 cond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
3243 logical_type_node
, cond
, tmp
);
3244 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
3249 /* Subtract 1 to get to zero based and add dimensions. */
3250 switch (arg
->expr
->rank
)
3253 bound
= fold_build2_loc (input_location
, MINUS_EXPR
,
3254 gfc_array_index_type
, bound
,
3255 gfc_index_one_node
);
3259 bound
= fold_build2_loc (input_location
, PLUS_EXPR
,
3260 gfc_array_index_type
, bound
,
3261 gfc_rank_cst
[arg
->expr
->rank
- 1]);
3265 resbound
= gfc_conv_descriptor_lbound_get (desc
, bound
);
3267 /* Handle UCOBOUND with special handling of the last codimension. */
3268 if (expr
->value
.function
.isym
->id
== GFC_ISYM_UCOBOUND
)
3270 /* Last codimension: For -fcoarray=single just return
3271 the lcobound - otherwise add
3272 ceiling (real (num_images ()) / real (size)) - 1
3273 = (num_images () + size - 1) / size - 1
3274 = (num_images - 1) / size(),
3275 where size is the product of the extent of all but the last
3278 if (flag_coarray
!= GFC_FCOARRAY_SINGLE
&& corank
> 1)
3282 cosize
= gfc_conv_descriptor_cosize (desc
, arg
->expr
->rank
, corank
);
3283 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
,
3284 2, integer_zero_node
,
3285 build_int_cst (integer_type_node
, -1));
3286 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
3287 gfc_array_index_type
,
3288 fold_convert (gfc_array_index_type
, tmp
),
3289 build_int_cst (gfc_array_index_type
, 1));
3290 tmp
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
3291 gfc_array_index_type
, tmp
,
3292 fold_convert (gfc_array_index_type
, cosize
));
3293 resbound
= fold_build2_loc (input_location
, PLUS_EXPR
,
3294 gfc_array_index_type
, resbound
, tmp
);
3296 else if (flag_coarray
!= GFC_FCOARRAY_SINGLE
)
3298 /* ubound = lbound + num_images() - 1. */
3299 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
,
3300 2, integer_zero_node
,
3301 build_int_cst (integer_type_node
, -1));
3302 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
3303 gfc_array_index_type
,
3304 fold_convert (gfc_array_index_type
, tmp
),
3305 build_int_cst (gfc_array_index_type
, 1));
3306 resbound
= fold_build2_loc (input_location
, PLUS_EXPR
,
3307 gfc_array_index_type
, resbound
, tmp
);
3312 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
3314 build_int_cst (TREE_TYPE (bound
),
3315 arg
->expr
->rank
+ corank
- 1));
3317 resbound2
= gfc_conv_descriptor_ubound_get (desc
, bound
);
3318 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
3319 gfc_array_index_type
, cond
,
3320 resbound
, resbound2
);
3323 se
->expr
= resbound
;
3326 se
->expr
= resbound
;
3328 type
= gfc_typenode_for_spec (&expr
->ts
);
3329 se
->expr
= convert (type
, se
->expr
);
3334 conv_intrinsic_stride (gfc_se
* se
, gfc_expr
* expr
)
3336 gfc_actual_arglist
*array_arg
;
3337 gfc_actual_arglist
*dim_arg
;
3341 array_arg
= expr
->value
.function
.actual
;
3342 dim_arg
= array_arg
->next
;
3344 gcc_assert (array_arg
->expr
->expr_type
== EXPR_VARIABLE
);
3346 gfc_init_se (&argse
, NULL
);
3347 gfc_conv_expr_descriptor (&argse
, array_arg
->expr
);
3348 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3349 gfc_add_block_to_block (&se
->post
, &argse
.post
);
3352 gcc_assert (dim_arg
->expr
);
3353 gfc_init_se (&argse
, NULL
);
3354 gfc_conv_expr_type (&argse
, dim_arg
->expr
, gfc_array_index_type
);
3355 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3356 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
3357 argse
.expr
, gfc_index_one_node
);
3358 se
->expr
= gfc_conv_descriptor_stride_get (desc
, tmp
);
3362 gfc_conv_intrinsic_abs (gfc_se
* se
, gfc_expr
* expr
)
3366 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
3368 switch (expr
->value
.function
.actual
->expr
->ts
.type
)
3372 se
->expr
= fold_build1_loc (input_location
, ABS_EXPR
, TREE_TYPE (arg
),
3377 cabs
= gfc_builtin_decl_for_float_kind (BUILT_IN_CABS
, expr
->ts
.kind
);
3378 se
->expr
= build_call_expr_loc (input_location
, cabs
, 1, arg
);
3387 /* Create a complex value from one or two real components. */
3390 gfc_conv_intrinsic_cmplx (gfc_se
* se
, gfc_expr
* expr
, int both
)
3396 unsigned int num_args
;
3398 num_args
= gfc_intrinsic_argument_list_length (expr
);
3399 args
= XALLOCAVEC (tree
, num_args
);
3401 type
= gfc_typenode_for_spec (&expr
->ts
);
3402 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
3403 real
= convert (TREE_TYPE (type
), args
[0]);
3405 imag
= convert (TREE_TYPE (type
), args
[1]);
3406 else if (TREE_CODE (TREE_TYPE (args
[0])) == COMPLEX_TYPE
)
3408 imag
= fold_build1_loc (input_location
, IMAGPART_EXPR
,
3409 TREE_TYPE (TREE_TYPE (args
[0])), args
[0]);
3410 imag
= convert (TREE_TYPE (type
), imag
);
3413 imag
= build_real_from_int_cst (TREE_TYPE (type
), integer_zero_node
);
3415 se
->expr
= fold_build2_loc (input_location
, COMPLEX_EXPR
, type
, real
, imag
);
3419 /* Remainder function MOD(A, P) = A - INT(A / P) * P
3420 MODULO(A, P) = A - FLOOR (A / P) * P
3422 The obvious algorithms above are numerically instable for large
3423 arguments, hence these intrinsics are instead implemented via calls
3424 to the fmod family of functions. It is the responsibility of the
3425 user to ensure that the second argument is non-zero. */
3428 gfc_conv_intrinsic_mod (gfc_se
* se
, gfc_expr
* expr
, int modulo
)
3438 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
3440 switch (expr
->ts
.type
)
3443 /* Integer case is easy, we've got a builtin op. */
3444 type
= TREE_TYPE (args
[0]);
3447 se
->expr
= fold_build2_loc (input_location
, FLOOR_MOD_EXPR
, type
,
3450 se
->expr
= fold_build2_loc (input_location
, TRUNC_MOD_EXPR
, type
,
3455 /* Even easier, we only need one. */
3456 type
= TREE_TYPE (args
[0]);
3457 se
->expr
= fold_build2_loc (input_location
, TRUNC_MOD_EXPR
, type
,
3463 /* Check if we have a builtin fmod. */
3464 fmod
= gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD
, expr
->ts
.kind
);
3466 /* The builtin should always be available. */
3467 gcc_assert (fmod
!= NULL_TREE
);
3469 tmp
= build_addr (fmod
);
3470 se
->expr
= build_call_array_loc (input_location
,
3471 TREE_TYPE (TREE_TYPE (fmod
)),
3476 type
= TREE_TYPE (args
[0]);
3478 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
3479 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
3482 modulo = arg - floor (arg/arg2) * arg2
3484 In order to calculate the result accurately, we use the fmod
3485 function as follows.
3487 res = fmod (arg, arg2);
3490 if ((arg < 0) xor (arg2 < 0))
3494 res = copysign (0., arg2);
3496 => As two nested ternary exprs:
3498 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3499 : copysign (0., arg2);
3503 zero
= gfc_build_const (type
, integer_zero_node
);
3504 tmp
= gfc_evaluate_now (se
->expr
, &se
->pre
);
3505 if (!flag_signed_zeros
)
3507 test
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3509 test2
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3511 test2
= fold_build2_loc (input_location
, TRUTH_XOR_EXPR
,
3512 logical_type_node
, test
, test2
);
3513 test
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
3515 test
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
3516 logical_type_node
, test
, test2
);
3517 test
= gfc_evaluate_now (test
, &se
->pre
);
3518 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, test
,
3519 fold_build2_loc (input_location
,
3521 type
, tmp
, args
[1]),
3526 tree expr1
, copysign
, cscall
;
3527 copysign
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
,
3529 test
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3531 test2
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3533 test2
= fold_build2_loc (input_location
, TRUTH_XOR_EXPR
,
3534 logical_type_node
, test
, test2
);
3535 expr1
= fold_build3_loc (input_location
, COND_EXPR
, type
, test2
,
3536 fold_build2_loc (input_location
,
3538 type
, tmp
, args
[1]),
3540 test
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
3542 cscall
= build_call_expr_loc (input_location
, copysign
, 2, zero
,
3544 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, test
,
3554 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3555 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3556 where the right shifts are logical (i.e. 0's are shifted in).
3557 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3558 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3560 DSHIFTL(I,J,BITSIZE) = J
3562 DSHIFTR(I,J,BITSIZE) = I. */
3565 gfc_conv_intrinsic_dshift (gfc_se
* se
, gfc_expr
* expr
, bool dshiftl
)
3567 tree type
, utype
, stype
, arg1
, arg2
, shift
, res
, left
, right
;
3568 tree args
[3], cond
, tmp
;
3571 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
3573 gcc_assert (TREE_TYPE (args
[0]) == TREE_TYPE (args
[1]));
3574 type
= TREE_TYPE (args
[0]);
3575 bitsize
= TYPE_PRECISION (type
);
3576 utype
= unsigned_type_for (type
);
3577 stype
= TREE_TYPE (args
[2]);
3579 arg1
= gfc_evaluate_now (args
[0], &se
->pre
);
3580 arg2
= gfc_evaluate_now (args
[1], &se
->pre
);
3581 shift
= gfc_evaluate_now (args
[2], &se
->pre
);
3583 /* The generic case. */
3584 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, stype
,
3585 build_int_cst (stype
, bitsize
), shift
);
3586 left
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
3587 arg1
, dshiftl
? shift
: tmp
);
3589 right
= fold_build2_loc (input_location
, RSHIFT_EXPR
, utype
,
3590 fold_convert (utype
, arg2
), dshiftl
? tmp
: shift
);
3591 right
= fold_convert (type
, right
);
3593 res
= fold_build2_loc (input_location
, BIT_IOR_EXPR
, type
, left
, right
);
3595 /* Special cases. */
3596 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, shift
,
3597 build_int_cst (stype
, 0));
3598 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
3599 dshiftl
? arg1
: arg2
, res
);
3601 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, shift
,
3602 build_int_cst (stype
, bitsize
));
3603 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
3604 dshiftl
? arg2
: arg1
, res
);
3610 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3613 gfc_conv_intrinsic_dim (gfc_se
* se
, gfc_expr
* expr
)
3621 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
3622 type
= TREE_TYPE (args
[0]);
3624 val
= fold_build2_loc (input_location
, MINUS_EXPR
, type
, args
[0], args
[1]);
3625 val
= gfc_evaluate_now (val
, &se
->pre
);
3627 zero
= gfc_build_const (type
, integer_zero_node
);
3628 tmp
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
, val
, zero
);
3629 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, zero
, val
);
3633 /* SIGN(A, B) is absolute value of A times sign of B.
3634 The real value versions use library functions to ensure the correct
3635 handling of negative zero. Integer case implemented as:
3636 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3640 gfc_conv_intrinsic_sign (gfc_se
* se
, gfc_expr
* expr
)
3646 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
3647 if (expr
->ts
.type
== BT_REAL
)
3651 tmp
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
, expr
->ts
.kind
);
3652 abs
= gfc_builtin_decl_for_float_kind (BUILT_IN_FABS
, expr
->ts
.kind
);
3654 /* We explicitly have to ignore the minus sign. We do so by using
3655 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3657 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args
[1]))))
3660 zero
= build_real_from_int_cst (TREE_TYPE (args
[1]), integer_zero_node
);
3661 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
3663 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
3664 TREE_TYPE (args
[0]), cond
,
3665 build_call_expr_loc (input_location
, abs
, 1,
3667 build_call_expr_loc (input_location
, tmp
, 2,
3671 se
->expr
= build_call_expr_loc (input_location
, tmp
, 2,
3676 /* Having excluded floating point types, we know we are now dealing
3677 with signed integer types. */
3678 type
= TREE_TYPE (args
[0]);
3680 /* Args[0] is used multiple times below. */
3681 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
3683 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3684 the signs of A and B are the same, and of all ones if they differ. */
3685 tmp
= fold_build2_loc (input_location
, BIT_XOR_EXPR
, type
, args
[0], args
[1]);
3686 tmp
= fold_build2_loc (input_location
, RSHIFT_EXPR
, type
, tmp
,
3687 build_int_cst (type
, TYPE_PRECISION (type
) - 1));
3688 tmp
= gfc_evaluate_now (tmp
, &se
->pre
);
3690 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3691 is all ones (i.e. -1). */
3692 se
->expr
= fold_build2_loc (input_location
, BIT_XOR_EXPR
, type
,
3693 fold_build2_loc (input_location
, PLUS_EXPR
,
3694 type
, args
[0], tmp
), tmp
);
3698 /* Test for the presence of an optional argument. */
3701 gfc_conv_intrinsic_present (gfc_se
* se
, gfc_expr
* expr
)
3705 arg
= expr
->value
.function
.actual
->expr
;
3706 gcc_assert (arg
->expr_type
== EXPR_VARIABLE
);
3707 se
->expr
= gfc_conv_expr_present (arg
->symtree
->n
.sym
);
3708 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
3712 /* Calculate the double precision product of two single precision values. */
3715 gfc_conv_intrinsic_dprod (gfc_se
* se
, gfc_expr
* expr
)
3720 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
3722 /* Convert the args to double precision before multiplying. */
3723 type
= gfc_typenode_for_spec (&expr
->ts
);
3724 args
[0] = convert (type
, args
[0]);
3725 args
[1] = convert (type
, args
[1]);
3726 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, type
, args
[0],
3731 /* Return a length one character string containing an ascii character. */
3734 gfc_conv_intrinsic_char (gfc_se
* se
, gfc_expr
* expr
)
3739 unsigned int num_args
;
3741 num_args
= gfc_intrinsic_argument_list_length (expr
);
3742 gfc_conv_intrinsic_function_args (se
, expr
, arg
, num_args
);
3744 type
= gfc_get_char_type (expr
->ts
.kind
);
3745 var
= gfc_create_var (type
, "char");
3747 arg
[0] = fold_build1_loc (input_location
, NOP_EXPR
, type
, arg
[0]);
3748 gfc_add_modify (&se
->pre
, var
, arg
[0]);
3749 se
->expr
= gfc_build_addr_expr (build_pointer_type (type
), var
);
3750 se
->string_length
= build_int_cst (gfc_charlen_type_node
, 1);
3755 gfc_conv_intrinsic_ctime (gfc_se
* se
, gfc_expr
* expr
)
3763 unsigned int num_args
;
3765 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
3766 args
= XALLOCAVEC (tree
, num_args
);
3768 var
= gfc_create_var (pchar_type_node
, "pstr");
3769 len
= gfc_create_var (gfc_charlen_type_node
, "len");
3771 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
3772 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
3773 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
3775 fndecl
= build_addr (gfor_fndecl_ctime
);
3776 tmp
= build_call_array_loc (input_location
,
3777 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime
)),
3778 fndecl
, num_args
, args
);
3779 gfc_add_expr_to_block (&se
->pre
, tmp
);
3781 /* Free the temporary afterwards, if necessary. */
3782 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3783 len
, build_int_cst (TREE_TYPE (len
), 0));
3784 tmp
= gfc_call_free (var
);
3785 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
3786 gfc_add_expr_to_block (&se
->post
, tmp
);
3789 se
->string_length
= len
;
3794 gfc_conv_intrinsic_fdate (gfc_se
* se
, gfc_expr
* expr
)
3802 unsigned int num_args
;
3804 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
3805 args
= XALLOCAVEC (tree
, num_args
);
3807 var
= gfc_create_var (pchar_type_node
, "pstr");
3808 len
= gfc_create_var (gfc_charlen_type_node
, "len");
3810 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
3811 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
3812 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
3814 fndecl
= build_addr (gfor_fndecl_fdate
);
3815 tmp
= build_call_array_loc (input_location
,
3816 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate
)),
3817 fndecl
, num_args
, args
);
3818 gfc_add_expr_to_block (&se
->pre
, tmp
);
3820 /* Free the temporary afterwards, if necessary. */
3821 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3822 len
, build_int_cst (TREE_TYPE (len
), 0));
3823 tmp
= gfc_call_free (var
);
3824 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
3825 gfc_add_expr_to_block (&se
->post
, tmp
);
3828 se
->string_length
= len
;
3832 /* Generate a direct call to free() for the FREE subroutine. */
3835 conv_intrinsic_free (gfc_code
*code
)
3841 gfc_init_se (&argse
, NULL
);
3842 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
3843 arg
= fold_convert (ptr_type_node
, argse
.expr
);
3845 gfc_init_block (&block
);
3846 call
= build_call_expr_loc (input_location
,
3847 builtin_decl_explicit (BUILT_IN_FREE
), 1, arg
);
3848 gfc_add_expr_to_block (&block
, call
);
3849 return gfc_finish_block (&block
);
3853 /* Call the RANDOM_INIT library subroutine with a hidden argument for
3854 handling seeding on coarray images. */
3857 conv_intrinsic_random_init (gfc_code
*code
)
3861 tree arg1
, arg2
, tmp
;
3862 /* On none coarray == lib compiles use LOGICAL(4) else regular LOGICAL. */
3863 tree used_bool_type_node
= flag_coarray
== GFC_FCOARRAY_LIB
3865 : gfc_get_logical_type (4);
3867 /* Make the function call. */
3868 gfc_init_block (&block
);
3869 gfc_init_se (&se
, NULL
);
3871 /* Convert REPEATABLE to the desired LOGICAL entity. */
3872 gfc_conv_expr (&se
, code
->ext
.actual
->expr
);
3873 gfc_add_block_to_block (&block
, &se
.pre
);
3874 arg1
= fold_convert (used_bool_type_node
, gfc_evaluate_now (se
.expr
, &block
));
3875 gfc_add_block_to_block (&block
, &se
.post
);
3877 /* Convert IMAGE_DISTINCT to the desired LOGICAL entity. */
3878 gfc_conv_expr (&se
, code
->ext
.actual
->next
->expr
);
3879 gfc_add_block_to_block (&block
, &se
.pre
);
3880 arg2
= fold_convert (used_bool_type_node
, gfc_evaluate_now (se
.expr
, &block
));
3881 gfc_add_block_to_block (&block
, &se
.post
);
3883 if (flag_coarray
== GFC_FCOARRAY_LIB
)
3885 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_random_init
,
3890 /* The ABI for libgfortran needs to be maintained, so a hidden
3891 argument must be include if code is compiled with -fcoarray=single
3892 or without the option. Set to 0. */
3893 tree arg3
= build_int_cst (gfc_get_int_type (4), 0);
3894 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_random_init
,
3895 3, arg1
, arg2
, arg3
);
3898 gfc_add_expr_to_block (&block
, tmp
);
3900 return gfc_finish_block (&block
);
3904 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3908 conv_intrinsic_system_clock (gfc_code
*code
)
3911 gfc_se count_se
, count_rate_se
, count_max_se
;
3912 tree arg1
= NULL_TREE
, arg2
= NULL_TREE
, arg3
= NULL_TREE
;
3916 gfc_expr
*count
= code
->ext
.actual
->expr
;
3917 gfc_expr
*count_rate
= code
->ext
.actual
->next
->expr
;
3918 gfc_expr
*count_max
= code
->ext
.actual
->next
->next
->expr
;
3920 /* Evaluate our arguments. */
3923 gfc_init_se (&count_se
, NULL
);
3924 gfc_conv_expr (&count_se
, count
);
3929 gfc_init_se (&count_rate_se
, NULL
);
3930 gfc_conv_expr (&count_rate_se
, count_rate
);
3935 gfc_init_se (&count_max_se
, NULL
);
3936 gfc_conv_expr (&count_max_se
, count_max
);
3939 /* Find the smallest kind found of the arguments. */
3941 least
= (count
&& count
->ts
.kind
< least
) ? count
->ts
.kind
: least
;
3942 least
= (count_rate
&& count_rate
->ts
.kind
< least
) ? count_rate
->ts
.kind
3944 least
= (count_max
&& count_max
->ts
.kind
< least
) ? count_max
->ts
.kind
3947 /* Prepare temporary variables. */
3952 arg1
= gfc_create_var (gfc_get_int_type (8), "count");
3953 else if (least
== 4)
3954 arg1
= gfc_create_var (gfc_get_int_type (4), "count");
3955 else if (count
->ts
.kind
== 1)
3956 arg1
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[0].pedantic_min_int
,
3959 arg1
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[1].pedantic_min_int
,
3966 arg2
= gfc_create_var (gfc_get_int_type (8), "count_rate");
3967 else if (least
== 4)
3968 arg2
= gfc_create_var (gfc_get_int_type (4), "count_rate");
3970 arg2
= integer_zero_node
;
3976 arg3
= gfc_create_var (gfc_get_int_type (8), "count_max");
3977 else if (least
== 4)
3978 arg3
= gfc_create_var (gfc_get_int_type (4), "count_max");
3980 arg3
= integer_zero_node
;
3983 /* Make the function call. */
3984 gfc_init_block (&block
);
3990 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
3991 : null_pointer_node
;
3992 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
3993 : null_pointer_node
;
3994 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
3995 : null_pointer_node
;
4000 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
4001 : null_pointer_node
;
4002 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
4003 : null_pointer_node
;
4004 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
4005 : null_pointer_node
;
4012 tmp
= build_call_expr_loc (input_location
,
4013 gfor_fndecl_system_clock4
, 3,
4014 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
4015 : null_pointer_node
,
4016 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
4017 : null_pointer_node
,
4018 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
4019 : null_pointer_node
);
4020 gfc_add_expr_to_block (&block
, tmp
);
4022 /* Handle kind>=8, 10, or 16 arguments */
4025 tmp
= build_call_expr_loc (input_location
,
4026 gfor_fndecl_system_clock8
, 3,
4027 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
4028 : null_pointer_node
,
4029 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
4030 : null_pointer_node
,
4031 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
4032 : null_pointer_node
);
4033 gfc_add_expr_to_block (&block
, tmp
);
4037 /* And store values back if needed. */
4038 if (arg1
&& arg1
!= count_se
.expr
)
4039 gfc_add_modify (&block
, count_se
.expr
,
4040 fold_convert (TREE_TYPE (count_se
.expr
), arg1
));
4041 if (arg2
&& arg2
!= count_rate_se
.expr
)
4042 gfc_add_modify (&block
, count_rate_se
.expr
,
4043 fold_convert (TREE_TYPE (count_rate_se
.expr
), arg2
));
4044 if (arg3
&& arg3
!= count_max_se
.expr
)
4045 gfc_add_modify (&block
, count_max_se
.expr
,
4046 fold_convert (TREE_TYPE (count_max_se
.expr
), arg3
));
4048 return gfc_finish_block (&block
);
4052 /* Return a character string containing the tty name. */
4055 gfc_conv_intrinsic_ttynam (gfc_se
* se
, gfc_expr
* expr
)
4063 unsigned int num_args
;
4065 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
4066 args
= XALLOCAVEC (tree
, num_args
);
4068 var
= gfc_create_var (pchar_type_node
, "pstr");
4069 len
= gfc_create_var (gfc_charlen_type_node
, "len");
4071 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
4072 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
4073 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
4075 fndecl
= build_addr (gfor_fndecl_ttynam
);
4076 tmp
= build_call_array_loc (input_location
,
4077 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam
)),
4078 fndecl
, num_args
, args
);
4079 gfc_add_expr_to_block (&se
->pre
, tmp
);
4081 /* Free the temporary afterwards, if necessary. */
4082 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
4083 len
, build_int_cst (TREE_TYPE (len
), 0));
4084 tmp
= gfc_call_free (var
);
4085 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
4086 gfc_add_expr_to_block (&se
->post
, tmp
);
4089 se
->string_length
= len
;
4093 /* Get the minimum/maximum value of all the parameters.
4094 minmax (a1, a2, a3, ...)
4097 mvar = COMP (mvar, a2)
4098 mvar = COMP (mvar, a3)
4102 Where COMP is MIN/MAX_EXPR for integral types or when we don't
4103 care about NaNs, or IFN_FMIN/MAX when the target has support for
4104 fast NaN-honouring min/max. When neither holds expand a sequence
4105 of explicit comparisons. */
4107 /* TODO: Mismatching types can occur when specific names are used.
4108 These should be handled during resolution. */
4110 gfc_conv_intrinsic_minmax (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
4118 gfc_actual_arglist
*argexpr
;
4119 unsigned int i
, nargs
;
4121 nargs
= gfc_intrinsic_argument_list_length (expr
);
4122 args
= XALLOCAVEC (tree
, nargs
);
4124 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
4125 type
= gfc_typenode_for_spec (&expr
->ts
);
4127 /* Only evaluate the argument once. */
4128 if (!VAR_P (args
[0]) && !TREE_CONSTANT (args
[0]))
4129 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
4131 /* Determine suitable type of temporary, as a GNU extension allows
4132 different argument kinds. */
4133 argtype
= TREE_TYPE (args
[0]);
4134 argexpr
= expr
->value
.function
.actual
;
4135 for (i
= 1, argexpr
= argexpr
->next
; i
< nargs
; i
++, argexpr
= argexpr
->next
)
4137 tree tmptype
= TREE_TYPE (args
[i
]);
4138 if (TYPE_PRECISION (tmptype
) > TYPE_PRECISION (argtype
))
4141 mvar
= gfc_create_var (argtype
, "M");
4142 gfc_add_modify (&se
->pre
, mvar
, convert (argtype
, args
[0]));
4144 argexpr
= expr
->value
.function
.actual
;
4145 for (i
= 1, argexpr
= argexpr
->next
; i
< nargs
; i
++, argexpr
= argexpr
->next
)
4147 tree cond
= NULL_TREE
;
4150 /* Handle absent optional arguments by ignoring the comparison. */
4151 if (argexpr
->expr
->expr_type
== EXPR_VARIABLE
4152 && argexpr
->expr
->symtree
->n
.sym
->attr
.optional
4153 && INDIRECT_REF_P (val
))
4155 cond
= fold_build2_loc (input_location
,
4156 NE_EXPR
, logical_type_node
,
4157 TREE_OPERAND (val
, 0),
4158 build_int_cst (TREE_TYPE (TREE_OPERAND (val
, 0)), 0));
4160 else if (!VAR_P (val
) && !TREE_CONSTANT (val
))
4161 /* Only evaluate the argument once. */
4162 val
= gfc_evaluate_now (val
, &se
->pre
);
4165 /* For floating point types, the question is what MAX(a, NaN) or
4166 MIN(a, NaN) should return (where "a" is a normal number).
4167 There are valid use case for returning either one, but the
4168 Fortran standard doesn't specify which one should be chosen.
4169 Also, there is no consensus among other tested compilers. In
4170 short, it's a mess. So lets just do whatever is fastest. */
4171 tree_code code
= op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
;
4172 calc
= fold_build2_loc (input_location
, code
, argtype
,
4173 convert (argtype
, val
), mvar
);
4174 tmp
= build2_v (MODIFY_EXPR
, mvar
, calc
);
4176 if (cond
!= NULL_TREE
)
4177 tmp
= build3_v (COND_EXPR
, cond
, tmp
,
4178 build_empty_stmt (input_location
));
4179 gfc_add_expr_to_block (&se
->pre
, tmp
);
4181 se
->expr
= convert (type
, mvar
);
4185 /* Generate library calls for MIN and MAX intrinsics for character
4188 gfc_conv_intrinsic_minmax_char (gfc_se
* se
, gfc_expr
* expr
, int op
)
4191 tree var
, len
, fndecl
, tmp
, cond
, function
;
4194 nargs
= gfc_intrinsic_argument_list_length (expr
);
4195 args
= XALLOCAVEC (tree
, nargs
+ 4);
4196 gfc_conv_intrinsic_function_args (se
, expr
, &args
[4], nargs
);
4198 /* Create the result variables. */
4199 len
= gfc_create_var (gfc_charlen_type_node
, "len");
4200 args
[0] = gfc_build_addr_expr (NULL_TREE
, len
);
4201 var
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
), "pstr");
4202 args
[1] = gfc_build_addr_expr (ppvoid_type_node
, var
);
4203 args
[2] = build_int_cst (integer_type_node
, op
);
4204 args
[3] = build_int_cst (integer_type_node
, nargs
/ 2);
4206 if (expr
->ts
.kind
== 1)
4207 function
= gfor_fndecl_string_minmax
;
4208 else if (expr
->ts
.kind
== 4)
4209 function
= gfor_fndecl_string_minmax_char4
;
4213 /* Make the function call. */
4214 fndecl
= build_addr (function
);
4215 tmp
= build_call_array_loc (input_location
,
4216 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
4218 gfc_add_expr_to_block (&se
->pre
, tmp
);
4220 /* Free the temporary afterwards, if necessary. */
4221 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
4222 len
, build_int_cst (TREE_TYPE (len
), 0));
4223 tmp
= gfc_call_free (var
);
4224 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
4225 gfc_add_expr_to_block (&se
->post
, tmp
);
4228 se
->string_length
= len
;
4232 /* Create a symbol node for this intrinsic. The symbol from the frontend
4233 has the generic name. */
4236 gfc_get_symbol_for_expr (gfc_expr
* expr
, bool ignore_optional
)
4240 /* TODO: Add symbols for intrinsic function to the global namespace. */
4241 gcc_assert (strlen (expr
->value
.function
.name
) <= GFC_MAX_SYMBOL_LEN
- 5);
4242 sym
= gfc_new_symbol (expr
->value
.function
.name
, NULL
);
4245 if (sym
->ts
.type
== BT_CHARACTER
)
4246 sym
->ts
.u
.cl
= gfc_new_charlen (gfc_current_ns
, NULL
);
4247 sym
->attr
.external
= 1;
4248 sym
->attr
.function
= 1;
4249 sym
->attr
.always_explicit
= 1;
4250 sym
->attr
.proc
= PROC_INTRINSIC
;
4251 sym
->attr
.flavor
= FL_PROCEDURE
;
4255 sym
->attr
.dimension
= 1;
4256 sym
->as
= gfc_get_array_spec ();
4257 sym
->as
->type
= AS_ASSUMED_SHAPE
;
4258 sym
->as
->rank
= expr
->rank
;
4261 gfc_copy_formal_args_intr (sym
, expr
->value
.function
.isym
,
4262 ignore_optional
? expr
->value
.function
.actual
4268 /* Remove empty actual arguments. */
4271 remove_empty_actual_arguments (gfc_actual_arglist
**ap
)
4275 if ((*ap
)->expr
== NULL
)
4277 gfc_actual_arglist
*r
= *ap
;
4280 gfc_free_actual_arglist (r
);
4283 ap
= &((*ap
)->next
);
4287 #define MAX_SPEC_ARG 12
4289 /* Make up an fn spec that's right for intrinsic functions that we
4293 intrinsic_fnspec (gfc_expr
*expr
)
4295 static char fnspec_buf
[MAX_SPEC_ARG
*2+1];
4300 #define ADD_CHAR(c) do { *fp++ = c; *fp++ = ' '; } while(0)
4302 /* Set the fndecl. */
4304 /* Function return value. FIXME: Check if the second letter could
4305 be something other than a space, for further optimization. */
4307 if (expr
->rank
== 0)
4309 if (expr
->ts
.type
== BT_CHARACTER
)
4311 ADD_CHAR ('w'); /* Address of character. */
4312 ADD_CHAR ('.'); /* Length of character. */
4316 ADD_CHAR ('w'); /* Return value is a descriptor. */
4319 for (gfc_actual_arglist
*a
= expr
->value
.function
.actual
; a
; a
= a
->next
)
4321 if (a
->expr
== NULL
)
4324 if (a
->name
&& strcmp (a
->name
,"%VAL") == 0)
4328 if (a
->expr
->rank
> 0)
4333 num_char_args
+= a
->expr
->ts
.type
== BT_CHARACTER
;
4334 gcc_assert (fp
- fnspec_buf
+ num_char_args
<= MAX_SPEC_ARG
*2);
4337 for (i
= 0; i
< num_char_args
; i
++)
4347 /* Generate the right symbol for the specific intrinsic function and
4348 modify the expr accordingly. This assumes that absent optional
4349 arguments should be removed. */
4352 specific_intrinsic_symbol (gfc_expr
*expr
)
4356 sym
= gfc_find_intrinsic_symbol (expr
);
4359 sym
= gfc_get_intrinsic_function_symbol (expr
);
4361 if (sym
->ts
.type
== BT_CHARACTER
&& sym
->ts
.u
.cl
)
4362 sym
->ts
.u
.cl
= gfc_new_charlen (sym
->ns
, NULL
);
4364 gfc_copy_formal_args_intr (sym
, expr
->value
.function
.isym
,
4365 expr
->value
.function
.actual
, true);
4367 = gfc_get_extern_function_decl (sym
, expr
->value
.function
.actual
,
4368 intrinsic_fnspec (expr
));
4371 remove_empty_actual_arguments (&(expr
->value
.function
.actual
));
4376 /* Generate a call to an external intrinsic function. FIXME: So far,
4377 this only works for functions which are called with well-defined
4378 types; CSHIFT and friends will come later. */
4381 gfc_conv_intrinsic_funcall (gfc_se
* se
, gfc_expr
* expr
)
4384 vec
<tree
, va_gc
> *append_args
;
4385 bool specific_symbol
;
4387 gcc_assert (!se
->ss
|| se
->ss
->info
->expr
== expr
);
4390 gcc_assert (expr
->rank
> 0);
4392 gcc_assert (expr
->rank
== 0);
4394 switch (expr
->value
.function
.isym
->id
)
4398 case GFC_ISYM_FINDLOC
:
4399 case GFC_ISYM_MAXLOC
:
4400 case GFC_ISYM_MINLOC
:
4401 case GFC_ISYM_MAXVAL
:
4402 case GFC_ISYM_MINVAL
:
4403 case GFC_ISYM_NORM2
:
4404 case GFC_ISYM_PRODUCT
:
4406 specific_symbol
= true;
4409 specific_symbol
= false;
4412 if (specific_symbol
)
4414 /* Need to copy here because specific_intrinsic_symbol modifies
4415 expr to omit the absent optional arguments. */
4416 expr
= gfc_copy_expr (expr
);
4417 sym
= specific_intrinsic_symbol (expr
);
4420 sym
= gfc_get_symbol_for_expr (expr
, se
->ignore_optional
);
4422 /* Calls to libgfortran_matmul need to be appended special arguments,
4423 to be able to call the BLAS ?gemm functions if required and possible. */
4425 if (expr
->value
.function
.isym
->id
== GFC_ISYM_MATMUL
4426 && !expr
->external_blas
4427 && sym
->ts
.type
!= BT_LOGICAL
)
4429 tree cint
= gfc_get_int_type (gfc_c_int_kind
);
4431 if (flag_external_blas
4432 && (sym
->ts
.type
== BT_REAL
|| sym
->ts
.type
== BT_COMPLEX
)
4433 && (sym
->ts
.kind
== 4 || sym
->ts
.kind
== 8))
4437 if (sym
->ts
.type
== BT_REAL
)
4439 if (sym
->ts
.kind
== 4)
4440 gemm_fndecl
= gfor_fndecl_sgemm
;
4442 gemm_fndecl
= gfor_fndecl_dgemm
;
4446 if (sym
->ts
.kind
== 4)
4447 gemm_fndecl
= gfor_fndecl_cgemm
;
4449 gemm_fndecl
= gfor_fndecl_zgemm
;
4452 vec_alloc (append_args
, 3);
4453 append_args
->quick_push (build_int_cst (cint
, 1));
4454 append_args
->quick_push (build_int_cst (cint
,
4455 flag_blas_matmul_limit
));
4456 append_args
->quick_push (gfc_build_addr_expr (NULL_TREE
,
4461 vec_alloc (append_args
, 3);
4462 append_args
->quick_push (build_int_cst (cint
, 0));
4463 append_args
->quick_push (build_int_cst (cint
, 0));
4464 append_args
->quick_push (null_pointer_node
);
4468 gfc_conv_procedure_call (se
, sym
, expr
->value
.function
.actual
, expr
,
4471 if (specific_symbol
)
4472 gfc_free_expr (expr
);
4474 gfc_free_symbol (sym
);
4477 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4497 gfc_conv_intrinsic_anyall (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
4506 gfc_actual_arglist
*actual
;
4513 gfc_conv_intrinsic_funcall (se
, expr
);
4517 actual
= expr
->value
.function
.actual
;
4518 type
= gfc_typenode_for_spec (&expr
->ts
);
4519 /* Initialize the result. */
4520 resvar
= gfc_create_var (type
, "test");
4522 tmp
= convert (type
, boolean_true_node
);
4524 tmp
= convert (type
, boolean_false_node
);
4525 gfc_add_modify (&se
->pre
, resvar
, tmp
);
4527 /* Walk the arguments. */
4528 arrayss
= gfc_walk_expr (actual
->expr
);
4529 gcc_assert (arrayss
!= gfc_ss_terminator
);
4531 /* Initialize the scalarizer. */
4532 gfc_init_loopinfo (&loop
);
4533 exit_label
= gfc_build_label_decl (NULL_TREE
);
4534 TREE_USED (exit_label
) = 1;
4535 gfc_add_ss_to_loop (&loop
, arrayss
);
4537 /* Initialize the loop. */
4538 gfc_conv_ss_startstride (&loop
);
4539 gfc_conv_loop_setup (&loop
, &expr
->where
);
4541 gfc_mark_ss_chain_used (arrayss
, 1);
4542 /* Generate the loop body. */
4543 gfc_start_scalarized_body (&loop
, &body
);
4545 /* If the condition matches then set the return value. */
4546 gfc_start_block (&block
);
4548 tmp
= convert (type
, boolean_false_node
);
4550 tmp
= convert (type
, boolean_true_node
);
4551 gfc_add_modify (&block
, resvar
, tmp
);
4553 /* And break out of the loop. */
4554 tmp
= build1_v (GOTO_EXPR
, exit_label
);
4555 gfc_add_expr_to_block (&block
, tmp
);
4557 found
= gfc_finish_block (&block
);
4559 /* Check this element. */
4560 gfc_init_se (&arrayse
, NULL
);
4561 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
4562 arrayse
.ss
= arrayss
;
4563 gfc_conv_expr_val (&arrayse
, actual
->expr
);
4565 gfc_add_block_to_block (&body
, &arrayse
.pre
);
4566 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
, arrayse
.expr
,
4567 build_int_cst (TREE_TYPE (arrayse
.expr
), 0));
4568 tmp
= build3_v (COND_EXPR
, tmp
, found
, build_empty_stmt (input_location
));
4569 gfc_add_expr_to_block (&body
, tmp
);
4570 gfc_add_block_to_block (&body
, &arrayse
.post
);
4572 gfc_trans_scalarizing_loops (&loop
, &body
);
4574 /* Add the exit label. */
4575 tmp
= build1_v (LABEL_EXPR
, exit_label
);
4576 gfc_add_expr_to_block (&loop
.pre
, tmp
);
4578 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
4579 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
4580 gfc_cleanup_loop (&loop
);
4586 /* Generate the constant 180 / pi, which is used in the conversion
4587 of acosd(), asind(), atand(), atan2d(). */
4595 gfc_set_model_kind (kind
);
4598 mpfr_set_si (t0
, 180, GFC_RND_MODE
);
4599 mpfr_const_pi (pi
, GFC_RND_MODE
);
4600 mpfr_div (t0
, t0
, pi
, GFC_RND_MODE
);
4601 retval
= gfc_conv_mpfr_to_tree (t0
, kind
, 0);
4608 static gfc_intrinsic_map_t
*
4609 gfc_lookup_intrinsic (gfc_isym_id id
)
4611 gfc_intrinsic_map_t
*m
= gfc_intrinsic_map
;
4612 for (; m
->id
!= GFC_ISYM_NONE
|| m
->double_built_in
!= END_BUILTINS
; m
++)
4615 gcc_assert (id
== m
->id
);
4620 /* ACOSD(x) is translated into ACOS(x) * 180 / pi.
4621 ASIND(x) is translated into ASIN(x) * 180 / pi.
4622 ATAND(x) is translated into ATAN(x) * 180 / pi. */
4625 gfc_conv_intrinsic_atrigd (gfc_se
* se
, gfc_expr
* expr
, gfc_isym_id id
)
4630 gfc_intrinsic_map_t
*m
;
4632 type
= gfc_typenode_for_spec (&expr
->ts
);
4634 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
4638 case GFC_ISYM_ACOSD
:
4639 m
= gfc_lookup_intrinsic (GFC_ISYM_ACOS
);
4641 case GFC_ISYM_ASIND
:
4642 m
= gfc_lookup_intrinsic (GFC_ISYM_ASIN
);
4644 case GFC_ISYM_ATAND
:
4645 m
= gfc_lookup_intrinsic (GFC_ISYM_ATAN
);
4650 atrigd
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
4651 atrigd
= build_call_expr_loc (input_location
, atrigd
, 1, arg
);
4653 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, type
, atrigd
,
4654 fold_convert (type
, rad2deg (expr
->ts
.kind
)));
4658 /* COTAN(X) is translated into -TAN(X+PI/2) for REAL argument and
4659 COS(X) / SIN(X) for COMPLEX argument. */
4662 gfc_conv_intrinsic_cotan (gfc_se
*se
, gfc_expr
*expr
)
4664 gfc_intrinsic_map_t
*m
;
4668 type
= gfc_typenode_for_spec (&expr
->ts
);
4669 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
4671 if (expr
->ts
.type
== BT_REAL
)
4678 gfc_set_model_kind (expr
->ts
.kind
);
4680 mpfr_const_pi (pio2
, GFC_RND_MODE
);
4681 mpfr_div_ui (pio2
, pio2
, 2, GFC_RND_MODE
);
4682 tmp
= gfc_conv_mpfr_to_tree (pio2
, expr
->ts
.kind
, 0);
4685 /* Find tan builtin function. */
4686 m
= gfc_lookup_intrinsic (GFC_ISYM_TAN
);
4687 tan
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
4688 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, arg
, tmp
);
4689 tan
= build_call_expr_loc (input_location
, tan
, 1, tmp
);
4690 se
->expr
= fold_build1_loc (input_location
, NEGATE_EXPR
, type
, tan
);
4697 /* Find cos builtin function. */
4698 m
= gfc_lookup_intrinsic (GFC_ISYM_COS
);
4699 cos
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
4700 cos
= build_call_expr_loc (input_location
, cos
, 1, arg
);
4702 /* Find sin builtin function. */
4703 m
= gfc_lookup_intrinsic (GFC_ISYM_SIN
);
4704 sin
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
4705 sin
= build_call_expr_loc (input_location
, sin
, 1, arg
);
4707 /* Divide cos by sin. */
4708 se
->expr
= fold_build2_loc (input_location
, RDIV_EXPR
, type
, cos
, sin
);
4713 /* COTAND(X) is translated into -TAND(X+90) for REAL argument. */
4716 gfc_conv_intrinsic_cotand (gfc_se
*se
, gfc_expr
*expr
)
4723 type
= gfc_typenode_for_spec (&expr
->ts
);
4724 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
4726 gfc_set_model_kind (expr
->ts
.kind
);
4728 /* Build the tree for x + 90. */
4729 mpfr_init_set_ui (ninety
, 90, GFC_RND_MODE
);
4730 ninety_tree
= gfc_conv_mpfr_to_tree (ninety
, expr
->ts
.kind
, 0);
4731 arg
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, arg
, ninety_tree
);
4732 mpfr_clear (ninety
);
4735 gfc_intrinsic_map_t
*m
= gfc_lookup_intrinsic (GFC_ISYM_TAND
);
4736 tree tand
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
4737 tand
= build_call_expr_loc (input_location
, tand
, 1, arg
);
4739 se
->expr
= fold_build1_loc (input_location
, NEGATE_EXPR
, type
, tand
);
4743 /* ATAN2D(Y,X) is translated into ATAN2(Y,X) * 180 / PI. */
4746 gfc_conv_intrinsic_atan2d (gfc_se
*se
, gfc_expr
*expr
)
4752 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
4753 type
= TREE_TYPE (args
[0]);
4755 gfc_intrinsic_map_t
*m
= gfc_lookup_intrinsic (GFC_ISYM_ATAN2
);
4756 atan2d
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
4757 atan2d
= build_call_expr_loc (input_location
, atan2d
, 2, args
[0], args
[1]);
4759 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, type
, atan2d
,
4760 rad2deg (expr
->ts
.kind
));
4764 /* COUNT(A) = Number of true elements in A. */
4766 gfc_conv_intrinsic_count (gfc_se
* se
, gfc_expr
* expr
)
4773 gfc_actual_arglist
*actual
;
4779 gfc_conv_intrinsic_funcall (se
, expr
);
4783 actual
= expr
->value
.function
.actual
;
4785 type
= gfc_typenode_for_spec (&expr
->ts
);
4786 /* Initialize the result. */
4787 resvar
= gfc_create_var (type
, "count");
4788 gfc_add_modify (&se
->pre
, resvar
, build_int_cst (type
, 0));
4790 /* Walk the arguments. */
4791 arrayss
= gfc_walk_expr (actual
->expr
);
4792 gcc_assert (arrayss
!= gfc_ss_terminator
);
4794 /* Initialize the scalarizer. */
4795 gfc_init_loopinfo (&loop
);
4796 gfc_add_ss_to_loop (&loop
, arrayss
);
4798 /* Initialize the loop. */
4799 gfc_conv_ss_startstride (&loop
);
4800 gfc_conv_loop_setup (&loop
, &expr
->where
);
4802 gfc_mark_ss_chain_used (arrayss
, 1);
4803 /* Generate the loop body. */
4804 gfc_start_scalarized_body (&loop
, &body
);
4806 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (resvar
),
4807 resvar
, build_int_cst (TREE_TYPE (resvar
), 1));
4808 tmp
= build2_v (MODIFY_EXPR
, resvar
, tmp
);
4810 gfc_init_se (&arrayse
, NULL
);
4811 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
4812 arrayse
.ss
= arrayss
;
4813 gfc_conv_expr_val (&arrayse
, actual
->expr
);
4814 tmp
= build3_v (COND_EXPR
, arrayse
.expr
, tmp
,
4815 build_empty_stmt (input_location
));
4817 gfc_add_block_to_block (&body
, &arrayse
.pre
);
4818 gfc_add_expr_to_block (&body
, tmp
);
4819 gfc_add_block_to_block (&body
, &arrayse
.post
);
4821 gfc_trans_scalarizing_loops (&loop
, &body
);
4823 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
4824 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
4825 gfc_cleanup_loop (&loop
);
4831 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4832 struct and return the corresponding loopinfo. */
4834 static gfc_loopinfo
*
4835 enter_nested_loop (gfc_se
*se
)
4837 se
->ss
= se
->ss
->nested_ss
;
4838 gcc_assert (se
->ss
== se
->ss
->loop
->ss
);
4840 return se
->ss
->loop
;
4843 /* Build the condition for a mask, which may be optional. */
4846 conv_mask_condition (gfc_se
*maskse
, gfc_expr
*maskexpr
,
4854 type
= TREE_TYPE (maskse
->expr
);
4855 present
= gfc_conv_expr_present (maskexpr
->symtree
->n
.sym
);
4856 present
= convert (type
, present
);
4857 present
= fold_build1_loc (input_location
, TRUTH_NOT_EXPR
, type
,
4859 return fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
4860 type
, present
, maskse
->expr
);
4863 return maskse
->expr
;
4866 /* Inline implementation of the sum and product intrinsics. */
4868 gfc_conv_intrinsic_arith (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
,
4872 tree scale
= NULL_TREE
;
4877 gfc_loopinfo loop
, *ploop
;
4878 gfc_actual_arglist
*arg_array
, *arg_mask
;
4879 gfc_ss
*arrayss
= NULL
;
4880 gfc_ss
*maskss
= NULL
;
4884 gfc_expr
*arrayexpr
;
4890 gcc_assert (gfc_inline_intrinsic_function_p (expr
));
4896 type
= gfc_typenode_for_spec (&expr
->ts
);
4897 /* Initialize the result. */
4898 resvar
= gfc_create_var (type
, "val");
4903 scale
= gfc_create_var (type
, "scale");
4904 gfc_add_modify (&se
->pre
, scale
,
4905 gfc_build_const (type
, integer_one_node
));
4906 tmp
= gfc_build_const (type
, integer_zero_node
);
4908 else if (op
== PLUS_EXPR
|| op
== BIT_IOR_EXPR
|| op
== BIT_XOR_EXPR
)
4909 tmp
= gfc_build_const (type
, integer_zero_node
);
4910 else if (op
== NE_EXPR
)
4912 tmp
= convert (type
, boolean_false_node
);
4913 else if (op
== BIT_AND_EXPR
)
4914 tmp
= gfc_build_const (type
, fold_build1_loc (input_location
, NEGATE_EXPR
,
4915 type
, integer_one_node
));
4917 tmp
= gfc_build_const (type
, integer_one_node
);
4919 gfc_add_modify (&se
->pre
, resvar
, tmp
);
4921 arg_array
= expr
->value
.function
.actual
;
4923 arrayexpr
= arg_array
->expr
;
4925 if (op
== NE_EXPR
|| norm2
)
4927 /* PARITY and NORM2. */
4929 optional_mask
= false;
4933 arg_mask
= arg_array
->next
->next
;
4934 gcc_assert (arg_mask
!= NULL
);
4935 maskexpr
= arg_mask
->expr
;
4936 optional_mask
= maskexpr
&& maskexpr
->expr_type
== EXPR_VARIABLE
4937 && maskexpr
->symtree
->n
.sym
->attr
.dummy
4938 && maskexpr
->symtree
->n
.sym
->attr
.optional
;
4941 if (expr
->rank
== 0)
4943 /* Walk the arguments. */
4944 arrayss
= gfc_walk_expr (arrayexpr
);
4945 gcc_assert (arrayss
!= gfc_ss_terminator
);
4947 if (maskexpr
&& maskexpr
->rank
> 0)
4949 maskss
= gfc_walk_expr (maskexpr
);
4950 gcc_assert (maskss
!= gfc_ss_terminator
);
4955 /* Initialize the scalarizer. */
4956 gfc_init_loopinfo (&loop
);
4958 /* We add the mask first because the number of iterations is
4959 taken from the last ss, and this breaks if an absent
4960 optional argument is used for mask. */
4962 if (maskexpr
&& maskexpr
->rank
> 0)
4963 gfc_add_ss_to_loop (&loop
, maskss
);
4964 gfc_add_ss_to_loop (&loop
, arrayss
);
4966 /* Initialize the loop. */
4967 gfc_conv_ss_startstride (&loop
);
4968 gfc_conv_loop_setup (&loop
, &expr
->where
);
4970 if (maskexpr
&& maskexpr
->rank
> 0)
4971 gfc_mark_ss_chain_used (maskss
, 1);
4972 gfc_mark_ss_chain_used (arrayss
, 1);
4977 /* All the work has been done in the parent loops. */
4978 ploop
= enter_nested_loop (se
);
4982 /* Generate the loop body. */
4983 gfc_start_scalarized_body (ploop
, &body
);
4985 /* If we have a mask, only add this element if the mask is set. */
4986 if (maskexpr
&& maskexpr
->rank
> 0)
4988 gfc_init_se (&maskse
, parent_se
);
4989 gfc_copy_loopinfo_to_se (&maskse
, ploop
);
4990 if (expr
->rank
== 0)
4992 gfc_conv_expr_val (&maskse
, maskexpr
);
4993 gfc_add_block_to_block (&body
, &maskse
.pre
);
4995 gfc_start_block (&block
);
4998 gfc_init_block (&block
);
5000 /* Do the actual summation/product. */
5001 gfc_init_se (&arrayse
, parent_se
);
5002 gfc_copy_loopinfo_to_se (&arrayse
, ploop
);
5003 if (expr
->rank
== 0)
5004 arrayse
.ss
= arrayss
;
5005 gfc_conv_expr_val (&arrayse
, arrayexpr
);
5006 gfc_add_block_to_block (&block
, &arrayse
.pre
);
5010 /* if (x (i) != 0.0)
5016 result = 1.0 + result * val * val;
5022 result += val * val;
5025 tree res1
, res2
, cond
, absX
, val
;
5026 stmtblock_t ifblock1
, ifblock2
, ifblock3
;
5028 gfc_init_block (&ifblock1
);
5030 absX
= gfc_create_var (type
, "absX");
5031 gfc_add_modify (&ifblock1
, absX
,
5032 fold_build1_loc (input_location
, ABS_EXPR
, type
,
5034 val
= gfc_create_var (type
, "val");
5035 gfc_add_expr_to_block (&ifblock1
, val
);
5037 gfc_init_block (&ifblock2
);
5038 gfc_add_modify (&ifblock2
, val
,
5039 fold_build2_loc (input_location
, RDIV_EXPR
, type
, scale
,
5041 res1
= fold_build2_loc (input_location
, MULT_EXPR
, type
, val
, val
);
5042 res1
= fold_build2_loc (input_location
, MULT_EXPR
, type
, resvar
, res1
);
5043 res1
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, res1
,
5044 gfc_build_const (type
, integer_one_node
));
5045 gfc_add_modify (&ifblock2
, resvar
, res1
);
5046 gfc_add_modify (&ifblock2
, scale
, absX
);
5047 res1
= gfc_finish_block (&ifblock2
);
5049 gfc_init_block (&ifblock3
);
5050 gfc_add_modify (&ifblock3
, val
,
5051 fold_build2_loc (input_location
, RDIV_EXPR
, type
, absX
,
5053 res2
= fold_build2_loc (input_location
, MULT_EXPR
, type
, val
, val
);
5054 res2
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, resvar
, res2
);
5055 gfc_add_modify (&ifblock3
, resvar
, res2
);
5056 res2
= gfc_finish_block (&ifblock3
);
5058 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
5060 tmp
= build3_v (COND_EXPR
, cond
, res1
, res2
);
5061 gfc_add_expr_to_block (&ifblock1
, tmp
);
5062 tmp
= gfc_finish_block (&ifblock1
);
5064 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
5066 gfc_build_const (type
, integer_zero_node
));
5068 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
5069 gfc_add_expr_to_block (&block
, tmp
);
5073 tmp
= fold_build2_loc (input_location
, op
, type
, resvar
, arrayse
.expr
);
5074 gfc_add_modify (&block
, resvar
, tmp
);
5077 gfc_add_block_to_block (&block
, &arrayse
.post
);
5079 if (maskexpr
&& maskexpr
->rank
> 0)
5081 /* We enclose the above in if (mask) {...} . If the mask is an
5082 optional argument, generate
5083 IF (.NOT. PRESENT(MASK) .OR. MASK(I)). */
5085 tmp
= gfc_finish_block (&block
);
5086 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
5087 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
5088 build_empty_stmt (input_location
));
5091 tmp
= gfc_finish_block (&block
);
5092 gfc_add_expr_to_block (&body
, tmp
);
5094 gfc_trans_scalarizing_loops (ploop
, &body
);
5096 /* For a scalar mask, enclose the loop in an if statement. */
5097 if (maskexpr
&& maskexpr
->rank
== 0)
5099 gfc_init_block (&block
);
5100 gfc_add_block_to_block (&block
, &ploop
->pre
);
5101 gfc_add_block_to_block (&block
, &ploop
->post
);
5102 tmp
= gfc_finish_block (&block
);
5106 tmp
= build3_v (COND_EXPR
, se
->ss
->info
->data
.scalar
.value
, tmp
,
5107 build_empty_stmt (input_location
));
5108 gfc_advance_se_ss_chain (se
);
5114 gcc_assert (expr
->rank
== 0);
5115 gfc_init_se (&maskse
, NULL
);
5116 gfc_conv_expr_val (&maskse
, maskexpr
);
5117 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
5118 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
5119 build_empty_stmt (input_location
));
5122 gfc_add_expr_to_block (&block
, tmp
);
5123 gfc_add_block_to_block (&se
->pre
, &block
);
5124 gcc_assert (se
->post
.head
== NULL
);
5128 gfc_add_block_to_block (&se
->pre
, &ploop
->pre
);
5129 gfc_add_block_to_block (&se
->pre
, &ploop
->post
);
5132 if (expr
->rank
== 0)
5133 gfc_cleanup_loop (ploop
);
5137 /* result = scale * sqrt(result). */
5139 sqrt
= gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT
, expr
->ts
.kind
);
5140 resvar
= build_call_expr_loc (input_location
,
5142 resvar
= fold_build2_loc (input_location
, MULT_EXPR
, type
, scale
, resvar
);
5149 /* Inline implementation of the dot_product intrinsic. This function
5150 is based on gfc_conv_intrinsic_arith (the previous function). */
5152 gfc_conv_intrinsic_dot_product (gfc_se
* se
, gfc_expr
* expr
)
5160 gfc_actual_arglist
*actual
;
5161 gfc_ss
*arrayss1
, *arrayss2
;
5162 gfc_se arrayse1
, arrayse2
;
5163 gfc_expr
*arrayexpr1
, *arrayexpr2
;
5165 type
= gfc_typenode_for_spec (&expr
->ts
);
5167 /* Initialize the result. */
5168 resvar
= gfc_create_var (type
, "val");
5169 if (expr
->ts
.type
== BT_LOGICAL
)
5170 tmp
= build_int_cst (type
, 0);
5172 tmp
= gfc_build_const (type
, integer_zero_node
);
5174 gfc_add_modify (&se
->pre
, resvar
, tmp
);
5176 /* Walk argument #1. */
5177 actual
= expr
->value
.function
.actual
;
5178 arrayexpr1
= actual
->expr
;
5179 arrayss1
= gfc_walk_expr (arrayexpr1
);
5180 gcc_assert (arrayss1
!= gfc_ss_terminator
);
5182 /* Walk argument #2. */
5183 actual
= actual
->next
;
5184 arrayexpr2
= actual
->expr
;
5185 arrayss2
= gfc_walk_expr (arrayexpr2
);
5186 gcc_assert (arrayss2
!= gfc_ss_terminator
);
5188 /* Initialize the scalarizer. */
5189 gfc_init_loopinfo (&loop
);
5190 gfc_add_ss_to_loop (&loop
, arrayss1
);
5191 gfc_add_ss_to_loop (&loop
, arrayss2
);
5193 /* Initialize the loop. */
5194 gfc_conv_ss_startstride (&loop
);
5195 gfc_conv_loop_setup (&loop
, &expr
->where
);
5197 gfc_mark_ss_chain_used (arrayss1
, 1);
5198 gfc_mark_ss_chain_used (arrayss2
, 1);
5200 /* Generate the loop body. */
5201 gfc_start_scalarized_body (&loop
, &body
);
5202 gfc_init_block (&block
);
5204 /* Make the tree expression for [conjg(]array1[)]. */
5205 gfc_init_se (&arrayse1
, NULL
);
5206 gfc_copy_loopinfo_to_se (&arrayse1
, &loop
);
5207 arrayse1
.ss
= arrayss1
;
5208 gfc_conv_expr_val (&arrayse1
, arrayexpr1
);
5209 if (expr
->ts
.type
== BT_COMPLEX
)
5210 arrayse1
.expr
= fold_build1_loc (input_location
, CONJ_EXPR
, type
,
5212 gfc_add_block_to_block (&block
, &arrayse1
.pre
);
5214 /* Make the tree expression for array2. */
5215 gfc_init_se (&arrayse2
, NULL
);
5216 gfc_copy_loopinfo_to_se (&arrayse2
, &loop
);
5217 arrayse2
.ss
= arrayss2
;
5218 gfc_conv_expr_val (&arrayse2
, arrayexpr2
);
5219 gfc_add_block_to_block (&block
, &arrayse2
.pre
);
5221 /* Do the actual product and sum. */
5222 if (expr
->ts
.type
== BT_LOGICAL
)
5224 tmp
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
, type
,
5225 arrayse1
.expr
, arrayse2
.expr
);
5226 tmp
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
, type
, resvar
, tmp
);
5230 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, type
, arrayse1
.expr
,
5232 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, resvar
, tmp
);
5234 gfc_add_modify (&block
, resvar
, tmp
);
5236 /* Finish up the loop block and the loop. */
5237 tmp
= gfc_finish_block (&block
);
5238 gfc_add_expr_to_block (&body
, tmp
);
5240 gfc_trans_scalarizing_loops (&loop
, &body
);
5241 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
5242 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
5243 gfc_cleanup_loop (&loop
);
5249 /* Tells whether the expression E is a reference to an optional variable whose
5250 presence is not known at compile time. Those are variable references without
5251 subreference; if there is a subreference, we can assume the variable is
5252 present. We have to special case full arrays, which we represent with a fake
5253 "full" reference, and class descriptors for which a reference to data is not
5254 really a subreference. */
5257 maybe_absent_optional_variable (gfc_expr
*e
)
5259 if (!(e
&& e
->expr_type
== EXPR_VARIABLE
))
5262 gfc_symbol
*sym
= e
->symtree
->n
.sym
;
5263 if (!sym
->attr
.optional
)
5266 gfc_ref
*ref
= e
->ref
;
5270 if (ref
->type
== REF_ARRAY
5271 && ref
->u
.ar
.type
== AR_FULL
5272 && ref
->next
== nullptr)
5275 if (!(sym
->ts
.type
== BT_CLASS
5276 && ref
->type
== REF_COMPONENT
5277 && ref
->u
.c
.component
== CLASS_DATA (sym
)))
5280 gfc_ref
*next_ref
= ref
->next
;
5281 if (next_ref
== nullptr)
5284 if (next_ref
->type
== REF_ARRAY
5285 && next_ref
->u
.ar
.type
== AR_FULL
5286 && next_ref
->next
== nullptr)
5293 /* Remove unneeded kind= argument from actual argument list when the
5294 result conversion is dealt with in a different place. */
5297 strip_kind_from_actual (gfc_actual_arglist
* actual
)
5299 for (gfc_actual_arglist
*a
= actual
; a
; a
= a
->next
)
5301 if (a
&& a
->name
&& strcmp (a
->name
, "kind") == 0)
5303 gfc_free_expr (a
->expr
);
5309 /* Emit code for minloc or maxloc intrinsic. There are many different cases
5310 we need to handle. For performance reasons we sometimes create two
5311 loops instead of one, where the second one is much simpler.
5312 Examples for minloc intrinsic:
5313 A: Result is scalar.
5314 1) Array mask is used and NaNs need to be supported:
5320 if (pos == 0) pos = S + (1 - from);
5321 if (a[S] <= limit) {
5323 pos = S + (1 - from);
5335 pos = S + (1 - from);
5340 2) NaNs need to be supported, but it is known at compile time or cheaply
5341 at runtime whether array is nonempty or not:
5346 if (a[S] <= limit) {
5348 pos = S + (1 - from);
5353 if (from <= to) pos = 1;
5359 pos = S + (1 - from);
5364 3) NaNs aren't supported, array mask is used:
5365 limit = infinities_supported ? Infinity : huge (limit);
5371 pos = S + (1 - from);
5382 pos = S + (1 - from);
5387 4) Same without array mask:
5388 limit = infinities_supported ? Infinity : huge (limit);
5389 pos = (from <= to) ? 1 : 0;
5394 pos = S + (1 - from);
5398 B: Array result, non-CHARACTER type, DIM absent
5399 Generate similar code as in the scalar case, using a collection of
5400 variables (one per dimension) instead of a single variable as result.
5401 Picking only cases 1) and 4) with ARRAY of rank 2, the generated code
5403 1) Array mask is used and NaNs need to be supported:
5408 second_loop_entry = false;
5414 pos0 = S0 + (1 - from0);
5415 pos1 = S1 + (1 - from1);
5417 if (a[S1][S0] <= limit) {
5419 pos0 = S0 + (1 - from0);
5420 pos1 = S1 + (1 - from1);
5421 second_loop_entry = true;
5431 S1 = second_loop_entry ? S1 : from1;
5433 S0 = second_loop_entry ? S0 : from0;
5436 if (a[S1][S0] < limit) {
5438 pos0 = S + (1 - from0);
5439 pos1 = S + (1 - from1);
5441 second_loop_entry = false;
5447 result = { pos0, pos1 };
5449 4) NANs aren't supported, no array mask.
5450 limit = infinities_supported ? Infinity : huge (limit);
5451 pos0 = (from0 <= to0 && from1 <= to1) ? 1 : 0;
5452 pos1 = (from0 <= to0 && from1 <= to1) ? 1 : 0;
5457 if (a[S1][S0] < limit) {
5459 pos0 = S + (1 - from0);
5460 pos1 = S + (1 - from1);
5466 result = { pos0, pos1 };
5467 C: Otherwise, a call is generated.
5468 For 2) and 4), if mask is scalar, this all goes into a conditional,
5469 setting pos = 0; in the else branch.
5471 Since we now also support the BACK argument, instead of using
5472 if (a[S] < limit), we now use
5475 cond = a[S] <= limit;
5477 cond = a[S] < limit;
5481 The optimizer is smart enough to move the condition out of the loop.
5482 They are now marked as unlikely too for further speedup. */
5485 gfc_conv_intrinsic_minmaxloc (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
5489 stmtblock_t ifblock
;
5490 stmtblock_t elseblock
;
5497 tree offset
[GFC_MAX_DIMENSIONS
];
5502 gfc_loopinfo loop
, *ploop
;
5503 gfc_actual_arglist
*actual
, *array_arg
, *dim_arg
, *mask_arg
, *kind_arg
;
5504 gfc_actual_arglist
*back_arg
;
5505 gfc_ss
*arrayss
= nullptr;
5506 gfc_ss
*maskss
= nullptr;
5507 gfc_ss
*orig_ss
= nullptr;
5512 gfc_expr
*arrayexpr
;
5516 tree pos
[GFC_MAX_DIMENSIONS
];
5517 tree idx
[GFC_MAX_DIMENSIONS
];
5518 tree result_var
= NULL_TREE
;
5522 actual
= expr
->value
.function
.actual
;
5524 dim_arg
= array_arg
->next
;
5525 mask_arg
= dim_arg
->next
;
5526 kind_arg
= mask_arg
->next
;
5527 back_arg
= kind_arg
->next
;
5529 bool dim_present
= dim_arg
->expr
!= nullptr;
5530 bool nested_loop
= dim_present
&& expr
->rank
> 0;
5532 /* The last argument, BACK, is passed by value. Ensure that
5533 by setting its name to %VAL. */
5534 for (gfc_actual_arglist
*a
= actual
; a
; a
= a
->next
)
5536 if (a
->next
== NULL
)
5542 if (se
->ss
->info
->useflags
)
5544 if (!dim_present
|| !gfc_inline_intrinsic_function_p (expr
))
5546 /* The code generating and initializing the result array has been
5547 generated already before the scalarization loop, either with a
5548 library function call or with inline code; now we can just use
5550 gfc_conv_tmp_array_ref (se
);
5554 else if (!gfc_inline_intrinsic_function_p (expr
))
5556 gfc_conv_intrinsic_funcall (se
, expr
);
5561 arrayexpr
= actual
->expr
;
5563 /* Special case for character maxloc. Remove unneeded actual
5564 arguments, then call a library function. */
5566 if (arrayexpr
->ts
.type
== BT_CHARACTER
)
5568 gcc_assert (expr
->rank
== 0);
5570 gfc_actual_arglist
*a
= actual
;
5571 strip_kind_from_actual (a
);
5574 if (a
->name
&& strcmp (a
->name
, "dim") == 0)
5576 gfc_free_expr (a
->expr
);
5581 gfc_conv_intrinsic_funcall (se
, expr
);
5585 type
= gfc_typenode_for_spec (&expr
->ts
);
5587 if (expr
->rank
> 0 && !dim_present
)
5590 memset (&as
, 0, sizeof (as
));
5593 as
.lower
[0] = gfc_get_int_expr (gfc_index_integer_kind
,
5596 as
.upper
[0] = gfc_get_int_expr (gfc_index_integer_kind
,
5600 tree array
= gfc_get_nodesc_array_type (type
, &as
, PACKED_STATIC
, true);
5602 result_var
= gfc_create_var (array
, "loc_result");
5605 const int reduction_dimensions
= dim_present
? 1 : arrayexpr
->rank
;
5607 /* Initialize the result. */
5608 for (int i
= 0; i
< reduction_dimensions
; i
++)
5610 pos
[i
] = gfc_create_var (gfc_array_index_type
,
5611 gfc_get_string ("pos%d", i
));
5612 offset
[i
] = gfc_create_var (gfc_array_index_type
,
5613 gfc_get_string ("offset%d", i
));
5614 idx
[i
] = gfc_create_var (gfc_array_index_type
,
5615 gfc_get_string ("idx%d", i
));
5618 maskexpr
= mask_arg
->expr
;
5619 optional_mask
= maskexpr
&& maskexpr
->expr_type
== EXPR_VARIABLE
5620 && maskexpr
->symtree
->n
.sym
->attr
.dummy
5621 && maskexpr
->symtree
->n
.sym
->attr
.optional
;
5622 backexpr
= back_arg
->expr
;
5624 gfc_init_se (&backse
, nested_loop
? se
: nullptr);
5625 if (backexpr
== nullptr)
5626 back
= logical_false_node
;
5627 else if (maybe_absent_optional_variable (backexpr
))
5629 /* This should have been checked already by
5630 maybe_absent_optional_variable. */
5631 gcc_checking_assert (backexpr
->expr_type
== EXPR_VARIABLE
);
5633 gfc_conv_expr (&backse
, backexpr
);
5634 tree present
= gfc_conv_expr_present (backexpr
->symtree
->n
.sym
, false);
5635 back
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
5636 logical_type_node
, present
, backse
.expr
);
5640 gfc_conv_expr (&backse
, backexpr
);
5643 gfc_add_block_to_block (&se
->pre
, &backse
.pre
);
5644 back
= gfc_evaluate_now_loc (input_location
, back
, &se
->pre
);
5645 gfc_add_block_to_block (&se
->pre
, &backse
.post
);
5649 gfc_init_se (&nested_se
, se
);
5650 base_se
= &nested_se
;
5654 /* Walk the arguments. */
5655 arrayss
= gfc_walk_expr (arrayexpr
);
5656 gcc_assert (arrayss
!= gfc_ss_terminator
);
5658 if (maskexpr
&& maskexpr
->rank
!= 0)
5660 maskss
= gfc_walk_expr (maskexpr
);
5661 gcc_assert (maskss
!= gfc_ss_terminator
);
5668 if (!(maskexpr
&& maskexpr
->rank
> 0))
5671 bool reduction_size_known
;
5676 if (dim_arg
->expr
->expr_type
== EXPR_CONSTANT
)
5677 reduction_dim
= mpz_get_si (dim_arg
->expr
->value
.integer
) - 1;
5678 else if (arrayexpr
->rank
== 1)
5682 reduction_size_known
= gfc_array_dimen_size (arrayexpr
, reduction_dim
,
5686 reduction_size_known
= gfc_array_size (arrayexpr
, &asize
);
5688 if (reduction_size_known
)
5690 nonempty
= gfc_conv_mpz_to_tree (asize
, gfc_index_integer_kind
);
5692 nonempty
= fold_build2_loc (input_location
, GT_EXPR
,
5693 logical_type_node
, nonempty
,
5694 gfc_index_zero_node
);
5699 limit
= gfc_create_var (gfc_typenode_for_spec (&arrayexpr
->ts
), "limit");
5700 switch (arrayexpr
->ts
.type
)
5703 tmp
= gfc_build_inf_or_huge (TREE_TYPE (limit
), arrayexpr
->ts
.kind
);
5707 n
= gfc_validate_kind (arrayexpr
->ts
.type
, arrayexpr
->ts
.kind
, false);
5708 tmp
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
,
5709 arrayexpr
->ts
.kind
);
5713 /* For MAXVAL, the minimum is zero, for MINVAL it is HUGE(). */
5716 tmp
= gfc_get_unsigned_type (arrayexpr
->ts
.kind
);
5717 tmp
= build_int_cst (tmp
, 0);
5721 n
= gfc_validate_kind (arrayexpr
->ts
.type
, arrayexpr
->ts
.kind
, false);
5722 tmp
= gfc_conv_mpz_unsigned_to_tree (gfc_unsigned_kinds
[n
].huge
,
5731 /* We start with the most negative possible value for MAXLOC, and the most
5732 positive possible value for MINLOC. The most negative possible value is
5733 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5734 possible value is HUGE in both cases. BT_UNSIGNED has already been dealt
5736 if (op
== GT_EXPR
&& expr
->ts
.type
!= BT_UNSIGNED
)
5737 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (tmp
), tmp
);
5738 if (op
== GT_EXPR
&& arrayexpr
->ts
.type
== BT_INTEGER
)
5739 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (tmp
), tmp
,
5740 build_int_cst (TREE_TYPE (tmp
), 1));
5742 gfc_add_modify (&se
->pre
, limit
, tmp
);
5744 /* If we are in a case where we generate two sets of loops, the second one
5745 should continue where the first stopped instead of restarting from the
5746 beginning. So nested loops in the second set should have a partial range
5747 on the first iteration, but they should start from the beginning and span
5748 their full range on the following iterations. So we use conditionals in
5749 the loops lower bounds, and use the following variable in those
5750 conditionals to decide whether to use the original loop bound or to use
5751 the index at which the loop from the first set stopped. */
5752 tree second_loop_entry
= gfc_create_var (logical_type_node
,
5753 "second_loop_entry");
5754 gfc_add_modify (&se
->pre
, second_loop_entry
, logical_false_node
);
5758 ploop
= enter_nested_loop (&nested_se
);
5759 orig_ss
= nested_se
.ss
;
5760 ploop
->temp_dim
= 1;
5764 /* Initialize the scalarizer. */
5765 gfc_init_loopinfo (&loop
);
5767 /* We add the mask first because the number of iterations is taken
5768 from the last ss, and this breaks if an absent optional argument
5769 is used for mask. */
5772 gfc_add_ss_to_loop (&loop
, maskss
);
5774 gfc_add_ss_to_loop (&loop
, arrayss
);
5776 /* Initialize the loop. */
5777 gfc_conv_ss_startstride (&loop
);
5779 /* The code generated can have more than one loop in sequence (see the
5780 comment at the function header). This doesn't work well with the
5781 scalarizer, which changes arrays' offset when the scalarization loops
5782 are generated (see gfc_trans_preloop_setup). Fortunately, we can use
5783 the scalarizer temporary code to handle multiple loops. Thus, we set
5784 temp_dim here, we call gfc_mark_ss_chain_used with flag=3 later, and
5785 we use gfc_trans_scalarized_loop_boundary even later to restore
5787 loop
.temp_dim
= loop
.dimen
;
5788 gfc_conv_loop_setup (&loop
, &expr
->where
);
5793 gcc_assert (reduction_dimensions
== ploop
->dimen
);
5795 if (nonempty
== NULL
&& !(maskexpr
&& maskexpr
->rank
> 0))
5797 nonempty
= logical_true_node
;
5799 for (int i
= 0; i
< ploop
->dimen
; i
++)
5801 if (!(ploop
->from
[i
] && ploop
->to
[i
]))
5807 tree tmp
= fold_build2_loc (input_location
, LE_EXPR
,
5808 logical_type_node
, ploop
->from
[i
],
5811 nonempty
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
5812 logical_type_node
, nonempty
, tmp
);
5818 /* Initialize the position to zero, following Fortran 2003. We are free
5819 to do this because Fortran 95 allows the result of an entirely false
5820 mask to be processor dependent. If we know at compile time the array
5821 is non-empty and no MASK is used, we can initialize to 1 to simplify
5823 if (nonempty
!= NULL
&& !HONOR_NANS (DECL_MODE (limit
)))
5825 tree init
= fold_build3_loc (input_location
, COND_EXPR
,
5826 gfc_array_index_type
, nonempty
,
5828 gfc_index_zero_node
);
5829 for (int i
= 0; i
< ploop
->dimen
; i
++)
5830 gfc_add_modify (&ploop
->pre
, pos
[i
], init
);
5834 for (int i
= 0; i
< ploop
->dimen
; i
++)
5835 gfc_add_modify (&ploop
->pre
, pos
[i
], gfc_index_zero_node
);
5836 lab1
= gfc_build_label_decl (NULL_TREE
);
5837 TREE_USED (lab1
) = 1;
5838 lab2
= gfc_build_label_decl (NULL_TREE
);
5839 TREE_USED (lab2
) = 1;
5842 /* An offset must be added to the loop
5843 counter to obtain the required position. */
5844 for (int i
= 0; i
< ploop
->dimen
; i
++)
5846 gcc_assert (ploop
->from
[i
]);
5848 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
5849 gfc_index_one_node
, ploop
->from
[i
]);
5850 gfc_add_modify (&ploop
->pre
, offset
[i
], tmp
);
5855 gfc_mark_ss_chain_used (arrayss
, lab1
? 3 : 1);
5857 gfc_mark_ss_chain_used (maskss
, lab1
? 3 : 1);
5860 /* Generate the loop body. */
5861 gfc_start_scalarized_body (ploop
, &body
);
5863 /* If we have a mask, only check this element if the mask is set. */
5864 if (maskexpr
&& maskexpr
->rank
> 0)
5866 gfc_init_se (&maskse
, base_se
);
5867 gfc_copy_loopinfo_to_se (&maskse
, ploop
);
5870 gfc_conv_expr_val (&maskse
, maskexpr
);
5871 gfc_add_block_to_block (&body
, &maskse
.pre
);
5873 gfc_start_block (&block
);
5876 gfc_init_block (&block
);
5878 /* Compare with the current limit. */
5879 gfc_init_se (&arrayse
, base_se
);
5880 gfc_copy_loopinfo_to_se (&arrayse
, ploop
);
5882 arrayse
.ss
= arrayss
;
5883 gfc_conv_expr_val (&arrayse
, arrayexpr
);
5884 gfc_add_block_to_block (&block
, &arrayse
.pre
);
5886 /* We do the following if this is a more extreme value. */
5887 gfc_start_block (&ifblock
);
5889 /* Assign the value to the limit... */
5890 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
5892 if (nonempty
== NULL
&& HONOR_NANS (DECL_MODE (limit
)))
5894 stmtblock_t ifblock2
;
5897 gfc_start_block (&ifblock2
);
5898 for (int i
= 0; i
< ploop
->dimen
; i
++)
5900 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
[i
]),
5901 ploop
->loopvar
[i
], offset
[i
]);
5902 gfc_add_modify (&ifblock2
, pos
[i
], tmp
);
5904 ifbody2
= gfc_finish_block (&ifblock2
);
5906 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
5907 pos
[0], gfc_index_zero_node
);
5908 tmp
= build3_v (COND_EXPR
, cond
, ifbody2
,
5909 build_empty_stmt (input_location
));
5910 gfc_add_expr_to_block (&block
, tmp
);
5913 for (int i
= 0; i
< ploop
->dimen
; i
++)
5915 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
[i
]),
5916 ploop
->loopvar
[i
], offset
[i
]);
5917 gfc_add_modify (&ifblock
, pos
[i
], tmp
);
5918 gfc_add_modify (&ifblock
, idx
[i
], ploop
->loopvar
[i
]);
5921 gfc_add_modify (&ifblock
, second_loop_entry
, logical_true_node
);
5924 gfc_add_expr_to_block (&ifblock
, build1_v (GOTO_EXPR
, lab1
));
5926 ifbody
= gfc_finish_block (&ifblock
);
5928 if (!lab1
|| HONOR_NANS (DECL_MODE (limit
)))
5931 cond
= fold_build2_loc (input_location
,
5932 op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
5933 logical_type_node
, arrayse
.expr
, limit
);
5936 tree ifbody2
, elsebody2
;
5938 /* We switch to > or >= depending on the value of the BACK argument. */
5939 cond
= gfc_create_var (logical_type_node
, "cond");
5941 gfc_start_block (&ifblock
);
5942 b_if
= fold_build2_loc (input_location
, op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
5943 logical_type_node
, arrayse
.expr
, limit
);
5945 gfc_add_modify (&ifblock
, cond
, b_if
);
5946 ifbody2
= gfc_finish_block (&ifblock
);
5948 gfc_start_block (&elseblock
);
5949 b_else
= fold_build2_loc (input_location
, op
, logical_type_node
,
5950 arrayse
.expr
, limit
);
5952 gfc_add_modify (&elseblock
, cond
, b_else
);
5953 elsebody2
= gfc_finish_block (&elseblock
);
5955 tmp
= fold_build3_loc (input_location
, COND_EXPR
, logical_type_node
,
5956 back
, ifbody2
, elsebody2
);
5958 gfc_add_expr_to_block (&block
, tmp
);
5961 cond
= gfc_unlikely (cond
, PRED_BUILTIN_EXPECT
);
5962 ifbody
= build3_v (COND_EXPR
, cond
, ifbody
,
5963 build_empty_stmt (input_location
));
5965 gfc_add_expr_to_block (&block
, ifbody
);
5967 if (maskexpr
&& maskexpr
->rank
> 0)
5969 /* We enclose the above in if (mask) {...}. If the mask is an
5970 optional argument, generate IF (.NOT. PRESENT(MASK)
5974 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
5975 tmp
= gfc_finish_block (&block
);
5976 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
5977 build_empty_stmt (input_location
));
5980 tmp
= gfc_finish_block (&block
);
5981 gfc_add_expr_to_block (&body
, tmp
);
5985 for (int i
= 0; i
< ploop
->dimen
; i
++)
5986 ploop
->from
[i
] = fold_build3_loc (input_location
, COND_EXPR
,
5987 TREE_TYPE (ploop
->from
[i
]),
5988 second_loop_entry
, idx
[i
],
5991 gfc_trans_scalarized_loop_boundary (ploop
, &body
);
5995 /* The first loop already advanced the parent se'ss chain, so clear
5996 the parent now to avoid doing it a second time, making the chain
5998 nested_se
.parent
= nullptr;
5999 nested_se
.ss
= orig_ss
;
6002 stmtblock_t
* const outer_block
= &ploop
->code
[ploop
->dimen
- 1];
6004 if (HONOR_NANS (DECL_MODE (limit
)))
6006 if (nonempty
!= NULL
)
6008 stmtblock_t init_block
;
6009 gfc_init_block (&init_block
);
6011 for (int i
= 0; i
< ploop
->dimen
; i
++)
6012 gfc_add_modify (&init_block
, pos
[i
], gfc_index_one_node
);
6014 tree ifbody
= gfc_finish_block (&init_block
);
6015 tmp
= build3_v (COND_EXPR
, nonempty
, ifbody
,
6016 build_empty_stmt (input_location
));
6017 gfc_add_expr_to_block (outer_block
, tmp
);
6021 gfc_add_expr_to_block (outer_block
, build1_v (GOTO_EXPR
, lab2
));
6022 gfc_add_expr_to_block (outer_block
, build1_v (LABEL_EXPR
, lab1
));
6024 /* If we have a mask, only check this element if the mask is set. */
6025 if (maskexpr
&& maskexpr
->rank
> 0)
6027 gfc_init_se (&maskse
, base_se
);
6028 gfc_copy_loopinfo_to_se (&maskse
, ploop
);
6031 gfc_conv_expr_val (&maskse
, maskexpr
);
6032 gfc_add_block_to_block (&body
, &maskse
.pre
);
6034 gfc_start_block (&block
);
6037 gfc_init_block (&block
);
6039 /* Compare with the current limit. */
6040 gfc_init_se (&arrayse
, base_se
);
6041 gfc_copy_loopinfo_to_se (&arrayse
, ploop
);
6043 arrayse
.ss
= arrayss
;
6044 gfc_conv_expr_val (&arrayse
, arrayexpr
);
6045 gfc_add_block_to_block (&block
, &arrayse
.pre
);
6047 /* We do the following if this is a more extreme value. */
6048 gfc_start_block (&ifblock
);
6050 /* Assign the value to the limit... */
6051 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
6053 for (int i
= 0; i
< ploop
->dimen
; i
++)
6055 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
[i
]),
6056 ploop
->loopvar
[i
], offset
[i
]);
6057 gfc_add_modify (&ifblock
, pos
[i
], tmp
);
6060 ifbody
= gfc_finish_block (&ifblock
);
6062 /* We switch to > or >= depending on the value of the BACK argument. */
6064 tree ifbody2
, elsebody2
;
6066 cond
= gfc_create_var (logical_type_node
, "cond");
6068 gfc_start_block (&ifblock
);
6069 b_if
= fold_build2_loc (input_location
, op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
6070 logical_type_node
, arrayse
.expr
, limit
);
6072 gfc_add_modify (&ifblock
, cond
, b_if
);
6073 ifbody2
= gfc_finish_block (&ifblock
);
6075 gfc_start_block (&elseblock
);
6076 b_else
= fold_build2_loc (input_location
, op
, logical_type_node
,
6077 arrayse
.expr
, limit
);
6079 gfc_add_modify (&elseblock
, cond
, b_else
);
6080 elsebody2
= gfc_finish_block (&elseblock
);
6082 tmp
= fold_build3_loc (input_location
, COND_EXPR
, logical_type_node
,
6083 back
, ifbody2
, elsebody2
);
6086 gfc_add_expr_to_block (&block
, tmp
);
6087 cond
= gfc_unlikely (cond
, PRED_BUILTIN_EXPECT
);
6088 tmp
= build3_v (COND_EXPR
, cond
, ifbody
,
6089 build_empty_stmt (input_location
));
6091 gfc_add_expr_to_block (&block
, tmp
);
6093 if (maskexpr
&& maskexpr
->rank
> 0)
6095 /* We enclose the above in if (mask) {...}. If the mask is
6096 an optional argument, generate IF (.NOT. PRESENT(MASK)
6100 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6101 tmp
= gfc_finish_block (&block
);
6102 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
6103 build_empty_stmt (input_location
));
6106 tmp
= gfc_finish_block (&block
);
6108 gfc_add_expr_to_block (&body
, tmp
);
6109 gfc_add_modify (&body
, second_loop_entry
, logical_false_node
);
6112 gfc_trans_scalarizing_loops (ploop
, &body
);
6115 gfc_add_expr_to_block (&ploop
->pre
, build1_v (LABEL_EXPR
, lab2
));
6117 /* For a scalar mask, enclose the loop in an if statement. */
6118 if (maskexpr
&& maskexpr
->rank
== 0)
6122 gfc_init_se (&maskse
, nested_loop
? se
: nullptr);
6123 gfc_conv_expr_val (&maskse
, maskexpr
);
6124 gfc_add_block_to_block (&se
->pre
, &maskse
.pre
);
6125 gfc_init_block (&block
);
6126 gfc_add_block_to_block (&block
, &ploop
->pre
);
6127 gfc_add_block_to_block (&block
, &ploop
->post
);
6128 tmp
= gfc_finish_block (&block
);
6130 /* For the else part of the scalar mask, just initialize
6131 the pos variable the same way as above. */
6133 gfc_init_block (&elseblock
);
6134 for (int i
= 0; i
< ploop
->dimen
; i
++)
6135 gfc_add_modify (&elseblock
, pos
[i
], gfc_index_zero_node
);
6136 elsetmp
= gfc_finish_block (&elseblock
);
6137 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6138 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
, elsetmp
);
6139 gfc_add_expr_to_block (&block
, tmp
);
6140 gfc_add_block_to_block (&se
->pre
, &block
);
6144 gfc_add_block_to_block (&se
->pre
, &ploop
->pre
);
6145 gfc_add_block_to_block (&se
->pre
, &ploop
->post
);
6149 gfc_cleanup_loop (&loop
);
6153 for (int i
= 0; i
< arrayexpr
->rank
; i
++)
6155 tree res_idx
= build_int_cst (gfc_array_index_type
, i
);
6156 tree res_arr_ref
= gfc_build_array_ref (result_var
, res_idx
,
6159 tree value
= convert (type
, pos
[i
]);
6160 gfc_add_modify (&se
->pre
, res_arr_ref
, value
);
6163 se
->expr
= result_var
;
6166 se
->expr
= convert (type
, pos
[0]);
6169 /* Emit code for findloc. */
6172 gfc_conv_intrinsic_findloc (gfc_se
*se
, gfc_expr
*expr
)
6174 gfc_actual_arglist
*array_arg
, *value_arg
, *dim_arg
, *mask_arg
,
6175 *kind_arg
, *back_arg
;
6176 gfc_expr
*value_expr
;
6181 stmtblock_t loopblock
;
6185 tree forward_branch
= NULL_TREE
;
6200 array_arg
= expr
->value
.function
.actual
;
6201 value_arg
= array_arg
->next
;
6202 dim_arg
= value_arg
->next
;
6203 mask_arg
= dim_arg
->next
;
6204 kind_arg
= mask_arg
->next
;
6205 back_arg
= kind_arg
->next
;
6207 /* Remove kind and set ikind. */
6210 ikind
= mpz_get_si (kind_arg
->expr
->value
.integer
);
6211 gfc_free_expr (kind_arg
->expr
);
6212 kind_arg
->expr
= NULL
;
6215 ikind
= gfc_default_integer_kind
;
6217 value_expr
= value_arg
->expr
;
6219 /* Unless it's a string, pass VALUE by value. */
6220 if (value_expr
->ts
.type
!= BT_CHARACTER
)
6221 value_arg
->name
= "%VAL";
6223 /* Pass BACK argument by value. */
6224 back_arg
->name
= "%VAL";
6226 /* Call the library if we have a character function or if
6228 if (se
->ss
|| array_arg
->expr
->ts
.type
== BT_CHARACTER
)
6230 se
->ignore_optional
= 1;
6231 if (expr
->rank
== 0)
6233 /* Remove dim argument. */
6234 gfc_free_expr (dim_arg
->expr
);
6235 dim_arg
->expr
= NULL
;
6237 gfc_conv_intrinsic_funcall (se
, expr
);
6241 type
= gfc_get_int_type (ikind
);
6243 /* Initialize the result. */
6244 resvar
= gfc_create_var (gfc_array_index_type
, "pos");
6245 gfc_add_modify (&se
->pre
, resvar
, build_int_cst (gfc_array_index_type
, 0));
6246 offset
= gfc_create_var (gfc_array_index_type
, "offset");
6248 maskexpr
= mask_arg
->expr
;
6249 optional_mask
= maskexpr
&& maskexpr
->expr_type
== EXPR_VARIABLE
6250 && maskexpr
->symtree
->n
.sym
->attr
.dummy
6251 && maskexpr
->symtree
->n
.sym
->attr
.optional
;
6253 /* Generate two loops, one for BACK=.true. and one for BACK=.false. */
6255 for (i
= 0 ; i
< 2; i
++)
6257 /* Walk the arguments. */
6258 arrayss
= gfc_walk_expr (array_arg
->expr
);
6259 gcc_assert (arrayss
!= gfc_ss_terminator
);
6261 if (maskexpr
&& maskexpr
->rank
!= 0)
6263 maskss
= gfc_walk_expr (maskexpr
);
6264 gcc_assert (maskss
!= gfc_ss_terminator
);
6269 /* Initialize the scalarizer. */
6270 gfc_init_loopinfo (&loop
);
6271 exit_label
= gfc_build_label_decl (NULL_TREE
);
6272 TREE_USED (exit_label
) = 1;
6274 /* We add the mask first because the number of iterations is
6275 taken from the last ss, and this breaks if an absent
6276 optional argument is used for mask. */
6279 gfc_add_ss_to_loop (&loop
, maskss
);
6280 gfc_add_ss_to_loop (&loop
, arrayss
);
6282 /* Initialize the loop. */
6283 gfc_conv_ss_startstride (&loop
);
6284 gfc_conv_loop_setup (&loop
, &expr
->where
);
6286 /* Calculate the offset. */
6287 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
6288 gfc_index_one_node
, loop
.from
[0]);
6289 gfc_add_modify (&loop
.pre
, offset
, tmp
);
6291 gfc_mark_ss_chain_used (arrayss
, 1);
6293 gfc_mark_ss_chain_used (maskss
, 1);
6295 /* The first loop is for BACK=.true. */
6297 loop
.reverse
[0] = GFC_REVERSE_SET
;
6299 /* Generate the loop body. */
6300 gfc_start_scalarized_body (&loop
, &body
);
6302 /* If we have an array mask, only add the element if it is
6306 gfc_init_se (&maskse
, NULL
);
6307 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
6309 gfc_conv_expr_val (&maskse
, maskexpr
);
6310 gfc_add_block_to_block (&body
, &maskse
.pre
);
6313 /* If the condition matches then set the return value. */
6314 gfc_start_block (&block
);
6316 /* Add the offset. */
6317 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
6319 loop
.loopvar
[0], offset
);
6320 gfc_add_modify (&block
, resvar
, tmp
);
6321 /* And break out of the loop. */
6322 tmp
= build1_v (GOTO_EXPR
, exit_label
);
6323 gfc_add_expr_to_block (&block
, tmp
);
6325 found
= gfc_finish_block (&block
);
6327 /* Check this element. */
6328 gfc_init_se (&arrayse
, NULL
);
6329 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
6330 arrayse
.ss
= arrayss
;
6331 gfc_conv_expr_val (&arrayse
, array_arg
->expr
);
6332 gfc_add_block_to_block (&body
, &arrayse
.pre
);
6334 gfc_init_se (&valuese
, NULL
);
6335 gfc_conv_expr_val (&valuese
, value_arg
->expr
);
6336 gfc_add_block_to_block (&body
, &valuese
.pre
);
6338 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
6339 arrayse
.expr
, valuese
.expr
);
6341 tmp
= build3_v (COND_EXPR
, tmp
, found
, build_empty_stmt (input_location
));
6344 /* We enclose the above in if (mask) {...}. If the mask is
6345 an optional argument, generate IF (.NOT. PRESENT(MASK)
6349 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6350 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
6351 build_empty_stmt (input_location
));
6354 gfc_add_expr_to_block (&body
, tmp
);
6355 gfc_add_block_to_block (&body
, &arrayse
.post
);
6357 gfc_trans_scalarizing_loops (&loop
, &body
);
6359 /* Add the exit label. */
6360 tmp
= build1_v (LABEL_EXPR
, exit_label
);
6361 gfc_add_expr_to_block (&loop
.pre
, tmp
);
6362 gfc_start_block (&loopblock
);
6363 gfc_add_block_to_block (&loopblock
, &loop
.pre
);
6364 gfc_add_block_to_block (&loopblock
, &loop
.post
);
6366 forward_branch
= gfc_finish_block (&loopblock
);
6368 back_branch
= gfc_finish_block (&loopblock
);
6370 gfc_cleanup_loop (&loop
);
6373 /* Enclose the two loops in an IF statement. */
6375 gfc_init_se (&backse
, NULL
);
6376 gfc_conv_expr_val (&backse
, back_arg
->expr
);
6377 gfc_add_block_to_block (&se
->pre
, &backse
.pre
);
6378 tmp
= build3_v (COND_EXPR
, backse
.expr
, forward_branch
, back_branch
);
6380 /* For a scalar mask, enclose the loop in an if statement. */
6381 if (maskexpr
&& maskss
== NULL
)
6386 gfc_init_se (&maskse
, NULL
);
6387 gfc_conv_expr_val (&maskse
, maskexpr
);
6388 gfc_init_block (&block
);
6389 gfc_add_expr_to_block (&block
, maskse
.expr
);
6390 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6391 if_stmt
= build3_v (COND_EXPR
, ifmask
, tmp
,
6392 build_empty_stmt (input_location
));
6393 gfc_add_expr_to_block (&block
, if_stmt
);
6394 tmp
= gfc_finish_block (&block
);
6397 gfc_add_expr_to_block (&se
->pre
, tmp
);
6398 se
->expr
= convert (type
, resvar
);
6402 /* Emit code for minval or maxval intrinsic. There are many different cases
6403 we need to handle. For performance reasons we sometimes create two
6404 loops instead of one, where the second one is much simpler.
6405 Examples for minval intrinsic:
6406 1) Result is an array, a call is generated
6407 2) Array mask is used and NaNs need to be supported, rank 1:
6414 if (a[S] <= limit) {
6423 limit = nonempty ? NaN : huge (limit);
6425 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
6426 3) NaNs need to be supported, but it is known at compile time or cheaply
6427 at runtime whether array is nonempty or not, rank 1:
6431 if (a[S] <= limit) {
6439 limit = (from <= to) ? NaN : huge (limit);
6441 while (S <= to) { limit = min (a[S], limit); S++; }
6442 4) Array mask is used and NaNs need to be supported, rank > 1:
6451 if (fast) limit = min (a[S1][S2], limit);
6454 if (a[S1][S2] <= limit) {
6465 limit = nonempty ? NaN : huge (limit);
6466 5) NaNs need to be supported, but it is known at compile time or cheaply
6467 at runtime whether array is nonempty or not, rank > 1:
6474 if (fast) limit = min (a[S1][S2], limit);
6476 if (a[S1][S2] <= limit) {
6486 limit = (nonempty_array) ? NaN : huge (limit);
6487 6) NaNs aren't supported, but infinities are. Array mask is used:
6492 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
6495 limit = nonempty ? limit : huge (limit);
6496 7) Same without array mask:
6499 while (S <= to) { limit = min (a[S], limit); S++; }
6500 limit = (from <= to) ? limit : huge (limit);
6501 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
6502 limit = huge (limit);
6504 while (S <= to) { limit = min (a[S], limit); S++); }
6506 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
6507 with array mask instead).
6508 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
6509 setting limit = huge (limit); in the else branch. */
6512 gfc_conv_intrinsic_minmaxval (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
6522 tree huge_cst
= NULL
, nan_cst
= NULL
;
6524 stmtblock_t block
, block2
;
6526 gfc_actual_arglist
*actual
;
6531 gfc_expr
*arrayexpr
;
6538 gfc_conv_intrinsic_funcall (se
, expr
);
6542 actual
= expr
->value
.function
.actual
;
6543 arrayexpr
= actual
->expr
;
6545 if (arrayexpr
->ts
.type
== BT_CHARACTER
)
6547 gfc_actual_arglist
*dim
= actual
->next
;
6548 if (expr
->rank
== 0 && dim
->expr
!= 0)
6550 gfc_free_expr (dim
->expr
);
6553 gfc_conv_intrinsic_funcall (se
, expr
);
6557 type
= gfc_typenode_for_spec (&expr
->ts
);
6558 /* Initialize the result. */
6559 limit
= gfc_create_var (type
, "limit");
6560 n
= gfc_validate_kind (expr
->ts
.type
, expr
->ts
.kind
, false);
6561 switch (expr
->ts
.type
)
6564 huge_cst
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[n
].huge
,
6566 if (HONOR_INFINITIES (DECL_MODE (limit
)))
6568 REAL_VALUE_TYPE real
;
6570 tmp
= build_real (type
, real
);
6574 if (HONOR_NANS (DECL_MODE (limit
)))
6575 nan_cst
= gfc_build_nan (type
, "");
6579 tmp
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
, expr
->ts
.kind
);
6583 /* For MAXVAL, the minimum is zero, for MINVAL it is HUGE(). */
6585 tmp
= build_int_cst (type
, 0);
6587 tmp
= gfc_conv_mpz_unsigned_to_tree (gfc_unsigned_kinds
[n
].huge
,
6595 /* We start with the most negative possible value for MAXVAL, and the most
6596 positive possible value for MINVAL. The most negative possible value is
6597 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
6598 possible value is HUGE in both cases. BT_UNSIGNED has already been dealt
6600 if (op
== GT_EXPR
&& expr
->ts
.type
!= BT_UNSIGNED
)
6602 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (tmp
), tmp
);
6604 huge_cst
= fold_build1_loc (input_location
, NEGATE_EXPR
,
6605 TREE_TYPE (huge_cst
), huge_cst
);
6608 if (op
== GT_EXPR
&& expr
->ts
.type
== BT_INTEGER
)
6609 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (tmp
),
6610 tmp
, build_int_cst (type
, 1));
6612 gfc_add_modify (&se
->pre
, limit
, tmp
);
6614 /* Walk the arguments. */
6615 arrayss
= gfc_walk_expr (arrayexpr
);
6616 gcc_assert (arrayss
!= gfc_ss_terminator
);
6618 actual
= actual
->next
->next
;
6619 gcc_assert (actual
);
6620 maskexpr
= actual
->expr
;
6621 optional_mask
= maskexpr
&& maskexpr
->expr_type
== EXPR_VARIABLE
6622 && maskexpr
->symtree
->n
.sym
->attr
.dummy
6623 && maskexpr
->symtree
->n
.sym
->attr
.optional
;
6625 if (maskexpr
&& maskexpr
->rank
!= 0)
6627 maskss
= gfc_walk_expr (maskexpr
);
6628 gcc_assert (maskss
!= gfc_ss_terminator
);
6633 if (gfc_array_size (arrayexpr
, &asize
))
6635 nonempty
= gfc_conv_mpz_to_tree (asize
, gfc_index_integer_kind
);
6637 nonempty
= fold_build2_loc (input_location
, GT_EXPR
,
6638 logical_type_node
, nonempty
,
6639 gfc_index_zero_node
);
6644 /* Initialize the scalarizer. */
6645 gfc_init_loopinfo (&loop
);
6647 /* We add the mask first because the number of iterations is taken
6648 from the last ss, and this breaks if an absent optional argument
6649 is used for mask. */
6652 gfc_add_ss_to_loop (&loop
, maskss
);
6653 gfc_add_ss_to_loop (&loop
, arrayss
);
6655 /* Initialize the loop. */
6656 gfc_conv_ss_startstride (&loop
);
6658 /* The code generated can have more than one loop in sequence (see the
6659 comment at the function header). This doesn't work well with the
6660 scalarizer, which changes arrays' offset when the scalarization loops
6661 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
6662 are currently inlined in the scalar case only. As there is no dependency
6663 to care about in that case, there is no temporary, so that we can use the
6664 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
6665 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
6666 gfc_trans_scalarized_loop_boundary even later to restore offset.
6667 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
6668 should eventually go away. We could either create two loops properly,
6669 or find another way to save/restore the array offsets between the two
6670 loops (without conflicting with temporary management), or use a single
6671 loop minmaxval implementation. See PR 31067. */
6672 loop
.temp_dim
= loop
.dimen
;
6673 gfc_conv_loop_setup (&loop
, &expr
->where
);
6675 if (nonempty
== NULL
&& maskss
== NULL
6676 && loop
.dimen
== 1 && loop
.from
[0] && loop
.to
[0])
6677 nonempty
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
,
6678 loop
.from
[0], loop
.to
[0]);
6679 nonempty_var
= NULL
;
6680 if (nonempty
== NULL
6681 && (HONOR_INFINITIES (DECL_MODE (limit
))
6682 || HONOR_NANS (DECL_MODE (limit
))))
6684 nonempty_var
= gfc_create_var (logical_type_node
, "nonempty");
6685 gfc_add_modify (&se
->pre
, nonempty_var
, logical_false_node
);
6686 nonempty
= nonempty_var
;
6690 if (HONOR_NANS (DECL_MODE (limit
)))
6692 if (loop
.dimen
== 1)
6694 lab
= gfc_build_label_decl (NULL_TREE
);
6695 TREE_USED (lab
) = 1;
6699 fast
= gfc_create_var (logical_type_node
, "fast");
6700 gfc_add_modify (&se
->pre
, fast
, logical_false_node
);
6704 gfc_mark_ss_chain_used (arrayss
, lab
? 3 : 1);
6706 gfc_mark_ss_chain_used (maskss
, lab
? 3 : 1);
6707 /* Generate the loop body. */
6708 gfc_start_scalarized_body (&loop
, &body
);
6710 /* If we have a mask, only add this element if the mask is set. */
6713 gfc_init_se (&maskse
, NULL
);
6714 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
6716 gfc_conv_expr_val (&maskse
, maskexpr
);
6717 gfc_add_block_to_block (&body
, &maskse
.pre
);
6719 gfc_start_block (&block
);
6722 gfc_init_block (&block
);
6724 /* Compare with the current limit. */
6725 gfc_init_se (&arrayse
, NULL
);
6726 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
6727 arrayse
.ss
= arrayss
;
6728 gfc_conv_expr_val (&arrayse
, arrayexpr
);
6729 arrayse
.expr
= gfc_evaluate_now (arrayse
.expr
, &arrayse
.pre
);
6730 gfc_add_block_to_block (&block
, &arrayse
.pre
);
6732 gfc_init_block (&block2
);
6735 gfc_add_modify (&block2
, nonempty_var
, logical_true_node
);
6737 if (HONOR_NANS (DECL_MODE (limit
)))
6739 tmp
= fold_build2_loc (input_location
, op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
6740 logical_type_node
, arrayse
.expr
, limit
);
6743 stmtblock_t ifblock
;
6745 inc_loop
= fold_build2_loc (input_location
, PLUS_EXPR
,
6746 TREE_TYPE (loop
.loopvar
[0]),
6747 loop
.loopvar
[0], gfc_index_one_node
);
6748 gfc_init_block (&ifblock
);
6749 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
6750 gfc_add_modify (&ifblock
, loop
.loopvar
[0], inc_loop
);
6751 gfc_add_expr_to_block (&ifblock
, build1_v (GOTO_EXPR
, lab
));
6752 ifbody
= gfc_finish_block (&ifblock
);
6756 stmtblock_t ifblock
;
6758 gfc_init_block (&ifblock
);
6759 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
6760 gfc_add_modify (&ifblock
, fast
, logical_true_node
);
6761 ifbody
= gfc_finish_block (&ifblock
);
6763 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
6764 build_empty_stmt (input_location
));
6765 gfc_add_expr_to_block (&block2
, tmp
);
6769 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6771 tmp
= fold_build2_loc (input_location
,
6772 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
6773 type
, arrayse
.expr
, limit
);
6774 gfc_add_modify (&block2
, limit
, tmp
);
6779 tree elsebody
= gfc_finish_block (&block2
);
6781 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6783 if (HONOR_NANS (DECL_MODE (limit
)))
6785 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
,
6786 arrayse
.expr
, limit
);
6787 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
6788 ifbody
= build3_v (COND_EXPR
, tmp
, ifbody
,
6789 build_empty_stmt (input_location
));
6793 tmp
= fold_build2_loc (input_location
,
6794 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
6795 type
, arrayse
.expr
, limit
);
6796 ifbody
= build2_v (MODIFY_EXPR
, limit
, tmp
);
6798 tmp
= build3_v (COND_EXPR
, fast
, ifbody
, elsebody
);
6799 gfc_add_expr_to_block (&block
, tmp
);
6802 gfc_add_block_to_block (&block
, &block2
);
6804 gfc_add_block_to_block (&block
, &arrayse
.post
);
6806 tmp
= gfc_finish_block (&block
);
6809 /* We enclose the above in if (mask) {...}. If the mask is an
6810 optional argument, generate IF (.NOT. PRESENT(MASK)
6813 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6814 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
6815 build_empty_stmt (input_location
));
6817 gfc_add_expr_to_block (&body
, tmp
);
6821 gfc_trans_scalarized_loop_boundary (&loop
, &body
);
6823 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
,
6825 gfc_add_modify (&loop
.code
[0], limit
, tmp
);
6826 gfc_add_expr_to_block (&loop
.code
[0], build1_v (LABEL_EXPR
, lab
));
6828 /* If we have a mask, only add this element if the mask is set. */
6831 gfc_init_se (&maskse
, NULL
);
6832 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
6834 gfc_conv_expr_val (&maskse
, maskexpr
);
6835 gfc_add_block_to_block (&body
, &maskse
.pre
);
6837 gfc_start_block (&block
);
6840 gfc_init_block (&block
);
6842 /* Compare with the current limit. */
6843 gfc_init_se (&arrayse
, NULL
);
6844 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
6845 arrayse
.ss
= arrayss
;
6846 gfc_conv_expr_val (&arrayse
, arrayexpr
);
6847 arrayse
.expr
= gfc_evaluate_now (arrayse
.expr
, &arrayse
.pre
);
6848 gfc_add_block_to_block (&block
, &arrayse
.pre
);
6850 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6852 if (HONOR_NANS (DECL_MODE (limit
)))
6854 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
,
6855 arrayse
.expr
, limit
);
6856 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
6857 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
6858 build_empty_stmt (input_location
));
6859 gfc_add_expr_to_block (&block
, tmp
);
6863 tmp
= fold_build2_loc (input_location
,
6864 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
6865 type
, arrayse
.expr
, limit
);
6866 gfc_add_modify (&block
, limit
, tmp
);
6869 gfc_add_block_to_block (&block
, &arrayse
.post
);
6871 tmp
= gfc_finish_block (&block
);
6873 /* We enclose the above in if (mask) {...}. */
6876 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6877 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
6878 build_empty_stmt (input_location
));
6881 gfc_add_expr_to_block (&body
, tmp
);
6882 /* Avoid initializing loopvar[0] again, it should be left where
6883 it finished by the first loop. */
6884 loop
.from
[0] = loop
.loopvar
[0];
6886 gfc_trans_scalarizing_loops (&loop
, &body
);
6890 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
,
6892 ifbody
= build2_v (MODIFY_EXPR
, limit
, tmp
);
6893 tmp
= build3_v (COND_EXPR
, fast
, build_empty_stmt (input_location
),
6895 gfc_add_expr_to_block (&loop
.pre
, tmp
);
6897 else if (HONOR_INFINITIES (DECL_MODE (limit
)) && !lab
)
6899 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
, limit
,
6901 gfc_add_modify (&loop
.pre
, limit
, tmp
);
6904 /* For a scalar mask, enclose the loop in an if statement. */
6905 if (maskexpr
&& maskss
== NULL
)
6910 gfc_init_se (&maskse
, NULL
);
6911 gfc_conv_expr_val (&maskse
, maskexpr
);
6912 gfc_init_block (&block
);
6913 gfc_add_block_to_block (&block
, &loop
.pre
);
6914 gfc_add_block_to_block (&block
, &loop
.post
);
6915 tmp
= gfc_finish_block (&block
);
6917 if (HONOR_INFINITIES (DECL_MODE (limit
)))
6918 else_stmt
= build2_v (MODIFY_EXPR
, limit
, huge_cst
);
6920 else_stmt
= build_empty_stmt (input_location
);
6922 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6923 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
, else_stmt
);
6924 gfc_add_expr_to_block (&block
, tmp
);
6925 gfc_add_block_to_block (&se
->pre
, &block
);
6929 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
6930 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
6933 gfc_cleanup_loop (&loop
);
6938 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
6940 gfc_conv_intrinsic_btest (gfc_se
* se
, gfc_expr
* expr
)
6946 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6947 type
= TREE_TYPE (args
[0]);
6949 /* Optionally generate code for runtime argument check. */
6950 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
6952 tree below
= fold_build2_loc (input_location
, LT_EXPR
,
6953 logical_type_node
, args
[1],
6954 build_int_cst (TREE_TYPE (args
[1]), 0));
6955 tree nbits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
6956 tree above
= fold_build2_loc (input_location
, GE_EXPR
,
6957 logical_type_node
, args
[1], nbits
);
6958 tree scond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
6959 logical_type_node
, below
, above
);
6960 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
6961 "POS argument (%ld) out of range 0:%ld "
6962 "in intrinsic BTEST",
6963 fold_convert (long_integer_type_node
, args
[1]),
6964 fold_convert (long_integer_type_node
, nbits
));
6967 tmp
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
6968 build_int_cst (type
, 1), args
[1]);
6969 tmp
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[0], tmp
);
6970 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, tmp
,
6971 build_int_cst (type
, 0));
6972 type
= gfc_typenode_for_spec (&expr
->ts
);
6973 se
->expr
= convert (type
, tmp
);
6977 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
6979 gfc_conv_intrinsic_bitcomp (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
6983 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6985 /* Convert both arguments to the unsigned type of the same size. */
6986 args
[0] = fold_convert (unsigned_type_for (TREE_TYPE (args
[0])), args
[0]);
6987 args
[1] = fold_convert (unsigned_type_for (TREE_TYPE (args
[1])), args
[1]);
6989 /* If they have unequal type size, convert to the larger one. */
6990 if (TYPE_PRECISION (TREE_TYPE (args
[0]))
6991 > TYPE_PRECISION (TREE_TYPE (args
[1])))
6992 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
6993 else if (TYPE_PRECISION (TREE_TYPE (args
[1]))
6994 > TYPE_PRECISION (TREE_TYPE (args
[0])))
6995 args
[0] = fold_convert (TREE_TYPE (args
[1]), args
[0]);
6997 /* Now, we compare them. */
6998 se
->expr
= fold_build2_loc (input_location
, op
, logical_type_node
,
7003 /* Generate code to perform the specified operation. */
7005 gfc_conv_intrinsic_bitop (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
7009 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
7010 se
->expr
= fold_build2_loc (input_location
, op
, TREE_TYPE (args
[0]),
7016 gfc_conv_intrinsic_not (gfc_se
* se
, gfc_expr
* expr
)
7020 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
7021 se
->expr
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
7022 TREE_TYPE (arg
), arg
);
7026 /* Generate code for OUT_OF_RANGE. */
7028 gfc_conv_intrinsic_out_of_range (gfc_se
* se
, gfc_expr
* expr
)
7032 tree tmp
= NULL_TREE
, tmp1
, tmp2
;
7033 unsigned int num_args
;
7036 gfc_actual_arglist
*arg
= expr
->value
.function
.actual
;
7037 gfc_expr
*x
= arg
->expr
;
7038 gfc_expr
*mold
= arg
->next
->expr
;
7040 num_args
= gfc_intrinsic_argument_list_length (expr
);
7041 args
= XALLOCAVEC (tree
, num_args
);
7043 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
7045 gfc_init_se (&rnd_se
, NULL
);
7049 /* The ROUND argument is optional and shall appear only if X is
7050 of type real and MOLD is of type integer (see edit F23/004). */
7051 gfc_expr
*round
= arg
->next
->next
->expr
;
7052 gfc_conv_expr (&rnd_se
, round
);
7054 if (round
->expr_type
== EXPR_VARIABLE
7055 && round
->symtree
->n
.sym
->attr
.dummy
7056 && round
->symtree
->n
.sym
->attr
.optional
)
7058 tree present
= gfc_conv_expr_present (round
->symtree
->n
.sym
);
7059 rnd_se
.expr
= build3_loc (input_location
, COND_EXPR
,
7060 logical_type_node
, present
,
7061 rnd_se
.expr
, logical_false_node
);
7062 gfc_add_block_to_block (&se
->pre
, &rnd_se
.pre
);
7067 /* If ROUND is absent, it is equivalent to having the value false. */
7068 rnd_se
.expr
= logical_false_node
;
7071 type
= TREE_TYPE (args
[0]);
7072 k
= gfc_validate_kind (mold
->ts
.type
, mold
->ts
.kind
, false);
7077 /* X may be IEEE infinity or NaN, but the representation of MOLD may not
7078 support infinity or NaN. */
7080 finite
= build_call_expr_loc (input_location
,
7081 builtin_decl_explicit (BUILT_IN_ISFINITE
),
7083 finite
= convert (logical_type_node
, finite
);
7085 if (mold
->ts
.type
== BT_REAL
)
7087 tmp1
= build1 (ABS_EXPR
, type
, args
[0]);
7088 tmp2
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[k
].huge
,
7090 tmp
= build2 (GT_EXPR
, logical_type_node
, tmp1
,
7091 convert (type
, tmp2
));
7093 /* Check if MOLD representation supports infinity or NaN. */
7094 bool infnan
= (HONOR_INFINITIES (TREE_TYPE (args
[1]))
7095 || HONOR_NANS (TREE_TYPE (args
[1])));
7096 tmp
= build3 (COND_EXPR
, logical_type_node
, finite
, tmp
,
7097 infnan
? logical_false_node
: logical_true_node
);
7104 decl
= gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC
, x
->ts
.kind
);
7105 gcc_assert (decl
!= NULL_TREE
);
7107 /* Round or truncate argument X, depending on the optional argument
7108 ROUND (default: .false.). */
7109 tmp1
= build_round_expr (args
[0], type
);
7110 tmp2
= build_call_expr_loc (input_location
, decl
, 1, args
[0]);
7111 rounded
= build3 (COND_EXPR
, type
, rnd_se
.expr
, tmp1
, tmp2
);
7113 if (mold
->ts
.type
== BT_INTEGER
)
7115 tmp1
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[k
].min_int
,
7117 tmp2
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[k
].huge
,
7120 else if (mold
->ts
.type
== BT_UNSIGNED
)
7122 tmp1
= build_real_from_int_cst (type
, integer_zero_node
);
7123 tmp2
= gfc_conv_mpz_to_tree (gfc_unsigned_kinds
[k
].huge
,
7129 tmp1
= build2 (LT_EXPR
, logical_type_node
, rounded
,
7130 convert (type
, tmp1
));
7131 tmp2
= build2 (GT_EXPR
, logical_type_node
, rounded
,
7132 convert (type
, tmp2
));
7133 tmp
= build2 (TRUTH_ORIF_EXPR
, logical_type_node
, tmp1
, tmp2
);
7134 tmp
= build2 (TRUTH_ORIF_EXPR
, logical_type_node
,
7135 build1 (TRUTH_NOT_EXPR
, logical_type_node
, finite
),
7141 if (mold
->ts
.type
== BT_INTEGER
)
7143 tmp1
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[k
].min_int
,
7145 tmp2
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[k
].huge
,
7147 tmp1
= build2 (LT_EXPR
, logical_type_node
, args
[0],
7148 convert (type
, tmp1
));
7149 tmp2
= build2 (GT_EXPR
, logical_type_node
, args
[0],
7150 convert (type
, tmp2
));
7151 tmp
= build2 (TRUTH_ORIF_EXPR
, logical_type_node
, tmp1
, tmp2
);
7153 else if (mold
->ts
.type
== BT_UNSIGNED
)
7155 int i
= gfc_validate_kind (x
->ts
.type
, x
->ts
.kind
, false);
7156 tmp
= build_int_cst (type
, 0);
7157 tmp
= build2 (LT_EXPR
, logical_type_node
, args
[0], tmp
);
7158 if (mpz_cmp (gfc_integer_kinds
[i
].huge
,
7159 gfc_unsigned_kinds
[k
].huge
) > 0)
7161 tmp2
= gfc_conv_mpz_to_tree (gfc_unsigned_kinds
[k
].huge
,
7163 tmp2
= build2 (GT_EXPR
, logical_type_node
, args
[0],
7164 convert (type
, tmp2
));
7165 tmp
= build2 (TRUTH_ORIF_EXPR
, logical_type_node
, tmp
, tmp2
);
7168 else if (mold
->ts
.type
== BT_REAL
)
7170 tmp2
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[k
].huge
,
7172 tmp1
= build1 (NEGATE_EXPR
, TREE_TYPE (tmp2
), tmp2
);
7173 tmp1
= build2 (LT_EXPR
, logical_type_node
, args
[0],
7174 convert (type
, tmp1
));
7175 tmp2
= build2 (GT_EXPR
, logical_type_node
, args
[0],
7176 convert (type
, tmp2
));
7177 tmp
= build2 (TRUTH_ORIF_EXPR
, logical_type_node
, tmp1
, tmp2
);
7184 if (mold
->ts
.type
== BT_UNSIGNED
)
7186 tmp
= gfc_conv_mpz_to_tree (gfc_unsigned_kinds
[k
].huge
,
7188 tmp
= build2 (GT_EXPR
, logical_type_node
, args
[0],
7189 convert (type
, tmp
));
7191 else if (mold
->ts
.type
== BT_INTEGER
)
7193 tmp
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[k
].huge
,
7195 tmp
= build2 (GT_EXPR
, logical_type_node
, args
[0],
7196 convert (type
, tmp
));
7198 else if (mold
->ts
.type
== BT_REAL
)
7200 tmp
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[k
].huge
,
7202 tmp
= build2 (GT_EXPR
, logical_type_node
, args
[0],
7203 convert (type
, tmp
));
7213 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), tmp
);
7217 /* Set or clear a single bit. */
7219 gfc_conv_intrinsic_singlebitop (gfc_se
* se
, gfc_expr
* expr
, int set
)
7226 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
7227 type
= TREE_TYPE (args
[0]);
7229 /* Optionally generate code for runtime argument check. */
7230 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
7232 tree below
= fold_build2_loc (input_location
, LT_EXPR
,
7233 logical_type_node
, args
[1],
7234 build_int_cst (TREE_TYPE (args
[1]), 0));
7235 tree nbits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
7236 tree above
= fold_build2_loc (input_location
, GE_EXPR
,
7237 logical_type_node
, args
[1], nbits
);
7238 tree scond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
7239 logical_type_node
, below
, above
);
7240 size_t len_name
= strlen (expr
->value
.function
.isym
->name
);
7241 char *name
= XALLOCAVEC (char, len_name
+ 1);
7242 for (size_t i
= 0; i
< len_name
; i
++)
7243 name
[i
] = TOUPPER (expr
->value
.function
.isym
->name
[i
]);
7244 name
[len_name
] = '\0';
7245 tree iname
= gfc_build_addr_expr (pchar_type_node
,
7246 gfc_build_cstring_const (name
));
7247 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
7248 "POS argument (%ld) out of range 0:%ld "
7250 fold_convert (long_integer_type_node
, args
[1]),
7251 fold_convert (long_integer_type_node
, nbits
),
7255 tmp
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
7256 build_int_cst (type
, 1), args
[1]);
7262 tmp
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, type
, tmp
);
7264 se
->expr
= fold_build2_loc (input_location
, op
, type
, args
[0], tmp
);
7267 /* Extract a sequence of bits.
7268 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
7270 gfc_conv_intrinsic_ibits (gfc_se
* se
, gfc_expr
* expr
)
7276 tree num_bits
, cond
;
7278 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
7279 type
= TREE_TYPE (args
[0]);
7281 /* Optionally generate code for runtime argument check. */
7282 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
7284 tree tmp1
= fold_convert (long_integer_type_node
, args
[1]);
7285 tree tmp2
= fold_convert (long_integer_type_node
, args
[2]);
7286 tree nbits
= build_int_cst (long_integer_type_node
,
7287 TYPE_PRECISION (type
));
7288 tree below
= fold_build2_loc (input_location
, LT_EXPR
,
7289 logical_type_node
, args
[1],
7290 build_int_cst (TREE_TYPE (args
[1]), 0));
7291 tree above
= fold_build2_loc (input_location
, GT_EXPR
,
7292 logical_type_node
, tmp1
, nbits
);
7293 tree scond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
7294 logical_type_node
, below
, above
);
7295 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
7296 "POS argument (%ld) out of range 0:%ld "
7297 "in intrinsic IBITS", tmp1
, nbits
);
7298 below
= fold_build2_loc (input_location
, LT_EXPR
,
7299 logical_type_node
, args
[2],
7300 build_int_cst (TREE_TYPE (args
[2]), 0));
7301 above
= fold_build2_loc (input_location
, GT_EXPR
,
7302 logical_type_node
, tmp2
, nbits
);
7303 scond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
7304 logical_type_node
, below
, above
);
7305 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
7306 "LEN argument (%ld) out of range 0:%ld "
7307 "in intrinsic IBITS", tmp2
, nbits
);
7308 above
= fold_build2_loc (input_location
, PLUS_EXPR
,
7309 long_integer_type_node
, tmp1
, tmp2
);
7310 scond
= fold_build2_loc (input_location
, GT_EXPR
,
7311 logical_type_node
, above
, nbits
);
7312 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
7313 "POS(%ld)+LEN(%ld)>BIT_SIZE(%ld) "
7314 "in intrinsic IBITS", tmp1
, tmp2
, nbits
);
7317 /* The Fortran standard allows (shift width) LEN <= BIT_SIZE(I), whereas
7318 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
7319 special case. See also gfc_conv_intrinsic_ishft (). */
7320 num_bits
= build_int_cst (TREE_TYPE (args
[2]), TYPE_PRECISION (type
));
7322 mask
= build_int_cst (type
, -1);
7323 mask
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
, mask
, args
[2]);
7324 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, args
[2],
7326 mask
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
7327 build_int_cst (type
, 0), mask
);
7328 mask
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, type
, mask
);
7330 tmp
= fold_build2_loc (input_location
, RSHIFT_EXPR
, type
, args
[0], args
[1]);
7332 se
->expr
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, tmp
, mask
);
7336 gfc_conv_intrinsic_shift (gfc_se
* se
, gfc_expr
* expr
, bool right_shift
,
7339 tree args
[2], type
, num_bits
, cond
;
7341 bool do_convert
= false;
7343 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
7345 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
7346 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
7347 type
= TREE_TYPE (args
[0]);
7351 args
[0] = fold_convert (unsigned_type_for (type
), args
[0]);
7355 gcc_assert (right_shift
);
7357 if (flag_unsigned
&& arithmetic
&& expr
->ts
.type
== BT_UNSIGNED
)
7360 args
[0] = fold_convert (signed_type_for (type
), args
[0]);
7363 se
->expr
= fold_build2_loc (input_location
,
7364 right_shift
? RSHIFT_EXPR
: LSHIFT_EXPR
,
7365 TREE_TYPE (args
[0]), args
[0], args
[1]);
7368 se
->expr
= fold_convert (type
, se
->expr
);
7371 bigshift
= build_int_cst (type
, 0);
7374 tree nonneg
= fold_build2_loc (input_location
, GE_EXPR
,
7375 logical_type_node
, args
[0],
7376 build_int_cst (TREE_TYPE (args
[0]), 0));
7377 bigshift
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonneg
,
7378 build_int_cst (type
, 0),
7379 build_int_cst (type
, -1));
7382 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
7383 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
7385 num_bits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
7387 /* Optionally generate code for runtime argument check. */
7388 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
7390 tree below
= fold_build2_loc (input_location
, LT_EXPR
,
7391 logical_type_node
, args
[1],
7392 build_int_cst (TREE_TYPE (args
[1]), 0));
7393 tree above
= fold_build2_loc (input_location
, GT_EXPR
,
7394 logical_type_node
, args
[1], num_bits
);
7395 tree scond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
7396 logical_type_node
, below
, above
);
7397 size_t len_name
= strlen (expr
->value
.function
.isym
->name
);
7398 char *name
= XALLOCAVEC (char, len_name
+ 1);
7399 for (size_t i
= 0; i
< len_name
; i
++)
7400 name
[i
] = TOUPPER (expr
->value
.function
.isym
->name
[i
]);
7401 name
[len_name
] = '\0';
7402 tree iname
= gfc_build_addr_expr (pchar_type_node
,
7403 gfc_build_cstring_const (name
));
7404 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
7405 "SHIFT argument (%ld) out of range 0:%ld "
7407 fold_convert (long_integer_type_node
, args
[1]),
7408 fold_convert (long_integer_type_node
, num_bits
),
7412 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
7415 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
7416 bigshift
, se
->expr
);
7419 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
7421 : ((shift >= 0) ? i << shift : i >> -shift)
7422 where all shifts are logical shifts. */
7424 gfc_conv_intrinsic_ishft (gfc_se
* se
, gfc_expr
* expr
)
7436 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
7438 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
7439 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
7441 type
= TREE_TYPE (args
[0]);
7442 utype
= unsigned_type_for (type
);
7444 width
= fold_build1_loc (input_location
, ABS_EXPR
, TREE_TYPE (args
[1]),
7447 /* Left shift if positive. */
7448 lshift
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
, args
[0], width
);
7450 /* Right shift if negative.
7451 We convert to an unsigned type because we want a logical shift.
7452 The standard doesn't define the case of shifting negative
7453 numbers, and we try to be compatible with other compilers, most
7454 notably g77, here. */
7455 rshift
= fold_convert (type
, fold_build2_loc (input_location
, RSHIFT_EXPR
,
7456 utype
, convert (utype
, args
[0]), width
));
7458 tmp
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, args
[1],
7459 build_int_cst (TREE_TYPE (args
[1]), 0));
7460 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, lshift
, rshift
);
7462 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
7463 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
7465 num_bits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
7467 /* Optionally generate code for runtime argument check. */
7468 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
7470 tree outside
= fold_build2_loc (input_location
, GT_EXPR
,
7471 logical_type_node
, width
, num_bits
);
7472 gfc_trans_runtime_check (true, false, outside
, &se
->pre
, &expr
->where
,
7473 "SHIFT argument (%ld) out of range -%ld:%ld "
7474 "in intrinsic ISHFT",
7475 fold_convert (long_integer_type_node
, args
[1]),
7476 fold_convert (long_integer_type_node
, num_bits
),
7477 fold_convert (long_integer_type_node
, num_bits
));
7480 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, width
,
7482 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
7483 build_int_cst (type
, 0), tmp
);
7487 /* Circular shift. AKA rotate or barrel shift. */
7490 gfc_conv_intrinsic_ishftc (gfc_se
* se
, gfc_expr
* expr
)
7499 unsigned int num_args
;
7501 num_args
= gfc_intrinsic_argument_list_length (expr
);
7502 args
= XALLOCAVEC (tree
, num_args
);
7504 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
7506 type
= TREE_TYPE (args
[0]);
7507 nbits
= build_int_cst (long_integer_type_node
, TYPE_PRECISION (type
));
7511 gfc_expr
*size
= expr
->value
.function
.actual
->next
->next
->expr
;
7513 /* Use a library function for the 3 parameter version. */
7514 tree int4type
= gfc_get_int_type (4);
7516 /* Treat optional SIZE argument when it is passed as an optional
7517 dummy. If SIZE is absent, the default value is BIT_SIZE(I). */
7518 if (size
->expr_type
== EXPR_VARIABLE
7519 && size
->symtree
->n
.sym
->attr
.dummy
7520 && size
->symtree
->n
.sym
->attr
.optional
)
7522 tree type_of_size
= TREE_TYPE (args
[2]);
7523 args
[2] = build3_loc (input_location
, COND_EXPR
, type_of_size
,
7524 gfc_conv_expr_present (size
->symtree
->n
.sym
),
7525 args
[2], fold_convert (type_of_size
, nbits
));
7528 /* We convert the first argument to at least 4 bytes, and
7529 convert back afterwards. This removes the need for library
7530 functions for all argument sizes, and function will be
7531 aligned to at least 32 bits, so there's no loss. */
7532 if (expr
->ts
.kind
< 4)
7533 args
[0] = convert (int4type
, args
[0]);
7535 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
7536 need loads of library functions. They cannot have values >
7537 BIT_SIZE (I) so the conversion is safe. */
7538 args
[1] = convert (int4type
, args
[1]);
7539 args
[2] = convert (int4type
, args
[2]);
7541 /* Optionally generate code for runtime argument check. */
7542 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
7544 tree size
= fold_convert (long_integer_type_node
, args
[2]);
7545 tree below
= fold_build2_loc (input_location
, LE_EXPR
,
7546 logical_type_node
, size
,
7547 build_int_cst (TREE_TYPE (args
[1]), 0));
7548 tree above
= fold_build2_loc (input_location
, GT_EXPR
,
7549 logical_type_node
, size
, nbits
);
7550 tree scond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
7551 logical_type_node
, below
, above
);
7552 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
7553 "SIZE argument (%ld) out of range 1:%ld "
7554 "in intrinsic ISHFTC", size
, nbits
);
7555 tree width
= fold_convert (long_integer_type_node
, args
[1]);
7556 width
= fold_build1_loc (input_location
, ABS_EXPR
,
7557 long_integer_type_node
, width
);
7558 scond
= fold_build2_loc (input_location
, GT_EXPR
,
7559 logical_type_node
, width
, size
);
7560 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
7561 "SHIFT argument (%ld) out of range -%ld:%ld "
7562 "in intrinsic ISHFTC",
7563 fold_convert (long_integer_type_node
, args
[1]),
7567 switch (expr
->ts
.kind
)
7572 tmp
= gfor_fndecl_math_ishftc4
;
7575 tmp
= gfor_fndecl_math_ishftc8
;
7578 tmp
= gfor_fndecl_math_ishftc16
;
7583 se
->expr
= build_call_expr_loc (input_location
,
7584 tmp
, 3, args
[0], args
[1], args
[2]);
7585 /* Convert the result back to the original type, if we extended
7586 the first argument's width above. */
7587 if (expr
->ts
.kind
< 4)
7588 se
->expr
= convert (type
, se
->expr
);
7593 /* Evaluate arguments only once. */
7594 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
7595 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
7597 /* Optionally generate code for runtime argument check. */
7598 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
7600 tree width
= fold_convert (long_integer_type_node
, args
[1]);
7601 width
= fold_build1_loc (input_location
, ABS_EXPR
,
7602 long_integer_type_node
, width
);
7603 tree outside
= fold_build2_loc (input_location
, GT_EXPR
,
7604 logical_type_node
, width
, nbits
);
7605 gfc_trans_runtime_check (true, false, outside
, &se
->pre
, &expr
->where
,
7606 "SHIFT argument (%ld) out of range -%ld:%ld "
7607 "in intrinsic ISHFTC",
7608 fold_convert (long_integer_type_node
, args
[1]),
7612 /* Rotate left if positive. */
7613 lrot
= fold_build2_loc (input_location
, LROTATE_EXPR
, type
, args
[0], args
[1]);
7615 /* Rotate right if negative. */
7616 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (args
[1]),
7618 rrot
= fold_build2_loc (input_location
,RROTATE_EXPR
, type
, args
[0], tmp
);
7620 zero
= build_int_cst (TREE_TYPE (args
[1]), 0);
7621 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
, args
[1],
7623 rrot
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, lrot
, rrot
);
7625 /* Do nothing if shift == 0. */
7626 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, args
[1],
7628 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, args
[0],
7633 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
7634 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
7636 The conditional expression is necessary because the result of LEADZ(0)
7637 is defined, but the result of __builtin_clz(0) is undefined for most
7640 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
7641 difference in bit size between the argument of LEADZ and the C int. */
7644 gfc_conv_intrinsic_leadz (gfc_se
* se
, gfc_expr
* expr
)
7656 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
7657 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
7659 /* Which variant of __builtin_clz* should we call? */
7660 if (argsize
<= INT_TYPE_SIZE
)
7662 arg_type
= unsigned_type_node
;
7663 func
= builtin_decl_explicit (BUILT_IN_CLZ
);
7665 else if (argsize
<= LONG_TYPE_SIZE
)
7667 arg_type
= long_unsigned_type_node
;
7668 func
= builtin_decl_explicit (BUILT_IN_CLZL
);
7670 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
7672 arg_type
= long_long_unsigned_type_node
;
7673 func
= builtin_decl_explicit (BUILT_IN_CLZLL
);
7677 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
7678 arg_type
= gfc_build_uint_type (argsize
);
7682 /* Convert the actual argument twice: first, to the unsigned type of the
7683 same size; then, to the proper argument type for the built-in
7684 function. But the return type is of the default INTEGER kind. */
7685 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
7686 arg
= fold_convert (arg_type
, arg
);
7687 arg
= gfc_evaluate_now (arg
, &se
->pre
);
7688 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
7690 /* Compute LEADZ for the case i .ne. 0. */
7693 s
= TYPE_PRECISION (arg_type
) - argsize
;
7694 tmp
= fold_convert (result_type
,
7695 build_call_expr_loc (input_location
, func
,
7697 leadz
= fold_build2_loc (input_location
, MINUS_EXPR
, result_type
,
7698 tmp
, build_int_cst (result_type
, s
));
7702 /* We end up here if the argument type is larger than 'long long'.
7703 We generate this code:
7705 if (x & (ULL_MAX << ULL_SIZE) != 0)
7706 return clzll ((unsigned long long) (x >> ULLSIZE));
7708 return ULL_SIZE + clzll ((unsigned long long) x);
7709 where ULL_MAX is the largest value that a ULL_MAX can hold
7710 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
7711 is the bit-size of the long long type (64 in this example). */
7712 tree ullsize
, ullmax
, tmp1
, tmp2
, btmp
;
7714 ullsize
= build_int_cst (result_type
, LONG_LONG_TYPE_SIZE
);
7715 ullmax
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
7716 long_long_unsigned_type_node
,
7717 build_int_cst (long_long_unsigned_type_node
,
7720 cond
= fold_build2_loc (input_location
, LSHIFT_EXPR
, arg_type
,
7721 fold_convert (arg_type
, ullmax
), ullsize
);
7722 cond
= fold_build2_loc (input_location
, BIT_AND_EXPR
, arg_type
,
7724 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
7725 cond
, build_int_cst (arg_type
, 0));
7727 tmp1
= fold_build2_loc (input_location
, RSHIFT_EXPR
, arg_type
,
7729 tmp1
= fold_convert (long_long_unsigned_type_node
, tmp1
);
7730 btmp
= builtin_decl_explicit (BUILT_IN_CLZLL
);
7731 tmp1
= fold_convert (result_type
,
7732 build_call_expr_loc (input_location
, btmp
, 1, tmp1
));
7734 tmp2
= fold_convert (long_long_unsigned_type_node
, arg
);
7735 btmp
= builtin_decl_explicit (BUILT_IN_CLZLL
);
7736 tmp2
= fold_convert (result_type
,
7737 build_call_expr_loc (input_location
, btmp
, 1, tmp2
));
7738 tmp2
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
7741 leadz
= fold_build3_loc (input_location
, COND_EXPR
, result_type
,
7745 /* Build BIT_SIZE. */
7746 bit_size
= build_int_cst (result_type
, argsize
);
7748 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
7749 arg
, build_int_cst (arg_type
, 0));
7750 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, result_type
, cond
,
7755 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
7757 The conditional expression is necessary because the result of TRAILZ(0)
7758 is defined, but the result of __builtin_ctz(0) is undefined for most
7762 gfc_conv_intrinsic_trailz (gfc_se
* se
, gfc_expr
*expr
)
7773 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
7774 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
7776 /* Which variant of __builtin_ctz* should we call? */
7777 if (argsize
<= INT_TYPE_SIZE
)
7779 arg_type
= unsigned_type_node
;
7780 func
= builtin_decl_explicit (BUILT_IN_CTZ
);
7782 else if (argsize
<= LONG_TYPE_SIZE
)
7784 arg_type
= long_unsigned_type_node
;
7785 func
= builtin_decl_explicit (BUILT_IN_CTZL
);
7787 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
7789 arg_type
= long_long_unsigned_type_node
;
7790 func
= builtin_decl_explicit (BUILT_IN_CTZLL
);
7794 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
7795 arg_type
= gfc_build_uint_type (argsize
);
7799 /* Convert the actual argument twice: first, to the unsigned type of the
7800 same size; then, to the proper argument type for the built-in
7801 function. But the return type is of the default INTEGER kind. */
7802 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
7803 arg
= fold_convert (arg_type
, arg
);
7804 arg
= gfc_evaluate_now (arg
, &se
->pre
);
7805 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
7807 /* Compute TRAILZ for the case i .ne. 0. */
7809 trailz
= fold_convert (result_type
, build_call_expr_loc (input_location
,
7813 /* We end up here if the argument type is larger than 'long long'.
7814 We generate this code:
7816 if ((x & ULL_MAX) == 0)
7817 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
7819 return ctzll ((unsigned long long) x);
7821 where ULL_MAX is the largest value that a ULL_MAX can hold
7822 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
7823 is the bit-size of the long long type (64 in this example). */
7824 tree ullsize
, ullmax
, tmp1
, tmp2
, btmp
;
7826 ullsize
= build_int_cst (result_type
, LONG_LONG_TYPE_SIZE
);
7827 ullmax
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
7828 long_long_unsigned_type_node
,
7829 build_int_cst (long_long_unsigned_type_node
, 0));
7831 cond
= fold_build2_loc (input_location
, BIT_AND_EXPR
, arg_type
, arg
,
7832 fold_convert (arg_type
, ullmax
));
7833 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, cond
,
7834 build_int_cst (arg_type
, 0));
7836 tmp1
= fold_build2_loc (input_location
, RSHIFT_EXPR
, arg_type
,
7838 tmp1
= fold_convert (long_long_unsigned_type_node
, tmp1
);
7839 btmp
= builtin_decl_explicit (BUILT_IN_CTZLL
);
7840 tmp1
= fold_convert (result_type
,
7841 build_call_expr_loc (input_location
, btmp
, 1, tmp1
));
7842 tmp1
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
7845 tmp2
= fold_convert (long_long_unsigned_type_node
, arg
);
7846 btmp
= builtin_decl_explicit (BUILT_IN_CTZLL
);
7847 tmp2
= fold_convert (result_type
,
7848 build_call_expr_loc (input_location
, btmp
, 1, tmp2
));
7850 trailz
= fold_build3_loc (input_location
, COND_EXPR
, result_type
,
7854 /* Build BIT_SIZE. */
7855 bit_size
= build_int_cst (result_type
, argsize
);
7857 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
7858 arg
, build_int_cst (arg_type
, 0));
7859 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, result_type
, cond
,
7863 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
7864 for types larger than "long long", we call the long long built-in for
7865 the lower and higher bits and combine the result. */
7868 gfc_conv_intrinsic_popcnt_poppar (gfc_se
* se
, gfc_expr
*expr
, int parity
)
7876 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
7877 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
7878 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
7880 /* Which variant of the builtin should we call? */
7881 if (argsize
<= INT_TYPE_SIZE
)
7883 arg_type
= unsigned_type_node
;
7884 func
= builtin_decl_explicit (parity
7886 : BUILT_IN_POPCOUNT
);
7888 else if (argsize
<= LONG_TYPE_SIZE
)
7890 arg_type
= long_unsigned_type_node
;
7891 func
= builtin_decl_explicit (parity
7893 : BUILT_IN_POPCOUNTL
);
7895 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
7897 arg_type
= long_long_unsigned_type_node
;
7898 func
= builtin_decl_explicit (parity
7900 : BUILT_IN_POPCOUNTLL
);
7904 /* Our argument type is larger than 'long long', which mean none
7905 of the POPCOUNT builtins covers it. We thus call the 'long long'
7906 variant multiple times, and add the results. */
7907 tree utype
, arg2
, call1
, call2
;
7909 /* For now, we only cover the case where argsize is twice as large
7911 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
7913 func
= builtin_decl_explicit (parity
7915 : BUILT_IN_POPCOUNTLL
);
7917 /* Convert it to an integer, and store into a variable. */
7918 utype
= gfc_build_uint_type (argsize
);
7919 arg
= fold_convert (utype
, arg
);
7920 arg
= gfc_evaluate_now (arg
, &se
->pre
);
7922 /* Call the builtin twice. */
7923 call1
= build_call_expr_loc (input_location
, func
, 1,
7924 fold_convert (long_long_unsigned_type_node
,
7927 arg2
= fold_build2_loc (input_location
, RSHIFT_EXPR
, utype
, arg
,
7928 build_int_cst (utype
, LONG_LONG_TYPE_SIZE
));
7929 call2
= build_call_expr_loc (input_location
, func
, 1,
7930 fold_convert (long_long_unsigned_type_node
,
7933 /* Combine the results. */
7935 se
->expr
= fold_build2_loc (input_location
, BIT_XOR_EXPR
,
7936 integer_type_node
, call1
, call2
);
7938 se
->expr
= fold_build2_loc (input_location
, PLUS_EXPR
,
7939 integer_type_node
, call1
, call2
);
7941 se
->expr
= convert (result_type
, se
->expr
);
7945 /* Convert the actual argument twice: first, to the unsigned type of the
7946 same size; then, to the proper argument type for the built-in
7948 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
7949 arg
= fold_convert (arg_type
, arg
);
7951 se
->expr
= fold_convert (result_type
,
7952 build_call_expr_loc (input_location
, func
, 1, arg
));
7956 /* Process an intrinsic with unspecified argument-types that has an optional
7957 argument (which could be of type character), e.g. EOSHIFT. For those, we
7958 need to append the string length of the optional argument if it is not
7959 present and the type is really character.
7960 primary specifies the position (starting at 1) of the non-optional argument
7961 specifying the type and optional gives the position of the optional
7962 argument in the arglist. */
7965 conv_generic_with_optional_char_arg (gfc_se
* se
, gfc_expr
* expr
,
7966 unsigned primary
, unsigned optional
)
7968 gfc_actual_arglist
* prim_arg
;
7969 gfc_actual_arglist
* opt_arg
;
7971 gfc_actual_arglist
* arg
;
7973 vec
<tree
, va_gc
> *append_args
;
7975 /* Find the two arguments given as position. */
7979 for (arg
= expr
->value
.function
.actual
; arg
; arg
= arg
->next
)
7983 if (cur_pos
== primary
)
7985 if (cur_pos
== optional
)
7988 if (cur_pos
>= primary
&& cur_pos
>= optional
)
7991 gcc_assert (prim_arg
);
7992 gcc_assert (prim_arg
->expr
);
7993 gcc_assert (opt_arg
);
7995 /* If we do have type CHARACTER and the optional argument is really absent,
7996 append a dummy 0 as string length. */
7998 if (prim_arg
->expr
->ts
.type
== BT_CHARACTER
&& !opt_arg
->expr
)
8002 dummy
= build_int_cst (gfc_charlen_type_node
, 0);
8003 vec_alloc (append_args
, 1);
8004 append_args
->quick_push (dummy
);
8007 /* Build the call itself. */
8008 gcc_assert (!se
->ignore_optional
);
8009 sym
= gfc_get_symbol_for_expr (expr
, false);
8010 gfc_conv_procedure_call (se
, sym
, expr
->value
.function
.actual
, expr
,
8012 gfc_free_symbol (sym
);
8015 /* The length of a character string. */
8017 gfc_conv_intrinsic_len (gfc_se
* se
, gfc_expr
* expr
)
8026 gcc_assert (!se
->ss
);
8028 arg
= expr
->value
.function
.actual
->expr
;
8030 type
= gfc_typenode_for_spec (&expr
->ts
);
8031 switch (arg
->expr_type
)
8034 len
= build_int_cst (gfc_charlen_type_node
, arg
->value
.character
.length
);
8038 /* Obtain the string length from the function used by
8039 trans-array.cc(gfc_trans_array_constructor). */
8041 get_array_ctor_strlen (&se
->pre
, arg
->value
.constructor
, &len
);
8045 if (arg
->ref
== NULL
8046 || (arg
->ref
->next
== NULL
&& arg
->ref
->type
== REF_ARRAY
))
8048 /* This doesn't catch all cases.
8049 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
8050 and the surrounding thread. */
8051 sym
= arg
->symtree
->n
.sym
;
8052 decl
= gfc_get_symbol_decl (sym
);
8053 if (decl
== current_function_decl
&& sym
->attr
.function
8054 && (sym
->result
== sym
))
8055 decl
= gfc_get_fake_result_decl (sym
, 0);
8057 len
= sym
->ts
.u
.cl
->backend_decl
;
8065 gfc_init_se (&argse
, se
);
8067 gfc_conv_expr (&argse
, arg
);
8069 gfc_conv_expr_descriptor (&argse
, arg
);
8070 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8071 gfc_add_block_to_block (&se
->post
, &argse
.post
);
8072 len
= argse
.string_length
;
8075 se
->expr
= convert (type
, len
);
8078 /* The length of a character string not including trailing blanks. */
8080 gfc_conv_intrinsic_len_trim (gfc_se
* se
, gfc_expr
* expr
)
8082 int kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
8083 tree args
[2], type
, fndecl
;
8085 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
8086 type
= gfc_typenode_for_spec (&expr
->ts
);
8089 fndecl
= gfor_fndecl_string_len_trim
;
8091 fndecl
= gfor_fndecl_string_len_trim_char4
;
8095 se
->expr
= build_call_expr_loc (input_location
,
8096 fndecl
, 2, args
[0], args
[1]);
8097 se
->expr
= convert (type
, se
->expr
);
8101 /* Returns the starting position of a substring within a string. */
8104 gfc_conv_intrinsic_index_scan_verify (gfc_se
* se
, gfc_expr
* expr
,
8107 tree logical4_type_node
= gfc_get_logical_type (4);
8111 unsigned int num_args
;
8113 args
= XALLOCAVEC (tree
, 5);
8115 /* Get number of arguments; characters count double due to the
8116 string length argument. Kind= is not passed to the library
8117 and thus ignored. */
8118 if (expr
->value
.function
.actual
->next
->next
->expr
== NULL
)
8123 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
8124 type
= gfc_typenode_for_spec (&expr
->ts
);
8127 args
[4] = build_int_cst (logical4_type_node
, 0);
8129 args
[4] = convert (logical4_type_node
, args
[4]);
8131 fndecl
= build_addr (function
);
8132 se
->expr
= build_call_array_loc (input_location
,
8133 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
8135 se
->expr
= convert (type
, se
->expr
);
8139 /* The ascii value for a single character. */
8141 gfc_conv_intrinsic_ichar (gfc_se
* se
, gfc_expr
* expr
)
8143 tree args
[3], type
, pchartype
;
8146 nargs
= gfc_intrinsic_argument_list_length (expr
);
8147 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
8148 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args
[1])));
8149 pchartype
= gfc_get_pchar_type (expr
->value
.function
.actual
->expr
->ts
.kind
);
8150 args
[1] = fold_build1_loc (input_location
, NOP_EXPR
, pchartype
, args
[1]);
8151 type
= gfc_typenode_for_spec (&expr
->ts
);
8153 se
->expr
= build_fold_indirect_ref_loc (input_location
,
8155 se
->expr
= convert (type
, se
->expr
);
8159 /* Intrinsic ISNAN calls __builtin_isnan. */
8162 gfc_conv_intrinsic_isnan (gfc_se
* se
, gfc_expr
* expr
)
8166 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
8167 se
->expr
= build_call_expr_loc (input_location
,
8168 builtin_decl_explicit (BUILT_IN_ISNAN
),
8170 STRIP_TYPE_NOPS (se
->expr
);
8171 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
8175 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
8176 their argument against a constant integer value. */
8179 gfc_conv_has_intvalue (gfc_se
* se
, gfc_expr
* expr
, const int value
)
8183 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
8184 se
->expr
= fold_build2_loc (input_location
, EQ_EXPR
,
8185 gfc_typenode_for_spec (&expr
->ts
),
8186 arg
, build_int_cst (TREE_TYPE (arg
), value
));
8191 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
8194 gfc_conv_intrinsic_merge (gfc_se
* se
, gfc_expr
* expr
)
8202 unsigned int num_args
;
8204 num_args
= gfc_intrinsic_argument_list_length (expr
);
8205 args
= XALLOCAVEC (tree
, num_args
);
8207 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
8208 if (expr
->ts
.type
!= BT_CHARACTER
)
8216 /* We do the same as in the non-character case, but the argument
8217 list is different because of the string length arguments. We
8218 also have to set the string length for the result. */
8225 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr
->where
, len
, len2
,
8227 se
->string_length
= len
;
8229 tsource
= gfc_evaluate_now (tsource
, &se
->pre
);
8230 fsource
= gfc_evaluate_now (fsource
, &se
->pre
);
8231 mask
= gfc_evaluate_now (mask
, &se
->pre
);
8232 type
= TREE_TYPE (tsource
);
8233 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, mask
, tsource
,
8234 fold_convert (type
, fsource
));
8238 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
8241 gfc_conv_intrinsic_merge_bits (gfc_se
* se
, gfc_expr
* expr
)
8243 tree args
[3], mask
, type
;
8245 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
8246 mask
= gfc_evaluate_now (args
[2], &se
->pre
);
8248 type
= TREE_TYPE (args
[0]);
8249 gcc_assert (TREE_TYPE (args
[1]) == type
);
8250 gcc_assert (TREE_TYPE (mask
) == type
);
8252 args
[0] = fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[0], mask
);
8253 args
[1] = fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[1],
8254 fold_build1_loc (input_location
, BIT_NOT_EXPR
,
8256 se
->expr
= fold_build2_loc (input_location
, BIT_IOR_EXPR
, type
,
8261 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
8262 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
8265 gfc_conv_intrinsic_mask (gfc_se
* se
, gfc_expr
* expr
, int left
)
8267 tree arg
, allones
, type
, utype
, res
, cond
, bitsize
;
8270 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
8271 arg
= gfc_evaluate_now (arg
, &se
->pre
);
8273 type
= gfc_get_int_type (expr
->ts
.kind
);
8274 utype
= unsigned_type_for (type
);
8276 i
= gfc_validate_kind (BT_INTEGER
, expr
->ts
.kind
, false);
8277 bitsize
= build_int_cst (TREE_TYPE (arg
), gfc_integer_kinds
[i
].bit_size
);
8279 allones
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, utype
,
8280 build_int_cst (utype
, 0));
8284 /* Left-justified mask. */
8285 res
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (arg
),
8287 res
= fold_build2_loc (input_location
, LSHIFT_EXPR
, utype
, allones
,
8288 fold_convert (utype
, res
));
8290 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
8291 smaller than type width. */
8292 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, arg
,
8293 build_int_cst (TREE_TYPE (arg
), 0));
8294 res
= fold_build3_loc (input_location
, COND_EXPR
, utype
, cond
,
8295 build_int_cst (utype
, 0), res
);
8299 /* Right-justified mask. */
8300 res
= fold_build2_loc (input_location
, LSHIFT_EXPR
, utype
, allones
,
8301 fold_convert (utype
, arg
));
8302 res
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, utype
, res
);
8304 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
8305 strictly smaller than type width. */
8306 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
8308 res
= fold_build3_loc (input_location
, COND_EXPR
, utype
,
8309 cond
, allones
, res
);
8312 se
->expr
= fold_convert (type
, res
);
8316 /* FRACTION (s) is translated into:
8317 isfinite (s) ? frexp (s, &dummy_int) : NaN */
8319 gfc_conv_intrinsic_fraction (gfc_se
* se
, gfc_expr
* expr
)
8321 tree arg
, type
, tmp
, res
, frexp
, cond
;
8323 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
8325 type
= gfc_typenode_for_spec (&expr
->ts
);
8326 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
8327 arg
= gfc_evaluate_now (arg
, &se
->pre
);
8329 cond
= build_call_expr_loc (input_location
,
8330 builtin_decl_explicit (BUILT_IN_ISFINITE
),
8333 tmp
= gfc_create_var (integer_type_node
, NULL
);
8334 res
= build_call_expr_loc (input_location
, frexp
, 2,
8335 fold_convert (type
, arg
),
8336 gfc_build_addr_expr (NULL_TREE
, tmp
));
8337 res
= fold_convert (type
, res
);
8339 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
,
8340 cond
, res
, gfc_build_nan (type
, ""));
8344 /* NEAREST (s, dir) is translated into
8345 tmp = copysign (HUGE_VAL, dir);
8346 return nextafter (s, tmp);
8349 gfc_conv_intrinsic_nearest (gfc_se
* se
, gfc_expr
* expr
)
8351 tree args
[2], type
, tmp
, nextafter
, copysign
, huge_val
;
8353 nextafter
= gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER
, expr
->ts
.kind
);
8354 copysign
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
, expr
->ts
.kind
);
8356 type
= gfc_typenode_for_spec (&expr
->ts
);
8357 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
8359 huge_val
= gfc_build_inf_or_huge (type
, expr
->ts
.kind
);
8360 tmp
= build_call_expr_loc (input_location
, copysign
, 2, huge_val
,
8361 fold_convert (type
, args
[1]));
8362 se
->expr
= build_call_expr_loc (input_location
, nextafter
, 2,
8363 fold_convert (type
, args
[0]), tmp
);
8364 se
->expr
= fold_convert (type
, se
->expr
);
8368 /* SPACING (s) is translated into
8378 e = MAX_EXPR (e, emin);
8379 res = scalbn (1., e);
8383 where prec is the precision of s, gfc_real_kinds[k].digits,
8384 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
8385 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
8388 gfc_conv_intrinsic_spacing (gfc_se
* se
, gfc_expr
* expr
)
8390 tree arg
, type
, prec
, emin
, tiny
, res
, e
;
8391 tree cond
, nan
, tmp
, frexp
, scalbn
;
8395 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
8396 prec
= build_int_cst (integer_type_node
, gfc_real_kinds
[k
].digits
);
8397 emin
= build_int_cst (integer_type_node
, gfc_real_kinds
[k
].min_exponent
- 1);
8398 tiny
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[k
].tiny
, expr
->ts
.kind
, 0);
8400 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
8401 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
8403 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
8404 arg
= gfc_evaluate_now (arg
, &se
->pre
);
8406 type
= gfc_typenode_for_spec (&expr
->ts
);
8407 e
= gfc_create_var (integer_type_node
, NULL
);
8408 res
= gfc_create_var (type
, NULL
);
8411 /* Build the block for s /= 0. */
8412 gfc_start_block (&block
);
8413 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
8414 gfc_build_addr_expr (NULL_TREE
, e
));
8415 gfc_add_expr_to_block (&block
, tmp
);
8417 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, integer_type_node
, e
,
8419 gfc_add_modify (&block
, e
, fold_build2_loc (input_location
, MAX_EXPR
,
8420 integer_type_node
, tmp
, emin
));
8422 tmp
= build_call_expr_loc (input_location
, scalbn
, 2,
8423 build_real_from_int_cst (type
, integer_one_node
), e
);
8424 gfc_add_modify (&block
, res
, tmp
);
8426 /* Finish by building the IF statement for value zero. */
8427 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, arg
,
8428 build_real_from_int_cst (type
, integer_zero_node
));
8429 tmp
= build3_v (COND_EXPR
, cond
, build2_v (MODIFY_EXPR
, res
, tiny
),
8430 gfc_finish_block (&block
));
8432 /* And deal with infinities and NaNs. */
8433 cond
= build_call_expr_loc (input_location
,
8434 builtin_decl_explicit (BUILT_IN_ISFINITE
),
8436 nan
= gfc_build_nan (type
, "");
8437 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build2_v (MODIFY_EXPR
, res
, nan
));
8439 gfc_add_expr_to_block (&se
->pre
, tmp
);
8444 /* RRSPACING (s) is translated into
8453 x = scalbn (x, precision - e);
8460 where precision is gfc_real_kinds[k].digits. */
8463 gfc_conv_intrinsic_rrspacing (gfc_se
* se
, gfc_expr
* expr
)
8465 tree arg
, type
, e
, x
, cond
, nan
, stmt
, tmp
, frexp
, scalbn
, fabs
;
8469 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
8470 prec
= gfc_real_kinds
[k
].digits
;
8472 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
8473 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
8474 fabs
= gfc_builtin_decl_for_float_kind (BUILT_IN_FABS
, expr
->ts
.kind
);
8476 type
= gfc_typenode_for_spec (&expr
->ts
);
8477 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
8478 arg
= gfc_evaluate_now (arg
, &se
->pre
);
8480 e
= gfc_create_var (integer_type_node
, NULL
);
8481 x
= gfc_create_var (type
, NULL
);
8482 gfc_add_modify (&se
->pre
, x
,
8483 build_call_expr_loc (input_location
, fabs
, 1, arg
));
8486 gfc_start_block (&block
);
8487 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
8488 gfc_build_addr_expr (NULL_TREE
, e
));
8489 gfc_add_expr_to_block (&block
, tmp
);
8491 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, integer_type_node
,
8492 build_int_cst (integer_type_node
, prec
), e
);
8493 tmp
= build_call_expr_loc (input_location
, scalbn
, 2, x
, tmp
);
8494 gfc_add_modify (&block
, x
, tmp
);
8495 stmt
= gfc_finish_block (&block
);
8498 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, x
,
8499 build_real_from_int_cst (type
, integer_zero_node
));
8500 tmp
= build3_v (COND_EXPR
, cond
, stmt
, build_empty_stmt (input_location
));
8502 /* And deal with infinities and NaNs. */
8503 cond
= build_call_expr_loc (input_location
,
8504 builtin_decl_explicit (BUILT_IN_ISFINITE
),
8506 nan
= gfc_build_nan (type
, "");
8507 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build2_v (MODIFY_EXPR
, x
, nan
));
8509 gfc_add_expr_to_block (&se
->pre
, tmp
);
8510 se
->expr
= fold_convert (type
, x
);
8514 /* SCALE (s, i) is translated into scalbn (s, i). */
8516 gfc_conv_intrinsic_scale (gfc_se
* se
, gfc_expr
* expr
)
8518 tree args
[2], type
, scalbn
;
8520 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
8522 type
= gfc_typenode_for_spec (&expr
->ts
);
8523 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
8524 se
->expr
= build_call_expr_loc (input_location
, scalbn
, 2,
8525 fold_convert (type
, args
[0]),
8526 fold_convert (integer_type_node
, args
[1]));
8527 se
->expr
= fold_convert (type
, se
->expr
);
8531 /* SET_EXPONENT (s, i) is translated into
8532 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
8534 gfc_conv_intrinsic_set_exponent (gfc_se
* se
, gfc_expr
* expr
)
8536 tree args
[2], type
, tmp
, frexp
, scalbn
, cond
, nan
, res
;
8538 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
8539 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
8541 type
= gfc_typenode_for_spec (&expr
->ts
);
8542 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
8543 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
8545 tmp
= gfc_create_var (integer_type_node
, NULL
);
8546 tmp
= build_call_expr_loc (input_location
, frexp
, 2,
8547 fold_convert (type
, args
[0]),
8548 gfc_build_addr_expr (NULL_TREE
, tmp
));
8549 res
= build_call_expr_loc (input_location
, scalbn
, 2, tmp
,
8550 fold_convert (integer_type_node
, args
[1]));
8551 res
= fold_convert (type
, res
);
8553 /* Call to isfinite */
8554 cond
= build_call_expr_loc (input_location
,
8555 builtin_decl_explicit (BUILT_IN_ISFINITE
),
8557 nan
= gfc_build_nan (type
, "");
8559 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
8565 gfc_conv_intrinsic_size (gfc_se
* se
, gfc_expr
* expr
)
8567 gfc_actual_arglist
*actual
;
8573 gfc_symbol
*sym
= NULL
;
8575 gfc_init_se (&argse
, NULL
);
8576 actual
= expr
->value
.function
.actual
;
8578 if (actual
->expr
->ts
.type
== BT_CLASS
)
8579 gfc_add_class_array_ref (actual
->expr
);
8583 /* These are emerging from the interface mapping, when a class valued
8584 function appears as the rhs in a realloc on assign statement, where
8585 the size of the result is that of one of the actual arguments. */
8586 if (e
->expr_type
== EXPR_VARIABLE
8587 && e
->symtree
->n
.sym
->ns
== NULL
/* This is distinctive! */
8588 && e
->symtree
->n
.sym
->ts
.type
== BT_CLASS
8589 && e
->ref
&& e
->ref
->type
== REF_COMPONENT
8590 && strcmp (e
->ref
->u
.c
.component
->name
, "_data") == 0)
8591 sym
= e
->symtree
->n
.sym
;
8593 if ((gfc_option
.rtcheck
& GFC_RTCHECK_POINTER
)
8595 && (e
->expr_type
== EXPR_VARIABLE
|| e
->expr_type
== EXPR_FUNCTION
))
8597 symbol_attribute attr
;
8602 if (e
->symtree
->n
.sym
&& IS_CLASS_ARRAY (e
->symtree
->n
.sym
))
8604 attr
= CLASS_DATA (e
->symtree
->n
.sym
)->attr
;
8605 attr
.pointer
= attr
.class_pointer
;
8608 attr
= gfc_expr_attr (e
);
8610 if (attr
.allocatable
)
8611 msg
= xasprintf ("Allocatable argument '%s' is not allocated",
8612 e
->symtree
->n
.sym
->name
);
8613 else if (attr
.pointer
)
8614 msg
= xasprintf ("Pointer argument '%s' is not associated",
8615 e
->symtree
->n
.sym
->name
);
8621 temp
= gfc_class_data_get (sym
->backend_decl
);
8622 temp
= gfc_conv_descriptor_data_get (temp
);
8626 argse
.descriptor_only
= 1;
8627 gfc_conv_expr_descriptor (&argse
, actual
->expr
);
8628 temp
= gfc_conv_descriptor_data_get (argse
.expr
);
8631 cond
= fold_build2_loc (input_location
, EQ_EXPR
,
8632 logical_type_node
, temp
,
8633 fold_convert (TREE_TYPE (temp
),
8634 null_pointer_node
));
8635 gfc_trans_runtime_check (true, false, cond
, &argse
.pre
, &e
->where
, msg
);
8641 argse
.data_not_needed
= 1;
8642 if (gfc_is_class_array_function (e
))
8644 /* For functions that return a class array conv_expr_descriptor is not
8645 able to get the descriptor right. Therefore this special case. */
8646 gfc_conv_expr_reference (&argse
, e
);
8647 argse
.expr
= gfc_class_data_get (argse
.expr
);
8649 else if (sym
&& sym
->backend_decl
)
8651 gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (sym
->backend_decl
)));
8652 argse
.expr
= gfc_class_data_get (sym
->backend_decl
);
8655 gfc_conv_expr_descriptor (&argse
, actual
->expr
);
8656 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8657 gfc_add_block_to_block (&se
->post
, &argse
.post
);
8660 actual
= actual
->next
;
8664 gfc_init_block (&block
);
8665 gfc_init_se (&argse
, NULL
);
8666 gfc_conv_expr_type (&argse
, actual
->expr
,
8667 gfc_array_index_type
);
8668 gfc_add_block_to_block (&block
, &argse
.pre
);
8669 tree tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
8670 argse
.expr
, gfc_index_one_node
);
8671 size
= gfc_tree_array_size (&block
, arg1
, e
, tmp
);
8673 /* Unusually, for an intrinsic, size does not exclude
8674 an optional arg2, so we must test for it. */
8675 if (actual
->expr
->expr_type
== EXPR_VARIABLE
8676 && actual
->expr
->symtree
->n
.sym
->attr
.dummy
8677 && actual
->expr
->symtree
->n
.sym
->attr
.optional
)
8681 gfc_init_block (&block2
);
8682 gfc_init_se (&argse
, NULL
);
8683 argse
.want_pointer
= 1;
8684 argse
.data_not_needed
= 1;
8685 gfc_conv_expr (&argse
, actual
->expr
);
8686 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8687 /* 'block2' contains the arg2 absent case, 'block' the arg2 present
8688 case; size_var can be used in both blocks. */
8689 tree size_var
= gfc_create_var (TREE_TYPE (size
), "size");
8690 tmp
= fold_build2_loc (input_location
, MODIFY_EXPR
,
8691 TREE_TYPE (size_var
), size_var
, size
);
8692 gfc_add_expr_to_block (&block
, tmp
);
8693 size
= gfc_tree_array_size (&block2
, arg1
, e
, NULL_TREE
);
8694 tmp
= fold_build2_loc (input_location
, MODIFY_EXPR
,
8695 TREE_TYPE (size_var
), size_var
, size
);
8696 gfc_add_expr_to_block (&block2
, tmp
);
8697 cond
= gfc_conv_expr_present (actual
->expr
->symtree
->n
.sym
);
8698 tmp
= build3_v (COND_EXPR
, cond
, gfc_finish_block (&block
),
8699 gfc_finish_block (&block2
));
8700 gfc_add_expr_to_block (&se
->pre
, tmp
);
8704 gfc_add_block_to_block (&se
->pre
, &block
);
8707 size
= gfc_tree_array_size (&se
->pre
, arg1
, e
, NULL_TREE
);
8708 type
= gfc_typenode_for_spec (&expr
->ts
);
8709 se
->expr
= convert (type
, size
);
8713 /* Helper function to compute the size of a character variable,
8714 excluding the terminating null characters. The result has
8715 gfc_array_index_type type. */
8718 size_of_string_in_bytes (int kind
, tree string_length
)
8721 int i
= gfc_validate_kind (BT_CHARACTER
, kind
, false);
8723 bytesize
= build_int_cst (gfc_array_index_type
,
8724 gfc_character_kinds
[i
].bit_size
/ 8);
8726 return fold_build2_loc (input_location
, MULT_EXPR
, gfc_array_index_type
,
8728 fold_convert (gfc_array_index_type
, string_length
));
8733 gfc_conv_intrinsic_sizeof (gfc_se
*se
, gfc_expr
*expr
)
8745 gfc_init_se (&argse
, NULL
);
8746 arg
= expr
->value
.function
.actual
->expr
;
8748 if (arg
->rank
|| arg
->ts
.type
== BT_ASSUMED
)
8749 gfc_conv_expr_descriptor (&argse
, arg
);
8751 gfc_conv_expr_reference (&argse
, arg
);
8753 if (arg
->ts
.type
== BT_ASSUMED
)
8755 /* This only works if an array descriptor has been passed; thus, extract
8756 the size from the descriptor. */
8757 gcc_assert (TYPE_PRECISION (gfc_array_index_type
)
8758 == TYPE_PRECISION (size_type_node
));
8759 tmp
= arg
->symtree
->n
.sym
->backend_decl
;
8760 tmp
= DECL_LANG_SPECIFIC (tmp
)
8761 && GFC_DECL_SAVED_DESCRIPTOR (tmp
) != NULL_TREE
8762 ? GFC_DECL_SAVED_DESCRIPTOR (tmp
) : tmp
;
8763 if (POINTER_TYPE_P (TREE_TYPE (tmp
)))
8764 tmp
= build_fold_indirect_ref_loc (input_location
, tmp
);
8766 tmp
= gfc_conv_descriptor_dtype (tmp
);
8767 field
= gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
8768 GFC_DTYPE_ELEM_LEN
);
8769 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
8770 tmp
, field
, NULL_TREE
);
8772 byte_size
= fold_convert (gfc_array_index_type
, tmp
);
8774 else if (arg
->ts
.type
== BT_CLASS
)
8776 /* Conv_expr_descriptor returns a component_ref to _data component of the
8777 class object. The class object may be a non-pointer object, e.g.
8778 located on the stack, or a memory location pointed to, e.g. a
8779 parameter, i.e., an indirect_ref. */
8780 if (POINTER_TYPE_P (TREE_TYPE (argse
.expr
))
8781 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (argse
.expr
))))
8783 = gfc_class_vtab_size_get (build_fold_indirect_ref (argse
.expr
));
8784 else if (GFC_CLASS_TYPE_P (TREE_TYPE (argse
.expr
)))
8785 byte_size
= gfc_class_vtab_size_get (argse
.expr
);
8786 else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (argse
.expr
))
8787 && TREE_CODE (argse
.expr
) == COMPONENT_REF
)
8788 byte_size
= gfc_class_vtab_size_get (TREE_OPERAND (argse
.expr
, 0));
8789 else if (arg
->rank
> 0
8791 && arg
->ref
&& arg
->ref
->type
== REF_COMPONENT
))
8793 /* The scalarizer added an additional temp. To get the class' vptr
8794 one has to look at the original backend_decl. */
8795 if (argse
.class_container
)
8796 byte_size
= gfc_class_vtab_size_get (argse
.class_container
);
8797 else if (DECL_LANG_SPECIFIC (arg
->symtree
->n
.sym
->backend_decl
))
8798 byte_size
= gfc_class_vtab_size_get (
8799 GFC_DECL_SAVED_DESCRIPTOR (arg
->symtree
->n
.sym
->backend_decl
));
8808 if (arg
->ts
.type
== BT_CHARACTER
)
8809 byte_size
= size_of_string_in_bytes (arg
->ts
.kind
, argse
.string_length
);
8813 byte_size
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
8816 byte_size
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
8817 byte_size
= fold_convert (gfc_array_index_type
,
8818 size_in_bytes (byte_size
));
8823 se
->expr
= byte_size
;
8826 source_bytes
= gfc_create_var (gfc_array_index_type
, "bytes");
8827 gfc_add_modify (&argse
.pre
, source_bytes
, byte_size
);
8829 if (arg
->rank
== -1)
8831 tree cond
, loop_var
, exit_label
;
8834 tmp
= fold_convert (gfc_array_index_type
,
8835 gfc_conv_descriptor_rank (argse
.expr
));
8836 loop_var
= gfc_create_var (gfc_array_index_type
, "i");
8837 gfc_add_modify (&argse
.pre
, loop_var
, gfc_index_zero_node
);
8838 exit_label
= gfc_build_label_decl (NULL_TREE
);
8845 source_bytes = source_bytes * array.dim[i].extent;
8849 gfc_start_block (&body
);
8850 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
8852 tmp
= build1_v (GOTO_EXPR
, exit_label
);
8853 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
8854 cond
, tmp
, build_empty_stmt (input_location
));
8855 gfc_add_expr_to_block (&body
, tmp
);
8857 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, loop_var
);
8858 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, loop_var
);
8859 tmp
= gfc_conv_array_extent_dim (lower
, upper
, NULL
);
8860 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
8861 gfc_array_index_type
, tmp
, source_bytes
);
8862 gfc_add_modify (&body
, source_bytes
, tmp
);
8864 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
8865 gfc_array_index_type
, loop_var
,
8866 gfc_index_one_node
);
8867 gfc_add_modify_loc (input_location
, &body
, loop_var
, tmp
);
8869 tmp
= gfc_finish_block (&body
);
8871 tmp
= fold_build1_loc (input_location
, LOOP_EXPR
, void_type_node
,
8873 gfc_add_expr_to_block (&argse
.pre
, tmp
);
8875 tmp
= build1_v (LABEL_EXPR
, exit_label
);
8876 gfc_add_expr_to_block (&argse
.pre
, tmp
);
8880 /* Obtain the size of the array in bytes. */
8881 for (n
= 0; n
< arg
->rank
; n
++)
8884 idx
= gfc_rank_cst
[n
];
8885 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, idx
);
8886 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, idx
);
8887 tmp
= gfc_conv_array_extent_dim (lower
, upper
, NULL
);
8888 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
8889 gfc_array_index_type
, tmp
, source_bytes
);
8890 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
8893 se
->expr
= source_bytes
;
8896 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8901 gfc_conv_intrinsic_storage_size (gfc_se
*se
, gfc_expr
*expr
)
8905 tree type
, result_type
, tmp
, class_decl
= NULL
;
8907 bool unlimited
= false;
8909 arg
= expr
->value
.function
.actual
->expr
;
8911 gfc_init_se (&argse
, NULL
);
8912 result_type
= gfc_get_int_type (expr
->ts
.kind
);
8916 if (arg
->ts
.type
== BT_CLASS
)
8918 unlimited
= UNLIMITED_POLY (arg
);
8919 gfc_add_vptr_component (arg
);
8920 gfc_add_size_component (arg
);
8921 gfc_conv_expr (&argse
, arg
);
8922 tmp
= fold_convert (result_type
, argse
.expr
);
8923 class_decl
= gfc_get_class_from_expr (argse
.expr
);
8927 gfc_conv_expr_reference (&argse
, arg
);
8928 type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
8933 argse
.want_pointer
= 0;
8934 gfc_conv_expr_descriptor (&argse
, arg
);
8935 sym
= arg
->expr_type
== EXPR_VARIABLE
? arg
->symtree
->n
.sym
: NULL
;
8936 if (arg
->ts
.type
== BT_CLASS
)
8938 unlimited
= UNLIMITED_POLY (arg
);
8939 if (TREE_CODE (argse
.expr
) == COMPONENT_REF
)
8940 tmp
= gfc_class_vtab_size_get (TREE_OPERAND (argse
.expr
, 0));
8941 else if (arg
->rank
> 0 && sym
8942 && DECL_LANG_SPECIFIC (sym
->backend_decl
))
8943 tmp
= gfc_class_vtab_size_get (
8944 GFC_DECL_SAVED_DESCRIPTOR (sym
->backend_decl
));
8947 tmp
= fold_convert (result_type
, tmp
);
8948 class_decl
= gfc_get_class_from_expr (argse
.expr
);
8951 type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
8954 /* Obtain the argument's word length. */
8955 if (arg
->ts
.type
== BT_CHARACTER
)
8956 tmp
= size_of_string_in_bytes (arg
->ts
.kind
, argse
.string_length
);
8958 tmp
= size_in_bytes (type
);
8959 tmp
= fold_convert (result_type
, tmp
);
8962 if (unlimited
&& class_decl
)
8963 tmp
= gfc_resize_class_size_with_len (NULL
, class_decl
, tmp
);
8965 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, result_type
, tmp
,
8966 build_int_cst (result_type
, BITS_PER_UNIT
));
8967 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8971 /* Intrinsic string comparison functions. */
8974 gfc_conv_intrinsic_strcmp (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
8978 gfc_conv_intrinsic_function_args (se
, expr
, args
, 4);
8981 = gfc_build_compare_string (args
[0], args
[1], args
[2], args
[3],
8982 expr
->value
.function
.actual
->expr
->ts
.kind
,
8984 se
->expr
= fold_build2_loc (input_location
, op
,
8985 gfc_typenode_for_spec (&expr
->ts
), se
->expr
,
8986 build_int_cst (TREE_TYPE (se
->expr
), 0));
8989 /* Generate a call to the adjustl/adjustr library function. */
8991 gfc_conv_intrinsic_adjust (gfc_se
* se
, gfc_expr
* expr
, tree fndecl
)
8999 gfc_conv_intrinsic_function_args (se
, expr
, &args
[1], 2);
9002 type
= TREE_TYPE (args
[2]);
9003 var
= gfc_conv_string_tmp (se
, type
, len
);
9006 tmp
= build_call_expr_loc (input_location
,
9007 fndecl
, 3, args
[0], args
[1], args
[2]);
9008 gfc_add_expr_to_block (&se
->pre
, tmp
);
9010 se
->string_length
= len
;
9014 /* Generate code for the TRANSFER intrinsic:
9016 DEST = TRANSFER (SOURCE, MOLD)
9018 typeof<DEST> = typeof<MOLD>
9023 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
9025 typeof<DEST> = typeof<MOLD>
9027 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
9028 sizeof (DEST(0) * SIZE). */
9030 gfc_conv_intrinsic_transfer (gfc_se
* se
, gfc_expr
* expr
)
9046 tree class_ref
= NULL_TREE
;
9047 gfc_actual_arglist
*arg
;
9049 gfc_array_info
*info
;
9053 gfc_expr
*source_expr
, *mold_expr
, *class_expr
;
9057 info
= &se
->ss
->info
->data
.array
;
9059 /* Convert SOURCE. The output from this stage is:-
9060 source_bytes = length of the source in bytes
9061 source = pointer to the source data. */
9062 arg
= expr
->value
.function
.actual
;
9063 source_expr
= arg
->expr
;
9065 /* Ensure double transfer through LOGICAL preserves all
9067 if (arg
->expr
->expr_type
== EXPR_FUNCTION
9068 && arg
->expr
->value
.function
.esym
== NULL
9069 && arg
->expr
->value
.function
.isym
!= NULL
9070 && arg
->expr
->value
.function
.isym
->id
== GFC_ISYM_TRANSFER
9071 && arg
->expr
->ts
.type
== BT_LOGICAL
9072 && expr
->ts
.type
!= arg
->expr
->ts
.type
)
9073 arg
->expr
->value
.function
.name
= "__transfer_in_transfer";
9075 gfc_init_se (&argse
, NULL
);
9077 source_bytes
= gfc_create_var (gfc_array_index_type
, NULL
);
9079 /* Obtain the pointer to source and the length of source in bytes. */
9080 if (arg
->expr
->rank
== 0)
9082 gfc_conv_expr_reference (&argse
, arg
->expr
);
9083 if (arg
->expr
->ts
.type
== BT_CLASS
)
9085 tmp
= build_fold_indirect_ref_loc (input_location
, argse
.expr
);
9086 if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp
)))
9088 source
= gfc_class_data_get (tmp
);
9093 /* Array elements are evaluated as a reference to the data.
9094 To obtain the vptr for the element size, the argument
9095 expression must be stripped to the class reference and
9096 re-evaluated. The pre and post blocks are not needed. */
9097 gcc_assert (arg
->expr
->expr_type
== EXPR_VARIABLE
);
9098 source
= argse
.expr
;
9099 class_expr
= gfc_find_and_cut_at_last_class_ref (arg
->expr
);
9100 gfc_init_se (&argse
, NULL
);
9101 gfc_conv_expr (&argse
, class_expr
);
9102 class_ref
= argse
.expr
;
9106 source
= argse
.expr
;
9108 /* Obtain the source word length. */
9109 switch (arg
->expr
->ts
.type
)
9112 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
,
9113 argse
.string_length
);
9116 if (class_ref
!= NULL_TREE
)
9118 tmp
= gfc_class_vtab_size_get (class_ref
);
9119 if (UNLIMITED_POLY (source_expr
))
9120 tmp
= gfc_resize_class_size_with_len (NULL
, class_ref
, tmp
);
9124 tmp
= gfc_class_vtab_size_get (argse
.expr
);
9125 if (UNLIMITED_POLY (source_expr
))
9126 tmp
= gfc_resize_class_size_with_len (NULL
, argse
.expr
, tmp
);
9130 source_type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
9132 tmp
= fold_convert (gfc_array_index_type
,
9133 size_in_bytes (source_type
));
9139 argse
.want_pointer
= 0;
9140 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
9141 source
= gfc_conv_descriptor_data_get (argse
.expr
);
9142 source_type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
9144 /* Repack the source if not simply contiguous. */
9145 if (!gfc_is_simply_contiguous (arg
->expr
, false, true))
9147 tmp
= gfc_build_addr_expr (NULL_TREE
, argse
.expr
);
9149 if (warn_array_temporaries
)
9150 gfc_warning (OPT_Warray_temporaries
,
9151 "Creating array temporary at %L", &expr
->where
);
9153 source
= build_call_expr_loc (input_location
,
9154 gfor_fndecl_in_pack
, 1, tmp
);
9155 source
= gfc_evaluate_now (source
, &argse
.pre
);
9157 /* Free the temporary. */
9158 gfc_start_block (&block
);
9159 tmp
= gfc_call_free (source
);
9160 gfc_add_expr_to_block (&block
, tmp
);
9161 stmt
= gfc_finish_block (&block
);
9163 /* Clean up if it was repacked. */
9164 gfc_init_block (&block
);
9165 tmp
= gfc_conv_array_data (argse
.expr
);
9166 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
9168 tmp
= build3_v (COND_EXPR
, tmp
, stmt
,
9169 build_empty_stmt (input_location
));
9170 gfc_add_expr_to_block (&block
, tmp
);
9171 gfc_add_block_to_block (&block
, &se
->post
);
9172 gfc_init_block (&se
->post
);
9173 gfc_add_block_to_block (&se
->post
, &block
);
9176 /* Obtain the source word length. */
9177 if (arg
->expr
->ts
.type
== BT_CHARACTER
)
9178 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
,
9179 argse
.string_length
);
9180 else if (arg
->expr
->ts
.type
== BT_CLASS
)
9182 class_ref
= TREE_OPERAND (argse
.expr
, 0);
9183 tmp
= gfc_class_vtab_size_get (class_ref
);
9184 if (UNLIMITED_POLY (arg
->expr
))
9185 tmp
= gfc_resize_class_size_with_len (&argse
.pre
, class_ref
, tmp
);
9188 tmp
= fold_convert (gfc_array_index_type
,
9189 size_in_bytes (source_type
));
9191 /* Obtain the size of the array in bytes. */
9192 extent
= gfc_create_var (gfc_array_index_type
, NULL
);
9193 for (n
= 0; n
< arg
->expr
->rank
; n
++)
9196 idx
= gfc_rank_cst
[n
];
9197 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
9198 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, idx
);
9199 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, idx
);
9200 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
9201 gfc_array_index_type
, upper
, lower
);
9202 gfc_add_modify (&argse
.pre
, extent
, tmp
);
9203 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
9204 gfc_array_index_type
, extent
,
9205 gfc_index_one_node
);
9206 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
9207 gfc_array_index_type
, tmp
, source_bytes
);
9211 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
9212 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
9213 gfc_add_block_to_block (&se
->post
, &argse
.post
);
9215 /* Now convert MOLD. The outputs are:
9216 mold_type = the TREE type of MOLD
9217 dest_word_len = destination word length in bytes. */
9219 mold_expr
= arg
->expr
;
9221 gfc_init_se (&argse
, NULL
);
9223 scalar_mold
= arg
->expr
->rank
== 0;
9225 if (arg
->expr
->rank
== 0)
9227 gfc_conv_expr_reference (&argse
, mold_expr
);
9228 mold_type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
9233 argse
.want_pointer
= 0;
9234 gfc_conv_expr_descriptor (&argse
, mold_expr
);
9235 mold_type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
9238 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
9239 gfc_add_block_to_block (&se
->post
, &argse
.post
);
9241 if (strcmp (expr
->value
.function
.name
, "__transfer_in_transfer") == 0)
9243 /* If this TRANSFER is nested in another TRANSFER, use a type
9244 that preserves all bits. */
9245 if (mold_expr
->ts
.type
== BT_LOGICAL
)
9246 mold_type
= gfc_get_int_type (mold_expr
->ts
.kind
);
9249 /* Obtain the destination word length. */
9250 switch (mold_expr
->ts
.type
)
9253 tmp
= size_of_string_in_bytes (mold_expr
->ts
.kind
, argse
.string_length
);
9254 mold_type
= gfc_get_character_type_len (mold_expr
->ts
.kind
,
9255 argse
.string_length
);
9259 class_ref
= argse
.expr
;
9261 class_ref
= TREE_OPERAND (argse
.expr
, 0);
9262 tmp
= gfc_class_vtab_size_get (class_ref
);
9263 if (UNLIMITED_POLY (arg
->expr
))
9264 tmp
= gfc_resize_class_size_with_len (&argse
.pre
, class_ref
, tmp
);
9267 tmp
= fold_convert (gfc_array_index_type
, size_in_bytes (mold_type
));
9271 /* Do not fix dest_word_len if it is a variable, since the temporary can wind
9272 up being used before the assignment. */
9273 if (mold_expr
->ts
.type
== BT_CHARACTER
&& mold_expr
->ts
.deferred
)
9274 dest_word_len
= tmp
;
9277 dest_word_len
= gfc_create_var (gfc_array_index_type
, NULL
);
9278 gfc_add_modify (&se
->pre
, dest_word_len
, tmp
);
9281 /* Finally convert SIZE, if it is present. */
9283 size_words
= gfc_create_var (gfc_array_index_type
, NULL
);
9287 gfc_init_se (&argse
, NULL
);
9288 gfc_conv_expr_reference (&argse
, arg
->expr
);
9289 tmp
= convert (gfc_array_index_type
,
9290 build_fold_indirect_ref_loc (input_location
,
9292 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
9293 gfc_add_block_to_block (&se
->post
, &argse
.post
);
9298 /* Separate array and scalar results. */
9299 if (scalar_mold
&& tmp
== NULL_TREE
)
9300 goto scalar_transfer
;
9302 size_bytes
= gfc_create_var (gfc_array_index_type
, NULL
);
9303 if (tmp
!= NULL_TREE
)
9304 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, gfc_array_index_type
,
9305 tmp
, dest_word_len
);
9309 gfc_add_modify (&se
->pre
, size_bytes
, tmp
);
9310 gfc_add_modify (&se
->pre
, size_words
,
9311 fold_build2_loc (input_location
, CEIL_DIV_EXPR
,
9312 gfc_array_index_type
,
9313 size_bytes
, dest_word_len
));
9315 /* Evaluate the bounds of the result. If the loop range exists, we have
9316 to check if it is too large. If so, we modify loop->to be consistent
9317 with min(size, size(source)). Otherwise, size is made consistent with
9318 the loop range, so that the right number of bytes is transferred.*/
9319 n
= se
->loop
->order
[0];
9320 if (se
->loop
->to
[n
] != NULL_TREE
)
9322 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
9323 se
->loop
->to
[n
], se
->loop
->from
[n
]);
9324 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
9325 tmp
, gfc_index_one_node
);
9326 tmp
= fold_build2_loc (input_location
, MIN_EXPR
, gfc_array_index_type
,
9328 gfc_add_modify (&se
->pre
, size_words
, tmp
);
9329 gfc_add_modify (&se
->pre
, size_bytes
,
9330 fold_build2_loc (input_location
, MULT_EXPR
,
9331 gfc_array_index_type
,
9332 size_words
, dest_word_len
));
9333 upper
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
9334 size_words
, se
->loop
->from
[n
]);
9335 upper
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
9336 upper
, gfc_index_one_node
);
9340 upper
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
9341 size_words
, gfc_index_one_node
);
9342 se
->loop
->from
[n
] = gfc_index_zero_node
;
9345 se
->loop
->to
[n
] = upper
;
9347 /* Build a destination descriptor, using the pointer, source, as the
9349 gfc_trans_create_temp_array (&se
->pre
, &se
->post
, se
->ss
, mold_type
,
9350 NULL_TREE
, false, true, false, &expr
->where
);
9352 /* Cast the pointer to the result. */
9353 tmp
= gfc_conv_descriptor_data_get (info
->descriptor
);
9354 tmp
= fold_convert (pvoid_type_node
, tmp
);
9356 /* Use memcpy to do the transfer. */
9358 = build_call_expr_loc (input_location
,
9359 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3, tmp
,
9360 fold_convert (pvoid_type_node
, source
),
9361 fold_convert (size_type_node
,
9362 fold_build2_loc (input_location
,
9364 gfc_array_index_type
,
9367 gfc_add_expr_to_block (&se
->pre
, tmp
);
9369 se
->expr
= info
->descriptor
;
9370 if (expr
->ts
.type
== BT_CHARACTER
)
9372 tmp
= fold_convert (gfc_charlen_type_node
,
9373 TYPE_SIZE_UNIT (gfc_get_char_type (expr
->ts
.kind
)));
9374 se
->string_length
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
9375 gfc_charlen_type_node
,
9376 dest_word_len
, tmp
);
9381 /* Deal with scalar results. */
9383 extent
= fold_build2_loc (input_location
, MIN_EXPR
, gfc_array_index_type
,
9384 dest_word_len
, source_bytes
);
9385 extent
= fold_build2_loc (input_location
, MAX_EXPR
, gfc_array_index_type
,
9386 extent
, gfc_index_zero_node
);
9388 if (expr
->ts
.type
== BT_CHARACTER
)
9390 tree direct
, indirect
, free
;
9392 ptr
= convert (gfc_get_pchar_type (expr
->ts
.kind
), source
);
9393 tmpdecl
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
),
9396 /* If source is longer than the destination, use a pointer to
9397 the source directly. */
9398 gfc_init_block (&block
);
9399 gfc_add_modify (&block
, tmpdecl
, ptr
);
9400 direct
= gfc_finish_block (&block
);
9402 /* Otherwise, allocate a string with the length of the destination
9403 and copy the source into it. */
9404 gfc_init_block (&block
);
9405 tmp
= gfc_get_pchar_type (expr
->ts
.kind
);
9406 tmp
= gfc_call_malloc (&block
, tmp
, dest_word_len
);
9407 gfc_add_modify (&block
, tmpdecl
,
9408 fold_convert (TREE_TYPE (ptr
), tmp
));
9409 tmp
= build_call_expr_loc (input_location
,
9410 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3,
9411 fold_convert (pvoid_type_node
, tmpdecl
),
9412 fold_convert (pvoid_type_node
, ptr
),
9413 fold_convert (size_type_node
, extent
));
9414 gfc_add_expr_to_block (&block
, tmp
);
9415 indirect
= gfc_finish_block (&block
);
9417 /* Wrap it up with the condition. */
9418 tmp
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
,
9419 dest_word_len
, source_bytes
);
9420 tmp
= build3_v (COND_EXPR
, tmp
, direct
, indirect
);
9421 gfc_add_expr_to_block (&se
->pre
, tmp
);
9423 /* Free the temporary string, if necessary. */
9424 free
= gfc_call_free (tmpdecl
);
9425 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
9426 dest_word_len
, source_bytes
);
9427 tmp
= build3_v (COND_EXPR
, tmp
, free
, build_empty_stmt (input_location
));
9428 gfc_add_expr_to_block (&se
->post
, tmp
);
9431 tmp
= fold_convert (gfc_charlen_type_node
,
9432 TYPE_SIZE_UNIT (gfc_get_char_type (expr
->ts
.kind
)));
9433 se
->string_length
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
9434 gfc_charlen_type_node
,
9435 dest_word_len
, tmp
);
9439 tmpdecl
= gfc_create_var (mold_type
, "transfer");
9441 ptr
= convert (build_pointer_type (mold_type
), source
);
9443 /* For CLASS results, allocate the needed memory first. */
9444 if (mold_expr
->ts
.type
== BT_CLASS
)
9447 cdata
= gfc_class_data_get (tmpdecl
);
9448 tmp
= gfc_call_malloc (&se
->pre
, TREE_TYPE (cdata
), dest_word_len
);
9449 gfc_add_modify (&se
->pre
, cdata
, tmp
);
9452 /* Use memcpy to do the transfer. */
9453 if (mold_expr
->ts
.type
== BT_CLASS
)
9454 tmp
= gfc_class_data_get (tmpdecl
);
9456 tmp
= gfc_build_addr_expr (NULL_TREE
, tmpdecl
);
9458 tmp
= build_call_expr_loc (input_location
,
9459 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3,
9460 fold_convert (pvoid_type_node
, tmp
),
9461 fold_convert (pvoid_type_node
, ptr
),
9462 fold_convert (size_type_node
, extent
));
9463 gfc_add_expr_to_block (&se
->pre
, tmp
);
9465 /* For CLASS results, set the _vptr. */
9466 if (mold_expr
->ts
.type
== BT_CLASS
)
9467 gfc_reset_vptr (&se
->pre
, nullptr, tmpdecl
, source_expr
->ts
.u
.derived
);
9474 /* Generate a call to caf_is_present. */
9477 trans_caf_is_present (gfc_se
*se
, gfc_expr
*expr
)
9479 tree caf_reference
, caf_decl
, token
, image_index
;
9481 /* Compile the reference chain. */
9482 caf_reference
= conv_expr_ref_to_caf_ref (&se
->pre
, expr
);
9483 gcc_assert (caf_reference
!= NULL_TREE
);
9485 caf_decl
= gfc_get_tree_for_caf_expr (expr
);
9486 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
9487 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
9488 image_index
= gfc_caf_get_image_index (&se
->pre
, expr
, caf_decl
);
9489 gfc_get_caf_token_offset (se
, &token
, NULL
, caf_decl
, NULL
,
9492 return build_call_expr_loc (input_location
, gfor_fndecl_caf_is_present
,
9493 3, token
, image_index
, caf_reference
);
9497 /* Test whether this ref-chain refs this image only. */
9500 caf_this_image_ref (gfc_ref
*ref
)
9502 for ( ; ref
; ref
= ref
->next
)
9503 if (ref
->type
== REF_ARRAY
&& ref
->u
.ar
.codimen
)
9504 return ref
->u
.ar
.dimen_type
[ref
->u
.ar
.dimen
] == DIMEN_THIS_IMAGE
;
9510 /* Generate code for the ALLOCATED intrinsic.
9511 Generate inline code that directly check the address of the argument. */
9514 gfc_conv_allocated (gfc_se
*se
, gfc_expr
*expr
)
9518 bool coindexed_caf_comp
= false;
9519 gfc_expr
*e
= expr
->value
.function
.actual
->expr
;
9521 gfc_init_se (&arg1se
, NULL
);
9522 if (e
->ts
.type
== BT_CLASS
)
9524 /* Make sure that class array expressions have both a _data
9525 component reference and an array reference.... */
9526 if (CLASS_DATA (e
)->attr
.dimension
)
9527 gfc_add_class_array_ref (e
);
9528 /* .... whilst scalars only need the _data component. */
9530 gfc_add_data_component (e
);
9533 /* When 'e' references an allocatable component in a coarray, then call
9534 the caf-library function caf_is_present (). */
9535 if (flag_coarray
== GFC_FCOARRAY_LIB
&& e
->expr_type
== EXPR_FUNCTION
9536 && e
->value
.function
.isym
9537 && e
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
9539 e
= e
->value
.function
.actual
->expr
;
9540 if (gfc_expr_attr (e
).codimension
)
9542 /* Last partref is the coindexed coarray. As coarrays are collectively
9543 (de)allocated, the allocation status must be the same as the one of
9544 the local allocation. Convert to local access. */
9545 for (gfc_ref
*ref
= e
->ref
; ref
; ref
= ref
->next
)
9546 if (ref
->type
== REF_ARRAY
&& ref
->u
.ar
.codimen
)
9548 for (int i
= ref
->u
.ar
.dimen
;
9549 i
< ref
->u
.ar
.dimen
+ ref
->u
.ar
.codimen
; ++i
)
9550 ref
->u
.ar
.dimen_type
[i
] = DIMEN_THIS_IMAGE
;
9554 else if (!caf_this_image_ref (e
->ref
))
9555 coindexed_caf_comp
= true;
9557 if (coindexed_caf_comp
)
9558 tmp
= trans_caf_is_present (se
, e
);
9563 /* Allocatable scalar. */
9564 arg1se
.want_pointer
= 1;
9565 gfc_conv_expr (&arg1se
, e
);
9570 /* Allocatable array. */
9571 arg1se
.descriptor_only
= 1;
9572 gfc_conv_expr_descriptor (&arg1se
, e
);
9573 tmp
= gfc_conv_descriptor_data_get (arg1se
.expr
);
9576 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, tmp
,
9577 fold_convert (TREE_TYPE (tmp
), null_pointer_node
));
9580 /* Components of pointer array references sometimes come back with a pre block. */
9581 if (arg1se
.pre
.head
)
9582 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
9584 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), tmp
);
9588 /* Generate code for the ASSOCIATED intrinsic.
9589 If both POINTER and TARGET are arrays, generate a call to library function
9590 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
9591 In other cases, generate inline code that directly compare the address of
9592 POINTER with the address of TARGET. */
9595 gfc_conv_associated (gfc_se
*se
, gfc_expr
*expr
)
9597 gfc_actual_arglist
*arg1
;
9598 gfc_actual_arglist
*arg2
;
9603 tree nonzero_arraylen
= NULL_TREE
;
9607 gfc_init_se (&arg1se
, NULL
);
9608 gfc_init_se (&arg2se
, NULL
);
9609 arg1
= expr
->value
.function
.actual
;
9612 /* Check whether the expression is a scalar or not; we cannot use
9613 arg1->expr->rank as it can be nonzero for proc pointers. */
9614 ss
= gfc_walk_expr (arg1
->expr
);
9615 scalar
= ss
== gfc_ss_terminator
;
9617 gfc_free_ss_chain (ss
);
9621 /* No optional target. */
9624 /* A pointer to a scalar. */
9625 arg1se
.want_pointer
= 1;
9626 gfc_conv_expr (&arg1se
, arg1
->expr
);
9627 if (arg1
->expr
->symtree
->n
.sym
->attr
.proc_pointer
9628 && arg1
->expr
->symtree
->n
.sym
->attr
.dummy
)
9629 arg1se
.expr
= build_fold_indirect_ref_loc (input_location
,
9631 if (arg1
->expr
->ts
.type
== BT_CLASS
)
9633 tmp2
= gfc_class_data_get (arg1se
.expr
);
9634 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2
)))
9635 tmp2
= gfc_conv_descriptor_data_get (tmp2
);
9642 /* A pointer to an array. */
9643 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
9644 tmp2
= gfc_conv_descriptor_data_get (arg1se
.expr
);
9646 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
9647 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
9648 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, tmp2
,
9649 fold_convert (TREE_TYPE (tmp2
), null_pointer_node
));
9654 /* An optional target. */
9655 if (arg2
->expr
->ts
.type
== BT_CLASS
9656 && arg2
->expr
->expr_type
!= EXPR_FUNCTION
)
9657 gfc_add_data_component (arg2
->expr
);
9661 /* A pointer to a scalar. */
9662 arg1se
.want_pointer
= 1;
9663 gfc_conv_expr (&arg1se
, arg1
->expr
);
9664 if (arg1
->expr
->symtree
->n
.sym
->attr
.proc_pointer
9665 && arg1
->expr
->symtree
->n
.sym
->attr
.dummy
)
9666 arg1se
.expr
= build_fold_indirect_ref_loc (input_location
,
9668 if (arg1
->expr
->ts
.type
== BT_CLASS
)
9669 arg1se
.expr
= gfc_class_data_get (arg1se
.expr
);
9671 arg2se
.want_pointer
= 1;
9672 gfc_conv_expr (&arg2se
, arg2
->expr
);
9673 if (arg2
->expr
->symtree
->n
.sym
->attr
.proc_pointer
9674 && arg2
->expr
->symtree
->n
.sym
->attr
.dummy
)
9675 arg2se
.expr
= build_fold_indirect_ref_loc (input_location
,
9677 if (arg2
->expr
->ts
.type
== BT_CLASS
)
9679 arg2se
.expr
= gfc_evaluate_now (arg2se
.expr
, &arg2se
.pre
);
9680 arg2se
.expr
= gfc_class_data_get (arg2se
.expr
);
9682 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
9683 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
9684 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
9685 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
9686 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
9687 arg1se
.expr
, arg2se
.expr
);
9688 tmp2
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
9689 arg1se
.expr
, null_pointer_node
);
9690 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
9691 logical_type_node
, tmp
, tmp2
);
9695 /* An array pointer of zero length is not associated if target is
9697 arg1se
.descriptor_only
= 1;
9698 gfc_conv_expr_lhs (&arg1se
, arg1
->expr
);
9699 if (arg1
->expr
->rank
== -1)
9701 tmp
= gfc_conv_descriptor_rank (arg1se
.expr
);
9702 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
9703 TREE_TYPE (tmp
), tmp
,
9704 build_int_cst (TREE_TYPE (tmp
), 1));
9707 tmp
= gfc_rank_cst
[arg1
->expr
->rank
- 1];
9708 tmp
= gfc_conv_descriptor_stride_get (arg1se
.expr
, tmp
);
9709 if (arg2
->expr
->rank
!= 0)
9710 nonzero_arraylen
= fold_build2_loc (input_location
, NE_EXPR
,
9711 logical_type_node
, tmp
,
9712 build_int_cst (TREE_TYPE (tmp
), 0));
9714 /* A pointer to an array, call library function _gfor_associated. */
9715 arg1se
.want_pointer
= 1;
9716 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
9717 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
9718 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
9720 arg2se
.want_pointer
= 1;
9721 arg2se
.force_no_tmp
= 1;
9722 if (arg2
->expr
->rank
!= 0)
9723 gfc_conv_expr_descriptor (&arg2se
, arg2
->expr
);
9726 gfc_conv_expr (&arg2se
, arg2
->expr
);
9728 = gfc_conv_scalar_to_descriptor (&arg2se
, arg2se
.expr
,
9729 gfc_expr_attr (arg2
->expr
));
9730 arg2se
.expr
= gfc_build_addr_expr (NULL_TREE
, arg2se
.expr
);
9732 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
9733 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
9734 se
->expr
= build_call_expr_loc (input_location
,
9735 gfor_fndecl_associated
, 2,
9736 arg1se
.expr
, arg2se
.expr
);
9737 se
->expr
= convert (logical_type_node
, se
->expr
);
9738 if (arg2
->expr
->rank
!= 0)
9739 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
9740 logical_type_node
, se
->expr
,
9744 /* If target is present zero character length pointers cannot
9746 if (arg1
->expr
->ts
.type
== BT_CHARACTER
)
9748 tmp
= arg1se
.string_length
;
9749 tmp
= fold_build2_loc (input_location
, NE_EXPR
,
9750 logical_type_node
, tmp
,
9751 build_zero_cst (TREE_TYPE (tmp
)));
9752 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
9753 logical_type_node
, se
->expr
, tmp
);
9757 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
9761 /* Generate code for the SAME_TYPE_AS intrinsic.
9762 Generate inline code that directly checks the vindices. */
9765 gfc_conv_same_type_as (gfc_se
*se
, gfc_expr
*expr
)
9770 tree conda
= NULL_TREE
, condb
= NULL_TREE
;
9772 gfc_init_se (&se1
, NULL
);
9773 gfc_init_se (&se2
, NULL
);
9775 a
= expr
->value
.function
.actual
->expr
;
9776 b
= expr
->value
.function
.actual
->next
->expr
;
9778 bool unlimited_poly_a
= UNLIMITED_POLY (a
);
9779 bool unlimited_poly_b
= UNLIMITED_POLY (b
);
9780 if (unlimited_poly_a
)
9782 se1
.want_pointer
= 1;
9783 gfc_add_vptr_component (a
);
9785 else if (a
->ts
.type
== BT_CLASS
)
9787 gfc_add_vptr_component (a
);
9788 gfc_add_hash_component (a
);
9790 else if (a
->ts
.type
== BT_DERIVED
)
9791 a
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
,
9792 a
->ts
.u
.derived
->hash_value
);
9794 if (unlimited_poly_b
)
9796 se2
.want_pointer
= 1;
9797 gfc_add_vptr_component (b
);
9799 else if (b
->ts
.type
== BT_CLASS
)
9801 gfc_add_vptr_component (b
);
9802 gfc_add_hash_component (b
);
9804 else if (b
->ts
.type
== BT_DERIVED
)
9805 b
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
,
9806 b
->ts
.u
.derived
->hash_value
);
9808 gfc_conv_expr (&se1
, a
);
9809 gfc_conv_expr (&se2
, b
);
9811 if (unlimited_poly_a
)
9813 conda
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
9815 build_int_cst (TREE_TYPE (se1
.expr
), 0));
9816 se1
.expr
= gfc_vptr_hash_get (se1
.expr
);
9819 if (unlimited_poly_b
)
9821 condb
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
9823 build_int_cst (TREE_TYPE (se2
.expr
), 0));
9824 se2
.expr
= gfc_vptr_hash_get (se2
.expr
);
9827 tmp
= fold_build2_loc (input_location
, EQ_EXPR
,
9828 logical_type_node
, se1
.expr
,
9829 fold_convert (TREE_TYPE (se1
.expr
), se2
.expr
));
9832 tmp
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
9833 logical_type_node
, conda
, tmp
);
9836 tmp
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
9837 logical_type_node
, condb
, tmp
);
9839 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), tmp
);
9843 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
9846 gfc_conv_intrinsic_sc_kind (gfc_se
*se
, gfc_expr
*expr
)
9850 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
9851 se
->expr
= build_call_expr_loc (input_location
,
9852 gfor_fndecl_sc_kind
, 2, args
[0], args
[1]);
9853 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
9857 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
9860 gfc_conv_intrinsic_si_kind (gfc_se
*se
, gfc_expr
*expr
)
9864 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
9866 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
9867 type
= gfc_get_int_type (4);
9868 arg
= gfc_build_addr_expr (NULL_TREE
, fold_convert (type
, arg
));
9870 /* Convert it to the required type. */
9871 type
= gfc_typenode_for_spec (&expr
->ts
);
9872 se
->expr
= build_call_expr_loc (input_location
,
9873 gfor_fndecl_si_kind
, 1, arg
);
9874 se
->expr
= fold_convert (type
, se
->expr
);
9878 /* Generate code for SELECTED_LOGICAL_KIND (BITS) intrinsic function. */
9881 gfc_conv_intrinsic_sl_kind (gfc_se
*se
, gfc_expr
*expr
)
9885 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
9887 /* The argument to SELECTED_LOGICAL_KIND is INTEGER(4). */
9888 type
= gfc_get_int_type (4);
9889 arg
= gfc_build_addr_expr (NULL_TREE
, fold_convert (type
, arg
));
9891 /* Convert it to the required type. */
9892 type
= gfc_typenode_for_spec (&expr
->ts
);
9893 se
->expr
= build_call_expr_loc (input_location
,
9894 gfor_fndecl_sl_kind
, 1, arg
);
9895 se
->expr
= fold_convert (type
, se
->expr
);
9899 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
9902 gfc_conv_intrinsic_sr_kind (gfc_se
*se
, gfc_expr
*expr
)
9904 gfc_actual_arglist
*actual
;
9907 vec
<tree
, va_gc
> *args
= NULL
;
9909 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
9911 gfc_init_se (&argse
, se
);
9913 /* Pass a NULL pointer for an absent arg. */
9914 if (actual
->expr
== NULL
)
9915 argse
.expr
= null_pointer_node
;
9921 if (actual
->expr
->ts
.kind
!= gfc_c_int_kind
)
9923 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
9924 ts
.type
= BT_INTEGER
;
9925 ts
.kind
= gfc_c_int_kind
;
9926 gfc_convert_type (actual
->expr
, &ts
, 2);
9928 gfc_conv_expr_reference (&argse
, actual
->expr
);
9931 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
9932 gfc_add_block_to_block (&se
->post
, &argse
.post
);
9933 vec_safe_push (args
, argse
.expr
);
9936 /* Convert it to the required type. */
9937 type
= gfc_typenode_for_spec (&expr
->ts
);
9938 se
->expr
= build_call_expr_loc_vec (input_location
,
9939 gfor_fndecl_sr_kind
, args
);
9940 se
->expr
= fold_convert (type
, se
->expr
);
9944 /* Generate code for TRIM (A) intrinsic function. */
9947 gfc_conv_intrinsic_trim (gfc_se
* se
, gfc_expr
* expr
)
9957 unsigned int num_args
;
9959 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
9960 args
= XALLOCAVEC (tree
, num_args
);
9962 var
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
), "pstr");
9963 addr
= gfc_build_addr_expr (ppvoid_type_node
, var
);
9964 len
= gfc_create_var (gfc_charlen_type_node
, "len");
9966 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
9967 args
[0] = gfc_build_addr_expr (NULL_TREE
, len
);
9970 if (expr
->ts
.kind
== 1)
9971 function
= gfor_fndecl_string_trim
;
9972 else if (expr
->ts
.kind
== 4)
9973 function
= gfor_fndecl_string_trim_char4
;
9977 fndecl
= build_addr (function
);
9978 tmp
= build_call_array_loc (input_location
,
9979 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
9981 gfc_add_expr_to_block (&se
->pre
, tmp
);
9983 /* Free the temporary afterwards, if necessary. */
9984 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
9985 len
, build_int_cst (TREE_TYPE (len
), 0));
9986 tmp
= gfc_call_free (var
);
9987 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
9988 gfc_add_expr_to_block (&se
->post
, tmp
);
9991 se
->string_length
= len
;
9995 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
9998 gfc_conv_intrinsic_repeat (gfc_se
* se
, gfc_expr
* expr
)
10000 tree args
[3], ncopies
, dest
, dlen
, src
, slen
, ncopies_type
;
10001 tree type
, cond
, tmp
, count
, exit_label
, n
, max
, largest
;
10003 stmtblock_t block
, body
;
10006 /* We store in charsize the size of a character. */
10007 i
= gfc_validate_kind (BT_CHARACTER
, expr
->ts
.kind
, false);
10008 size
= build_int_cst (sizetype
, gfc_character_kinds
[i
].bit_size
/ 8);
10010 /* Get the arguments. */
10011 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
10012 slen
= fold_convert (sizetype
, gfc_evaluate_now (args
[0], &se
->pre
));
10014 ncopies
= gfc_evaluate_now (args
[2], &se
->pre
);
10015 ncopies_type
= TREE_TYPE (ncopies
);
10017 /* Check that NCOPIES is not negative. */
10018 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
, ncopies
,
10019 build_int_cst (ncopies_type
, 0));
10020 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
10021 "Argument NCOPIES of REPEAT intrinsic is negative "
10022 "(its value is %ld)",
10023 fold_convert (long_integer_type_node
, ncopies
));
10025 /* If the source length is zero, any non negative value of NCOPIES
10026 is valid, and nothing happens. */
10027 n
= gfc_create_var (ncopies_type
, "ncopies");
10028 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, slen
,
10030 tmp
= fold_build3_loc (input_location
, COND_EXPR
, ncopies_type
, cond
,
10031 build_int_cst (ncopies_type
, 0), ncopies
);
10032 gfc_add_modify (&se
->pre
, n
, tmp
);
10035 /* Check that ncopies is not too large: ncopies should be less than
10036 (or equal to) MAX / slen, where MAX is the maximal integer of
10037 the gfc_charlen_type_node type. If slen == 0, we need a special
10038 case to avoid the division by zero. */
10039 max
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
, sizetype
,
10040 fold_convert (sizetype
,
10041 TYPE_MAX_VALUE (gfc_charlen_type_node
)),
10043 largest
= TYPE_PRECISION (sizetype
) > TYPE_PRECISION (ncopies_type
)
10044 ? sizetype
: ncopies_type
;
10045 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
10046 fold_convert (largest
, ncopies
),
10047 fold_convert (largest
, max
));
10048 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, slen
,
10050 cond
= fold_build3_loc (input_location
, COND_EXPR
, logical_type_node
, tmp
,
10051 logical_false_node
, cond
);
10052 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
10053 "Argument NCOPIES of REPEAT intrinsic is too large");
10055 /* Compute the destination length. */
10056 dlen
= fold_build2_loc (input_location
, MULT_EXPR
, gfc_charlen_type_node
,
10057 fold_convert (gfc_charlen_type_node
, slen
),
10058 fold_convert (gfc_charlen_type_node
, ncopies
));
10059 type
= gfc_get_character_type (expr
->ts
.kind
, expr
->ts
.u
.cl
);
10060 dest
= gfc_conv_string_tmp (se
, build_pointer_type (type
), dlen
);
10062 /* Generate the code to do the repeat operation:
10063 for (i = 0; i < ncopies; i++)
10064 memmove (dest + (i * slen * size), src, slen*size); */
10065 gfc_start_block (&block
);
10066 count
= gfc_create_var (sizetype
, "count");
10067 gfc_add_modify (&block
, count
, size_zero_node
);
10068 exit_label
= gfc_build_label_decl (NULL_TREE
);
10070 /* Start the loop body. */
10071 gfc_start_block (&body
);
10073 /* Exit the loop if count >= ncopies. */
10074 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, count
,
10075 fold_convert (sizetype
, ncopies
));
10076 tmp
= build1_v (GOTO_EXPR
, exit_label
);
10077 TREE_USED (exit_label
) = 1;
10078 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
, tmp
,
10079 build_empty_stmt (input_location
));
10080 gfc_add_expr_to_block (&body
, tmp
);
10082 /* Call memmove (dest + (i*slen*size), src, slen*size). */
10083 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, sizetype
, slen
,
10085 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, sizetype
, tmp
,
10087 tmp
= fold_build_pointer_plus_loc (input_location
,
10088 fold_convert (pvoid_type_node
, dest
), tmp
);
10089 tmp
= build_call_expr_loc (input_location
,
10090 builtin_decl_explicit (BUILT_IN_MEMMOVE
),
10092 fold_build2_loc (input_location
, MULT_EXPR
,
10093 size_type_node
, slen
, size
));
10094 gfc_add_expr_to_block (&body
, tmp
);
10096 /* Increment count. */
10097 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, sizetype
,
10098 count
, size_one_node
);
10099 gfc_add_modify (&body
, count
, tmp
);
10101 /* Build the loop. */
10102 tmp
= build1_v (LOOP_EXPR
, gfc_finish_block (&body
));
10103 gfc_add_expr_to_block (&block
, tmp
);
10105 /* Add the exit label. */
10106 tmp
= build1_v (LABEL_EXPR
, exit_label
);
10107 gfc_add_expr_to_block (&block
, tmp
);
10109 /* Finish the block. */
10110 tmp
= gfc_finish_block (&block
);
10111 gfc_add_expr_to_block (&se
->pre
, tmp
);
10113 /* Set the result value. */
10115 se
->string_length
= dlen
;
10119 /* Generate code for the IARGC intrinsic. */
10122 gfc_conv_intrinsic_iargc (gfc_se
* se
, gfc_expr
* expr
)
10128 /* Call the library function. This always returns an INTEGER(4). */
10129 fndecl
= gfor_fndecl_iargc
;
10130 tmp
= build_call_expr_loc (input_location
,
10133 /* Convert it to the required type. */
10134 type
= gfc_typenode_for_spec (&expr
->ts
);
10135 tmp
= fold_convert (type
, tmp
);
10141 /* Generate code for the KILL intrinsic. */
10144 conv_intrinsic_kill (gfc_se
*se
, gfc_expr
*expr
)
10147 tree int4_type_node
= gfc_get_int_type (4);
10151 unsigned int num_args
;
10153 num_args
= gfc_intrinsic_argument_list_length (expr
);
10154 args
= XALLOCAVEC (tree
, num_args
);
10155 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
10157 /* Convert PID to a INTEGER(4) entity. */
10158 pid
= convert (int4_type_node
, args
[0]);
10160 /* Convert SIG to a INTEGER(4) entity. */
10161 sig
= convert (int4_type_node
, args
[1]);
10163 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_kill
, 2, pid
, sig
);
10165 se
->expr
= fold_convert (TREE_TYPE (args
[0]), tmp
);
10170 conv_intrinsic_kill_sub (gfc_code
*code
)
10173 gfc_se se
, se_stat
;
10174 tree int4_type_node
= gfc_get_int_type (4);
10180 /* Make the function call. */
10181 gfc_init_block (&block
);
10182 gfc_init_se (&se
, NULL
);
10184 /* Convert PID to a INTEGER(4) entity. */
10185 gfc_conv_expr (&se
, code
->ext
.actual
->expr
);
10186 gfc_add_block_to_block (&block
, &se
.pre
);
10187 pid
= fold_convert (int4_type_node
, gfc_evaluate_now (se
.expr
, &block
));
10188 gfc_add_block_to_block (&block
, &se
.post
);
10190 /* Convert SIG to a INTEGER(4) entity. */
10191 gfc_conv_expr (&se
, code
->ext
.actual
->next
->expr
);
10192 gfc_add_block_to_block (&block
, &se
.pre
);
10193 sig
= fold_convert (int4_type_node
, gfc_evaluate_now (se
.expr
, &block
));
10194 gfc_add_block_to_block (&block
, &se
.post
);
10196 /* Deal with an optional STATUS. */
10197 if (code
->ext
.actual
->next
->next
->expr
)
10199 gfc_init_se (&se_stat
, NULL
);
10200 gfc_conv_expr (&se_stat
, code
->ext
.actual
->next
->next
->expr
);
10201 statp
= gfc_create_var (gfc_get_int_type (4), "_statp");
10206 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_kill_sub
, 3, pid
, sig
,
10207 statp
? gfc_build_addr_expr (NULL_TREE
, statp
) : null_pointer_node
);
10209 gfc_add_expr_to_block (&block
, tmp
);
10211 if (statp
&& statp
!= se_stat
.expr
)
10212 gfc_add_modify (&block
, se_stat
.expr
,
10213 fold_convert (TREE_TYPE (se_stat
.expr
), statp
));
10215 return gfc_finish_block (&block
);
10220 /* The loc intrinsic returns the address of its argument as
10221 gfc_index_integer_kind integer. */
10224 gfc_conv_intrinsic_loc (gfc_se
* se
, gfc_expr
* expr
)
10227 gfc_expr
*arg_expr
;
10229 gcc_assert (!se
->ss
);
10231 arg_expr
= expr
->value
.function
.actual
->expr
;
10232 if (arg_expr
->rank
== 0)
10234 if (arg_expr
->ts
.type
== BT_CLASS
)
10235 gfc_add_data_component (arg_expr
);
10236 gfc_conv_expr_reference (se
, arg_expr
);
10239 gfc_conv_array_parameter (se
, arg_expr
, true, NULL
, NULL
, NULL
);
10240 se
->expr
= convert (gfc_get_int_type (gfc_index_integer_kind
), se
->expr
);
10242 /* Create a temporary variable for loc return value. Without this,
10243 we get an error an ICE in gcc/expr.cc(expand_expr_addr_expr_1). */
10244 temp_var
= gfc_create_var (gfc_get_int_type (gfc_index_integer_kind
), NULL
);
10245 gfc_add_modify (&se
->pre
, temp_var
, se
->expr
);
10246 se
->expr
= temp_var
;
10250 /* Specialized trim for f_c_string. */
10253 conv_trim (gfc_se
*tse
, gfc_se
*str
)
10255 tree cond
, plen
, pvar
, tlen
, ttmp
, tvar
;
10257 tlen
= gfc_create_var (gfc_charlen_type_node
, "tlen");
10258 plen
= gfc_build_addr_expr (NULL_TREE
, tlen
);
10260 tvar
= gfc_create_var (pchar_type_node
, "tstr");
10261 pvar
= gfc_build_addr_expr (ppvoid_type_node
, tvar
);
10263 ttmp
= build_call_expr_loc (input_location
, gfor_fndecl_string_trim
, 4,
10264 plen
, pvar
, str
->string_length
, str
->expr
);
10266 gfc_add_expr_to_block (&tse
->pre
, ttmp
);
10268 /* Free the temporary afterwards, if necessary. */
10269 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
10270 tlen
, build_int_cst (TREE_TYPE (tlen
), 0));
10271 ttmp
= gfc_call_free (tvar
);
10272 ttmp
= build3_v (COND_EXPR
, cond
, ttmp
, build_empty_stmt (input_location
));
10273 gfc_add_expr_to_block (&tse
->post
, ttmp
);
10276 tse
->string_length
= tlen
;
10280 /* The following routine generates code for the intrinsic functions from
10281 the ISO_C_BINDING module: C_LOC, C_FUNLOC, C_ASSOCIATED, and
10285 conv_isocbinding_function (gfc_se
*se
, gfc_expr
*expr
)
10287 gfc_actual_arglist
*arg
= expr
->value
.function
.actual
;
10289 if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_LOC
)
10291 if (arg
->expr
->rank
== 0)
10292 gfc_conv_expr_reference (se
, arg
->expr
);
10293 else if (gfc_is_simply_contiguous (arg
->expr
, false, false))
10294 gfc_conv_array_parameter (se
, arg
->expr
, true, NULL
, NULL
, NULL
);
10297 gfc_conv_expr_descriptor (se
, arg
->expr
);
10298 se
->expr
= gfc_conv_descriptor_data_get (se
->expr
);
10301 /* TODO -- the following two lines shouldn't be necessary, but if
10302 they're removed, a bug is exposed later in the code path.
10303 This workaround was thus introduced, but will have to be
10304 removed; please see PR 35150 for details about the issue. */
10305 se
->expr
= convert (pvoid_type_node
, se
->expr
);
10306 se
->expr
= gfc_evaluate_now (se
->expr
, &se
->pre
);
10308 else if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_FUNLOC
)
10309 gfc_conv_expr_reference (se
, arg
->expr
);
10310 else if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_ASSOCIATED
)
10315 /* Build the addr_expr for the first argument. The argument is
10316 already an *address* so we don't need to set want_pointer in
10318 gfc_init_se (&arg1se
, NULL
);
10319 gfc_conv_expr (&arg1se
, arg
->expr
);
10320 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
10321 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
10323 /* See if we were given two arguments. */
10324 if (arg
->next
->expr
== NULL
)
10325 /* Only given one arg so generate a null and do a
10326 not-equal comparison against the first arg. */
10327 se
->expr
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
10329 fold_convert (TREE_TYPE (arg1se
.expr
),
10330 null_pointer_node
));
10334 tree not_null_expr
;
10336 /* Given two arguments so build the arg2se from second arg. */
10337 gfc_init_se (&arg2se
, NULL
);
10338 gfc_conv_expr (&arg2se
, arg
->next
->expr
);
10339 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
10340 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
10342 /* Generate test to compare that the two args are equal. */
10343 eq_expr
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
10344 arg1se
.expr
, arg2se
.expr
);
10345 /* Generate test to ensure that the first arg is not null. */
10346 not_null_expr
= fold_build2_loc (input_location
, NE_EXPR
,
10348 arg1se
.expr
, null_pointer_node
);
10350 /* Finally, the generated test must check that both arg1 is not
10351 NULL and that it is equal to the second arg. */
10352 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
10354 not_null_expr
, eq_expr
);
10357 else if (expr
->value
.function
.isym
->id
== GFC_ISYM_F_C_STRING
)
10359 /* There are three cases:
10360 f_c_string(string) -> trim(string) // c_null_char
10361 f_c_string(string, .false.) -> trim(string) // c_null_char
10362 f_c_string(string, .true.) -> string // c_null_char */
10364 gfc_se lse
, rse
, tse
;
10365 tree len
, tmp
, var
;
10366 gfc_expr
*string
= arg
->expr
;
10367 gfc_expr
*asis
= arg
->next
->expr
;
10370 /* Convert string. */
10371 gfc_init_se (&lse
, se
);
10372 gfc_conv_expr (&lse
, string
);
10373 gfc_conv_string_parameter (&lse
);
10375 /* Create a string for C_NULL_CHAR and convert it. */
10376 cnc
= gfc_get_character_expr (gfc_default_character_kind
,
10377 &string
->where
, "\0", 1);
10378 gfc_init_se (&rse
, se
);
10379 gfc_conv_expr (&rse
, cnc
);
10380 gfc_conv_string_parameter (&rse
);
10381 gfc_free_expr (cnc
);
10386 #define cnode gfc_charlen_type_node
10390 gfc_se asis_se
, vse
;
10391 tree elen
, evar
, tlen
, tvar
;
10392 tree else_branch
, then_branch
;
10394 elen
= evar
= tlen
= tvar
= NULL_TREE
;
10396 /* f_c_string(string, .true.) -> string // c_null_char */
10398 gfc_init_block (&block
);
10400 gfc_add_block_to_block (&block
, &lse
.pre
);
10401 gfc_add_block_to_block (&block
, &rse
.pre
);
10403 tlen
= fold_build2_loc (input_location
, PLUS_EXPR
, cnode
,
10404 fold_convert (cnode
, lse
.string_length
),
10405 fold_convert (cnode
, rse
.string_length
));
10407 gfc_init_se (&vse
, se
);
10408 tvar
= gfc_conv_string_tmp (&vse
, pchar_type_node
, tlen
);
10409 gfc_add_block_to_block (&block
, &vse
.pre
);
10411 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_concat_string
,
10413 lse
.string_length
, lse
.expr
,
10414 rse
.string_length
, rse
.expr
);
10415 gfc_add_expr_to_block (&block
, tmp
);
10417 then_branch
= gfc_finish_block (&block
);
10419 /* f_c_string(string, .false.) = trim(string) // c_null_char */
10421 gfc_init_block (&block
);
10423 gfc_init_se (&tse
, se
);
10424 conv_trim (&tse
, &lse
);
10425 gfc_add_block_to_block (&block
, &tse
.pre
);
10426 gfc_add_block_to_block (&block
, &rse
.pre
);
10428 elen
= fold_build2_loc (input_location
, PLUS_EXPR
, cnode
,
10429 fold_convert (cnode
, tse
.string_length
),
10430 fold_convert (cnode
, rse
.string_length
));
10432 gfc_init_se (&vse
, se
);
10433 evar
= gfc_conv_string_tmp (&vse
, pchar_type_node
, elen
);
10434 gfc_add_block_to_block (&block
, &vse
.pre
);
10436 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_concat_string
,
10438 tse
.string_length
, tse
.expr
,
10439 rse
.string_length
, rse
.expr
);
10440 gfc_add_expr_to_block (&block
, tmp
);
10442 else_branch
= gfc_finish_block (&block
);
10444 gfc_init_se (&asis_se
, se
);
10445 gfc_conv_expr (&asis_se
, asis
);
10446 if (asis
->expr_type
== EXPR_VARIABLE
10447 && asis
->symtree
->n
.sym
->attr
.dummy
10448 && asis
->symtree
->n
.sym
->attr
.optional
)
10450 tree present
= gfc_conv_expr_present (asis
->symtree
->n
.sym
);
10451 asis_se
.expr
= build3_loc (input_location
, COND_EXPR
,
10452 logical_type_node
, present
,
10454 build_int_cst (logical_type_node
, 0));
10456 gfc_add_block_to_block (&se
->pre
, &asis_se
.pre
);
10457 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
10458 asis_se
.expr
, then_branch
, else_branch
);
10460 gfc_add_expr_to_block (&se
->pre
, tmp
);
10462 var
= fold_build3_loc (input_location
, COND_EXPR
, pchar_type_node
,
10463 asis_se
.expr
, tvar
, evar
);
10464 gfc_add_expr_to_block (&se
->pre
, var
);
10466 len
= fold_build3_loc (input_location
, COND_EXPR
, cnode
,
10467 asis_se
.expr
, tlen
, elen
);
10468 gfc_add_expr_to_block (&se
->pre
, len
);
10472 /* f_c_string(string) = trim(string) // c_null_char */
10474 gfc_add_block_to_block (&se
->pre
, &lse
.pre
);
10475 gfc_add_block_to_block (&se
->pre
, &rse
.pre
);
10477 gfc_init_se (&tse
, se
);
10478 conv_trim (&tse
, &lse
);
10479 gfc_add_block_to_block (&se
->pre
, &tse
.pre
);
10480 gfc_add_block_to_block (&se
->post
, &tse
.post
);
10482 len
= fold_build2_loc (input_location
, PLUS_EXPR
, cnode
,
10483 fold_convert (cnode
, tse
.string_length
),
10484 fold_convert (cnode
, rse
.string_length
));
10486 var
= gfc_conv_string_tmp (se
, pchar_type_node
, len
);
10488 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_concat_string
,
10490 tse
.string_length
, tse
.expr
,
10491 rse
.string_length
, rse
.expr
);
10492 gfc_add_expr_to_block (&se
->pre
, tmp
);
10496 se
->string_length
= len
;
10501 gcc_unreachable ();
10505 /* The following routine generates code for the intrinsic
10506 subroutines from the ISO_C_BINDING module:
10508 * C_F_PROCPOINTER. */
10511 conv_isocbinding_subroutine (gfc_code
*code
)
10518 tree desc
, dim
, tmp
, stride
, offset
;
10519 stmtblock_t body
, block
;
10521 gfc_actual_arglist
*arg
= code
->ext
.actual
;
10523 gfc_init_se (&se
, NULL
);
10524 gfc_init_se (&cptrse
, NULL
);
10525 gfc_conv_expr (&cptrse
, arg
->expr
);
10526 gfc_add_block_to_block (&se
.pre
, &cptrse
.pre
);
10527 gfc_add_block_to_block (&se
.post
, &cptrse
.post
);
10529 gfc_init_se (&fptrse
, NULL
);
10530 if (arg
->next
->expr
->rank
== 0)
10532 fptrse
.want_pointer
= 1;
10533 gfc_conv_expr (&fptrse
, arg
->next
->expr
);
10534 gfc_add_block_to_block (&se
.pre
, &fptrse
.pre
);
10535 gfc_add_block_to_block (&se
.post
, &fptrse
.post
);
10536 if (arg
->next
->expr
->symtree
->n
.sym
->attr
.proc_pointer
10537 && arg
->next
->expr
->symtree
->n
.sym
->attr
.dummy
)
10538 fptrse
.expr
= build_fold_indirect_ref_loc (input_location
,
10540 se
.expr
= fold_build2_loc (input_location
, MODIFY_EXPR
,
10541 TREE_TYPE (fptrse
.expr
),
10543 fold_convert (TREE_TYPE (fptrse
.expr
),
10545 gfc_add_expr_to_block (&se
.pre
, se
.expr
);
10546 gfc_add_block_to_block (&se
.pre
, &se
.post
);
10547 return gfc_finish_block (&se
.pre
);
10550 gfc_start_block (&block
);
10552 /* Get the descriptor of the Fortran pointer. */
10553 fptrse
.descriptor_only
= 1;
10554 gfc_conv_expr_descriptor (&fptrse
, arg
->next
->expr
);
10555 gfc_add_block_to_block (&block
, &fptrse
.pre
);
10556 desc
= fptrse
.expr
;
10558 /* Set the span field. */
10559 tmp
= TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc
)));
10560 tmp
= fold_convert (gfc_array_index_type
, tmp
);
10561 gfc_conv_descriptor_span_set (&block
, desc
, tmp
);
10563 /* Set data value, dtype, and offset. */
10564 tmp
= GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc
));
10565 gfc_conv_descriptor_data_set (&block
, desc
, fold_convert (tmp
, cptrse
.expr
));
10566 gfc_add_modify (&block
, gfc_conv_descriptor_dtype (desc
),
10567 gfc_get_dtype (TREE_TYPE (desc
)));
10569 /* Start scalarization of the bounds, using the shape argument. */
10571 shape_ss
= gfc_walk_expr (arg
->next
->next
->expr
);
10572 gcc_assert (shape_ss
!= gfc_ss_terminator
);
10573 gfc_init_se (&shapese
, NULL
);
10575 gfc_init_loopinfo (&loop
);
10576 gfc_add_ss_to_loop (&loop
, shape_ss
);
10577 gfc_conv_ss_startstride (&loop
);
10578 gfc_conv_loop_setup (&loop
, &arg
->next
->expr
->where
);
10579 gfc_mark_ss_chain_used (shape_ss
, 1);
10581 gfc_copy_loopinfo_to_se (&shapese
, &loop
);
10582 shapese
.ss
= shape_ss
;
10584 stride
= gfc_create_var (gfc_array_index_type
, "stride");
10585 offset
= gfc_create_var (gfc_array_index_type
, "offset");
10586 gfc_add_modify (&block
, stride
, gfc_index_one_node
);
10587 gfc_add_modify (&block
, offset
, gfc_index_zero_node
);
10590 gfc_start_scalarized_body (&loop
, &body
);
10592 dim
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
10593 loop
.loopvar
[0], loop
.from
[0]);
10595 /* Set bounds and stride. */
10596 gfc_conv_descriptor_lbound_set (&body
, desc
, dim
, gfc_index_one_node
);
10597 gfc_conv_descriptor_stride_set (&body
, desc
, dim
, stride
);
10599 gfc_conv_expr (&shapese
, arg
->next
->next
->expr
);
10600 gfc_add_block_to_block (&body
, &shapese
.pre
);
10601 gfc_conv_descriptor_ubound_set (&body
, desc
, dim
, shapese
.expr
);
10602 gfc_add_block_to_block (&body
, &shapese
.post
);
10604 /* Calculate offset. */
10605 gfc_add_modify (&body
, offset
,
10606 fold_build2_loc (input_location
, PLUS_EXPR
,
10607 gfc_array_index_type
, offset
, stride
));
10608 /* Update stride. */
10609 gfc_add_modify (&body
, stride
,
10610 fold_build2_loc (input_location
, MULT_EXPR
,
10611 gfc_array_index_type
, stride
,
10612 fold_convert (gfc_array_index_type
,
10614 /* Finish scalarization loop. */
10615 gfc_trans_scalarizing_loops (&loop
, &body
);
10616 gfc_add_block_to_block (&block
, &loop
.pre
);
10617 gfc_add_block_to_block (&block
, &loop
.post
);
10618 gfc_add_block_to_block (&block
, &fptrse
.post
);
10619 gfc_cleanup_loop (&loop
);
10621 gfc_add_modify (&block
, offset
,
10622 fold_build1_loc (input_location
, NEGATE_EXPR
,
10623 gfc_array_index_type
, offset
));
10624 gfc_conv_descriptor_offset_set (&block
, desc
, offset
);
10626 gfc_add_expr_to_block (&se
.pre
, gfc_finish_block (&block
));
10627 gfc_add_block_to_block (&se
.pre
, &se
.post
);
10628 return gfc_finish_block (&se
.pre
);
10632 /* Save and restore floating-point state. */
10635 gfc_save_fp_state (stmtblock_t
*block
)
10637 tree type
, fpstate
, tmp
;
10639 type
= build_array_type (char_type_node
,
10640 build_range_type (size_type_node
, size_zero_node
,
10641 size_int (GFC_FPE_STATE_BUFFER_SIZE
)));
10642 fpstate
= gfc_create_var (type
, "fpstate");
10643 fpstate
= gfc_build_addr_expr (pvoid_type_node
, fpstate
);
10645 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_ieee_procedure_entry
,
10647 gfc_add_expr_to_block (block
, tmp
);
10654 gfc_restore_fp_state (stmtblock_t
*block
, tree fpstate
)
10658 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_ieee_procedure_exit
,
10660 gfc_add_expr_to_block (block
, tmp
);
10664 /* Generate code for arguments of IEEE functions. */
10667 conv_ieee_function_args (gfc_se
*se
, gfc_expr
*expr
, tree
*argarray
,
10670 gfc_actual_arglist
*actual
;
10675 actual
= expr
->value
.function
.actual
;
10676 for (arg
= 0; arg
< nargs
; arg
++, actual
= actual
->next
)
10678 gcc_assert (actual
);
10681 gfc_init_se (&argse
, se
);
10682 gfc_conv_expr_val (&argse
, e
);
10684 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
10685 gfc_add_block_to_block (&se
->post
, &argse
.post
);
10686 argarray
[arg
] = argse
.expr
;
10691 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE
10692 and IEEE_UNORDERED, which translate directly to GCC type-generic
10696 conv_intrinsic_ieee_builtin (gfc_se
* se
, gfc_expr
* expr
,
10697 enum built_in_function code
, int nargs
)
10700 gcc_assert ((unsigned) nargs
<= ARRAY_SIZE (args
));
10702 conv_ieee_function_args (se
, expr
, args
, nargs
);
10703 se
->expr
= build_call_expr_loc_array (input_location
,
10704 builtin_decl_explicit (code
),
10706 STRIP_TYPE_NOPS (se
->expr
);
10707 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
10711 /* Generate code for intrinsics IEEE_SIGNBIT. */
10714 conv_intrinsic_ieee_signbit (gfc_se
* se
, gfc_expr
* expr
)
10718 conv_ieee_function_args (se
, expr
, &arg
, 1);
10719 signbit
= build_call_expr_loc (input_location
,
10720 builtin_decl_explicit (BUILT_IN_SIGNBIT
),
10722 signbit
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
10723 signbit
, integer_zero_node
);
10724 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), signbit
);
10728 /* Generate code for IEEE_IS_NORMAL intrinsic:
10729 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
10732 conv_intrinsic_ieee_is_normal (gfc_se
* se
, gfc_expr
* expr
)
10734 tree arg
, isnormal
, iszero
;
10736 /* Convert arg, evaluate it only once. */
10737 conv_ieee_function_args (se
, expr
, &arg
, 1);
10738 arg
= gfc_evaluate_now (arg
, &se
->pre
);
10740 isnormal
= build_call_expr_loc (input_location
,
10741 builtin_decl_explicit (BUILT_IN_ISNORMAL
),
10743 iszero
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, arg
,
10744 build_real_from_int_cst (TREE_TYPE (arg
),
10745 integer_zero_node
));
10746 se
->expr
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
10747 logical_type_node
, isnormal
, iszero
);
10748 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
10752 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
10753 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
10756 conv_intrinsic_ieee_is_negative (gfc_se
* se
, gfc_expr
* expr
)
10758 tree arg
, signbit
, isnan
;
10760 /* Convert arg, evaluate it only once. */
10761 conv_ieee_function_args (se
, expr
, &arg
, 1);
10762 arg
= gfc_evaluate_now (arg
, &se
->pre
);
10764 isnan
= build_call_expr_loc (input_location
,
10765 builtin_decl_explicit (BUILT_IN_ISNAN
),
10767 STRIP_TYPE_NOPS (isnan
);
10769 signbit
= build_call_expr_loc (input_location
,
10770 builtin_decl_explicit (BUILT_IN_SIGNBIT
),
10772 signbit
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
10773 signbit
, integer_zero_node
);
10775 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
10776 logical_type_node
, signbit
,
10777 fold_build1_loc (input_location
, TRUTH_NOT_EXPR
,
10778 TREE_TYPE(isnan
), isnan
));
10780 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
10784 /* Generate code for IEEE_LOGB and IEEE_RINT. */
10787 conv_intrinsic_ieee_logb_rint (gfc_se
* se
, gfc_expr
* expr
,
10788 enum built_in_function code
)
10790 tree arg
, decl
, call
, fpstate
;
10793 conv_ieee_function_args (se
, expr
, &arg
, 1);
10794 argprec
= TYPE_PRECISION (TREE_TYPE (arg
));
10795 decl
= builtin_decl_for_precision (code
, argprec
);
10797 /* Save floating-point state. */
10798 fpstate
= gfc_save_fp_state (&se
->pre
);
10800 /* Make the function call. */
10801 call
= build_call_expr_loc (input_location
, decl
, 1, arg
);
10802 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), call
);
10804 /* Restore floating-point state. */
10805 gfc_restore_fp_state (&se
->post
, fpstate
);
10809 /* Generate code for IEEE_REM. */
10812 conv_intrinsic_ieee_rem (gfc_se
* se
, gfc_expr
* expr
)
10814 tree args
[2], decl
, call
, fpstate
;
10817 conv_ieee_function_args (se
, expr
, args
, 2);
10819 /* If arguments have unequal size, convert them to the larger. */
10820 if (TYPE_PRECISION (TREE_TYPE (args
[0]))
10821 > TYPE_PRECISION (TREE_TYPE (args
[1])))
10822 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
10823 else if (TYPE_PRECISION (TREE_TYPE (args
[1]))
10824 > TYPE_PRECISION (TREE_TYPE (args
[0])))
10825 args
[0] = fold_convert (TREE_TYPE (args
[1]), args
[0]);
10827 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
10828 decl
= builtin_decl_for_precision (BUILT_IN_REMAINDER
, argprec
);
10830 /* Save floating-point state. */
10831 fpstate
= gfc_save_fp_state (&se
->pre
);
10833 /* Make the function call. */
10834 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
10835 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
10837 /* Restore floating-point state. */
10838 gfc_restore_fp_state (&se
->post
, fpstate
);
10842 /* Generate code for IEEE_NEXT_AFTER. */
10845 conv_intrinsic_ieee_next_after (gfc_se
* se
, gfc_expr
* expr
)
10847 tree args
[2], decl
, call
, fpstate
;
10850 conv_ieee_function_args (se
, expr
, args
, 2);
10852 /* Result has the characteristics of first argument. */
10853 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
10854 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
10855 decl
= builtin_decl_for_precision (BUILT_IN_NEXTAFTER
, argprec
);
10857 /* Save floating-point state. */
10858 fpstate
= gfc_save_fp_state (&se
->pre
);
10860 /* Make the function call. */
10861 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
10862 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
10864 /* Restore floating-point state. */
10865 gfc_restore_fp_state (&se
->post
, fpstate
);
10869 /* Generate code for IEEE_SCALB. */
10872 conv_intrinsic_ieee_scalb (gfc_se
* se
, gfc_expr
* expr
)
10874 tree args
[2], decl
, call
, huge
, type
;
10877 conv_ieee_function_args (se
, expr
, args
, 2);
10879 /* Result has the characteristics of first argument. */
10880 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
10881 decl
= builtin_decl_for_precision (BUILT_IN_SCALBN
, argprec
);
10883 if (TYPE_PRECISION (TREE_TYPE (args
[1])) > TYPE_PRECISION (integer_type_node
))
10885 /* We need to fold the integer into the range of a C int. */
10886 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
10887 type
= TREE_TYPE (args
[1]);
10889 n
= gfc_validate_kind (BT_INTEGER
, gfc_c_int_kind
, false);
10890 huge
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
,
10892 huge
= fold_convert (type
, huge
);
10893 args
[1] = fold_build2_loc (input_location
, MIN_EXPR
, type
, args
[1],
10895 args
[1] = fold_build2_loc (input_location
, MAX_EXPR
, type
, args
[1],
10896 fold_build1_loc (input_location
, NEGATE_EXPR
,
10900 args
[1] = fold_convert (integer_type_node
, args
[1]);
10902 /* Make the function call. */
10903 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
10904 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
10908 /* Generate code for IEEE_COPY_SIGN. */
10911 conv_intrinsic_ieee_copy_sign (gfc_se
* se
, gfc_expr
* expr
)
10913 tree args
[2], decl
, sign
;
10916 conv_ieee_function_args (se
, expr
, args
, 2);
10918 /* Get the sign of the second argument. */
10919 sign
= build_call_expr_loc (input_location
,
10920 builtin_decl_explicit (BUILT_IN_SIGNBIT
),
10922 sign
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
10923 sign
, integer_zero_node
);
10925 /* Create a value of one, with the right sign. */
10926 sign
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
10928 fold_build1_loc (input_location
, NEGATE_EXPR
,
10932 args
[1] = fold_convert (TREE_TYPE (args
[0]), sign
);
10934 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
10935 decl
= builtin_decl_for_precision (BUILT_IN_COPYSIGN
, argprec
);
10937 se
->expr
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
10941 /* Generate code for IEEE_CLASS. */
10944 conv_intrinsic_ieee_class (gfc_se
*se
, gfc_expr
*expr
)
10946 tree arg
, c
, t1
, t2
, t3
, t4
;
10948 /* Convert arg, evaluate it only once. */
10949 conv_ieee_function_args (se
, expr
, &arg
, 1);
10950 arg
= gfc_evaluate_now (arg
, &se
->pre
);
10952 c
= build_call_expr_loc (input_location
,
10953 builtin_decl_explicit (BUILT_IN_FPCLASSIFY
), 6,
10954 build_int_cst (integer_type_node
, IEEE_QUIET_NAN
),
10955 build_int_cst (integer_type_node
,
10956 IEEE_POSITIVE_INF
),
10957 build_int_cst (integer_type_node
,
10958 IEEE_POSITIVE_NORMAL
),
10959 build_int_cst (integer_type_node
,
10960 IEEE_POSITIVE_DENORMAL
),
10961 build_int_cst (integer_type_node
,
10962 IEEE_POSITIVE_ZERO
),
10964 c
= gfc_evaluate_now (c
, &se
->pre
);
10965 t1
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
10966 c
, build_int_cst (integer_type_node
,
10968 t2
= build_call_expr_loc (input_location
,
10969 builtin_decl_explicit (BUILT_IN_ISSIGNALING
), 1,
10971 t2
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
10972 t2
, build_zero_cst (TREE_TYPE (t2
)));
10973 t1
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
10974 logical_type_node
, t1
, t2
);
10975 t3
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
10976 c
, build_int_cst (integer_type_node
,
10977 IEEE_POSITIVE_ZERO
));
10978 t4
= build_call_expr_loc (input_location
,
10979 builtin_decl_explicit (BUILT_IN_SIGNBIT
), 1,
10981 t4
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
10982 t4
, build_zero_cst (TREE_TYPE (t4
)));
10983 t3
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
10984 logical_type_node
, t3
, t4
);
10985 int s
= IEEE_NEGATIVE_ZERO
+ IEEE_POSITIVE_ZERO
;
10986 gcc_assert (IEEE_NEGATIVE_INF
== s
- IEEE_POSITIVE_INF
);
10987 gcc_assert (IEEE_NEGATIVE_NORMAL
== s
- IEEE_POSITIVE_NORMAL
);
10988 gcc_assert (IEEE_NEGATIVE_DENORMAL
== s
- IEEE_POSITIVE_DENORMAL
);
10989 gcc_assert (IEEE_NEGATIVE_SUBNORMAL
== s
- IEEE_POSITIVE_SUBNORMAL
);
10990 gcc_assert (IEEE_NEGATIVE_ZERO
== s
- IEEE_POSITIVE_ZERO
);
10991 t4
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (c
),
10992 build_int_cst (TREE_TYPE (c
), s
), c
);
10993 t3
= fold_build3_loc (input_location
, COND_EXPR
, TREE_TYPE (c
),
10995 t1
= fold_build3_loc (input_location
, COND_EXPR
, TREE_TYPE (c
), t1
,
10996 build_int_cst (TREE_TYPE (c
), IEEE_SIGNALING_NAN
),
10998 tree type
= gfc_typenode_for_spec (&expr
->ts
);
10999 /* Perform a quick sanity check that the return type is
11000 IEEE_CLASS_TYPE derived type defined in
11001 libgfortran/ieee/ieee_arithmetic.F90
11002 Primarily check that it is a derived type with a single
11004 gcc_assert (TREE_CODE (type
) == RECORD_TYPE
);
11005 tree field
= NULL_TREE
;
11006 for (tree f
= TYPE_FIELDS (type
); f
!= NULL_TREE
; f
= DECL_CHAIN (f
))
11007 if (TREE_CODE (f
) == FIELD_DECL
)
11009 gcc_assert (field
== NULL_TREE
);
11012 gcc_assert (field
);
11013 t1
= fold_convert (TREE_TYPE (field
), t1
);
11014 se
->expr
= build_constructor_single (type
, field
, t1
);
11018 /* Generate code for IEEE_VALUE. */
11021 conv_intrinsic_ieee_value (gfc_se
*se
, gfc_expr
*expr
)
11023 tree args
[2], arg
, ret
, tmp
;
11026 /* Convert args, evaluate the second one only once. */
11027 conv_ieee_function_args (se
, expr
, args
, 2);
11028 arg
= gfc_evaluate_now (args
[1], &se
->pre
);
11030 tree type
= TREE_TYPE (arg
);
11031 /* Perform a quick sanity check that the second argument's type is
11032 IEEE_CLASS_TYPE derived type defined in
11033 libgfortran/ieee/ieee_arithmetic.F90
11034 Primarily check that it is a derived type with a single
11036 gcc_assert (TREE_CODE (type
) == RECORD_TYPE
);
11037 tree field
= NULL_TREE
;
11038 for (tree f
= TYPE_FIELDS (type
); f
!= NULL_TREE
; f
= DECL_CHAIN (f
))
11039 if (TREE_CODE (f
) == FIELD_DECL
)
11041 gcc_assert (field
== NULL_TREE
);
11044 gcc_assert (field
);
11045 arg
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
11046 arg
, field
, NULL_TREE
);
11047 arg
= gfc_evaluate_now (arg
, &se
->pre
);
11049 type
= gfc_typenode_for_spec (&expr
->ts
);
11050 gcc_assert (SCALAR_FLOAT_TYPE_P (type
));
11051 ret
= gfc_create_var (type
, NULL
);
11053 gfc_init_block (&body
);
11055 tree end_label
= gfc_build_label_decl (NULL_TREE
);
11056 for (int c
= IEEE_SIGNALING_NAN
; c
<= IEEE_POSITIVE_INF
; ++c
)
11058 tree label
= gfc_build_label_decl (NULL_TREE
);
11059 tree low
= build_int_cst (TREE_TYPE (arg
), c
);
11060 tmp
= build_case_label (low
, low
, label
);
11061 gfc_add_expr_to_block (&body
, tmp
);
11063 REAL_VALUE_TYPE real
;
11067 case IEEE_SIGNALING_NAN
:
11068 real_nan (&real
, "", 0, TYPE_MODE (type
));
11070 case IEEE_QUIET_NAN
:
11071 real_nan (&real
, "", 1, TYPE_MODE (type
));
11073 case IEEE_NEGATIVE_INF
:
11075 real
= real_value_negate (&real
);
11077 case IEEE_NEGATIVE_NORMAL
:
11078 real_from_integer (&real
, TYPE_MODE (type
), -42, SIGNED
);
11080 case IEEE_NEGATIVE_DENORMAL
:
11081 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
11082 real_from_mpfr (&real
, gfc_real_kinds
[k
].tiny
,
11083 type
, GFC_RND_MODE
);
11084 real_arithmetic (&real
, RDIV_EXPR
, &real
, &dconst2
);
11085 real
= real_value_negate (&real
);
11087 case IEEE_NEGATIVE_ZERO
:
11088 real_from_integer (&real
, TYPE_MODE (type
), 0, SIGNED
);
11089 real
= real_value_negate (&real
);
11091 case IEEE_POSITIVE_ZERO
:
11092 /* Make this also the default: label. The other possibility
11093 would be to add a separate default: label followed by
11094 __builtin_unreachable (). */
11095 label
= gfc_build_label_decl (NULL_TREE
);
11096 tmp
= build_case_label (NULL_TREE
, NULL_TREE
, label
);
11097 gfc_add_expr_to_block (&body
, tmp
);
11098 real_from_integer (&real
, TYPE_MODE (type
), 0, SIGNED
);
11100 case IEEE_POSITIVE_DENORMAL
:
11101 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
11102 real_from_mpfr (&real
, gfc_real_kinds
[k
].tiny
,
11103 type
, GFC_RND_MODE
);
11104 real_arithmetic (&real
, RDIV_EXPR
, &real
, &dconst2
);
11106 case IEEE_POSITIVE_NORMAL
:
11107 real_from_integer (&real
, TYPE_MODE (type
), 42, SIGNED
);
11109 case IEEE_POSITIVE_INF
:
11113 gcc_unreachable ();
11116 tree val
= build_real (type
, real
);
11117 gfc_add_modify (&body
, ret
, val
);
11119 tmp
= build1_v (GOTO_EXPR
, end_label
);
11120 gfc_add_expr_to_block (&body
, tmp
);
11123 tmp
= gfc_finish_block (&body
);
11124 tmp
= fold_build2_loc (input_location
, SWITCH_EXPR
, NULL_TREE
, arg
, tmp
);
11125 gfc_add_expr_to_block (&se
->pre
, tmp
);
11127 tmp
= build1_v (LABEL_EXPR
, end_label
);
11128 gfc_add_expr_to_block (&se
->pre
, tmp
);
11134 /* Generate code for IEEE_FMA. */
11137 conv_intrinsic_ieee_fma (gfc_se
* se
, gfc_expr
* expr
)
11139 tree args
[3], decl
, call
;
11142 conv_ieee_function_args (se
, expr
, args
, 3);
11144 /* All three arguments should have the same type. */
11145 gcc_assert (TYPE_PRECISION (TREE_TYPE (args
[0])) == TYPE_PRECISION (TREE_TYPE (args
[1])));
11146 gcc_assert (TYPE_PRECISION (TREE_TYPE (args
[0])) == TYPE_PRECISION (TREE_TYPE (args
[2])));
11148 /* Call the type-generic FMA built-in. */
11149 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
11150 decl
= builtin_decl_for_precision (BUILT_IN_FMA
, argprec
);
11151 call
= build_call_expr_loc_array (input_location
, decl
, 3, args
);
11153 /* Convert to the final type. */
11154 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
11158 /* Generate code for IEEE_{MIN,MAX}_NUM{,_MAG}. */
11161 conv_intrinsic_ieee_minmax (gfc_se
* se
, gfc_expr
* expr
, int max
,
11164 tree args
[2], func
;
11165 built_in_function fn
;
11167 conv_ieee_function_args (se
, expr
, args
, 2);
11168 gcc_assert (TYPE_PRECISION (TREE_TYPE (args
[0])) == TYPE_PRECISION (TREE_TYPE (args
[1])));
11169 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
11170 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
11172 if (startswith (name
, "mag"))
11174 /* IEEE_MIN_NUM_MAG and IEEE_MAX_NUM_MAG translate to C functions
11175 fminmag() and fmaxmag(), which do not exist as built-ins.
11177 Following glibc, we emit this:
11182 if (isless (ax, ay))
11184 else if (isgreater (ax, ay))
11187 return x < y ? x : y;
11188 else if (issignaling (x) || issignaling (y))
11191 return isnan (y) ? x : y;
11197 if (isgreater (ax, ay))
11199 else if (isless (ax, ay))
11202 return x > y ? x : y;
11203 else if (issignaling (x) || issignaling (y))
11206 return isnan (y) ? x : y;
11211 tree abs0
, abs1
, sig0
, sig1
;
11212 tree cond1
, cond2
, cond3
, cond4
, cond5
;
11214 tree type
= TREE_TYPE (args
[0]);
11216 func
= gfc_builtin_decl_for_float_kind (BUILT_IN_FABS
, expr
->ts
.kind
);
11217 abs0
= build_call_expr_loc (input_location
, func
, 1, args
[0]);
11218 abs1
= build_call_expr_loc (input_location
, func
, 1, args
[1]);
11219 abs0
= gfc_evaluate_now (abs0
, &se
->pre
);
11220 abs1
= gfc_evaluate_now (abs1
, &se
->pre
);
11222 cond5
= build_call_expr_loc (input_location
,
11223 builtin_decl_explicit (BUILT_IN_ISNAN
),
11225 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond5
,
11228 sig0
= build_call_expr_loc (input_location
,
11229 builtin_decl_explicit (BUILT_IN_ISSIGNALING
),
11231 sig1
= build_call_expr_loc (input_location
,
11232 builtin_decl_explicit (BUILT_IN_ISSIGNALING
),
11234 cond4
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
11235 logical_type_node
, sig0
, sig1
);
11236 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond4
,
11237 fold_build2_loc (input_location
, PLUS_EXPR
,
11238 type
, args
[0], args
[1]),
11241 cond3
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
11243 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond3
,
11244 fold_build2_loc (input_location
,
11245 max
? MAX_EXPR
: MIN_EXPR
,
11246 type
, args
[0], args
[1]),
11249 func
= builtin_decl_explicit (max
? BUILT_IN_ISLESS
: BUILT_IN_ISGREATER
);
11250 cond2
= build_call_expr_loc (input_location
, func
, 2, abs0
, abs1
);
11251 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond2
,
11254 func
= builtin_decl_explicit (max
? BUILT_IN_ISGREATER
: BUILT_IN_ISLESS
);
11255 cond1
= build_call_expr_loc (input_location
, func
, 2, abs0
, abs1
);
11256 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond1
,
11263 /* IEEE_MIN_NUM and IEEE_MAX_NUM translate to fmin() and fmax(). */
11264 fn
= max
? BUILT_IN_FMAX
: BUILT_IN_FMIN
;
11265 func
= gfc_builtin_decl_for_float_kind (fn
, expr
->ts
.kind
);
11266 se
->expr
= build_call_expr_loc_array (input_location
, func
, 2, args
);
11271 /* Generate code for comparison functions IEEE_QUIET_* and
11272 IEEE_SIGNALING_*. */
11275 conv_intrinsic_ieee_comparison (gfc_se
* se
, gfc_expr
* expr
, int signaling
,
11279 tree arg1
, arg2
, res
;
11281 /* Evaluate arguments only once. */
11282 conv_ieee_function_args (se
, expr
, args
, 2);
11283 arg1
= gfc_evaluate_now (args
[0], &se
->pre
);
11284 arg2
= gfc_evaluate_now (args
[1], &se
->pre
);
11286 if (startswith (name
, "eq"))
11289 res
= build_call_expr_loc (input_location
,
11290 builtin_decl_explicit (BUILT_IN_ISEQSIG
),
11293 res
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
11296 else if (startswith (name
, "ne"))
11300 res
= build_call_expr_loc (input_location
,
11301 builtin_decl_explicit (BUILT_IN_ISEQSIG
),
11303 res
= fold_build1_loc (input_location
, TRUTH_NOT_EXPR
,
11304 logical_type_node
, res
);
11307 res
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
11310 else if (startswith (name
, "ge"))
11313 res
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
11316 res
= build_call_expr_loc (input_location
,
11317 builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL
),
11320 else if (startswith (name
, "gt"))
11323 res
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
11326 res
= build_call_expr_loc (input_location
,
11327 builtin_decl_explicit (BUILT_IN_ISGREATER
),
11330 else if (startswith (name
, "le"))
11333 res
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
,
11336 res
= build_call_expr_loc (input_location
,
11337 builtin_decl_explicit (BUILT_IN_ISLESSEQUAL
),
11340 else if (startswith (name
, "lt"))
11343 res
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
11346 res
= build_call_expr_loc (input_location
,
11347 builtin_decl_explicit (BUILT_IN_ISLESS
),
11351 gcc_unreachable ();
11353 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), res
);
11357 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
11361 gfc_conv_ieee_arithmetic_function (gfc_se
* se
, gfc_expr
* expr
)
11363 const char *name
= expr
->value
.function
.name
;
11365 if (startswith (name
, "_gfortran_ieee_is_nan"))
11366 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISNAN
, 1);
11367 else if (startswith (name
, "_gfortran_ieee_is_finite"))
11368 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISFINITE
, 1);
11369 else if (startswith (name
, "_gfortran_ieee_unordered"))
11370 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISUNORDERED
, 2);
11371 else if (startswith (name
, "_gfortran_ieee_signbit"))
11372 conv_intrinsic_ieee_signbit (se
, expr
);
11373 else if (startswith (name
, "_gfortran_ieee_is_normal"))
11374 conv_intrinsic_ieee_is_normal (se
, expr
);
11375 else if (startswith (name
, "_gfortran_ieee_is_negative"))
11376 conv_intrinsic_ieee_is_negative (se
, expr
);
11377 else if (startswith (name
, "_gfortran_ieee_copy_sign"))
11378 conv_intrinsic_ieee_copy_sign (se
, expr
);
11379 else if (startswith (name
, "_gfortran_ieee_scalb"))
11380 conv_intrinsic_ieee_scalb (se
, expr
);
11381 else if (startswith (name
, "_gfortran_ieee_next_after"))
11382 conv_intrinsic_ieee_next_after (se
, expr
);
11383 else if (startswith (name
, "_gfortran_ieee_rem"))
11384 conv_intrinsic_ieee_rem (se
, expr
);
11385 else if (startswith (name
, "_gfortran_ieee_logb"))
11386 conv_intrinsic_ieee_logb_rint (se
, expr
, BUILT_IN_LOGB
);
11387 else if (startswith (name
, "_gfortran_ieee_rint"))
11388 conv_intrinsic_ieee_logb_rint (se
, expr
, BUILT_IN_RINT
);
11389 else if (startswith (name
, "ieee_class_") && ISDIGIT (name
[11]))
11390 conv_intrinsic_ieee_class (se
, expr
);
11391 else if (startswith (name
, "ieee_value_") && ISDIGIT (name
[11]))
11392 conv_intrinsic_ieee_value (se
, expr
);
11393 else if (startswith (name
, "_gfortran_ieee_fma"))
11394 conv_intrinsic_ieee_fma (se
, expr
);
11395 else if (startswith (name
, "_gfortran_ieee_min_num_"))
11396 conv_intrinsic_ieee_minmax (se
, expr
, 0, name
+ 23);
11397 else if (startswith (name
, "_gfortran_ieee_max_num_"))
11398 conv_intrinsic_ieee_minmax (se
, expr
, 1, name
+ 23);
11399 else if (startswith (name
, "_gfortran_ieee_quiet_"))
11400 conv_intrinsic_ieee_comparison (se
, expr
, 0, name
+ 21);
11401 else if (startswith (name
, "_gfortran_ieee_signaling_"))
11402 conv_intrinsic_ieee_comparison (se
, expr
, 1, name
+ 25);
11404 /* It is not among the functions we translate directly. We return
11405 false, so a library function call is emitted. */
11412 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
11415 gfc_conv_intrinsic_malloc (gfc_se
* se
, gfc_expr
* expr
)
11417 tree arg
, res
, restype
;
11419 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
11420 arg
= fold_convert (size_type_node
, arg
);
11421 res
= build_call_expr_loc (input_location
,
11422 builtin_decl_explicit (BUILT_IN_MALLOC
), 1, arg
);
11423 restype
= gfc_typenode_for_spec (&expr
->ts
);
11424 se
->expr
= fold_convert (restype
, res
);
11428 /* Generate code for an intrinsic function. Some map directly to library
11429 calls, others get special handling. In some cases the name of the function
11430 used depends on the type specifiers. */
11433 gfc_conv_intrinsic_function (gfc_se
* se
, gfc_expr
* expr
)
11439 name
= &expr
->value
.function
.name
[2];
11441 if (expr
->rank
> 0)
11443 lib
= gfc_is_intrinsic_libcall (expr
);
11447 se
->ignore_optional
= 1;
11449 switch (expr
->value
.function
.isym
->id
)
11451 case GFC_ISYM_EOSHIFT
:
11452 case GFC_ISYM_PACK
:
11453 case GFC_ISYM_RESHAPE
:
11454 /* For all of those the first argument specifies the type and the
11455 third is optional. */
11456 conv_generic_with_optional_char_arg (se
, expr
, 1, 3);
11459 case GFC_ISYM_FINDLOC
:
11460 gfc_conv_intrinsic_findloc (se
, expr
);
11463 case GFC_ISYM_MINLOC
:
11464 gfc_conv_intrinsic_minmaxloc (se
, expr
, LT_EXPR
);
11467 case GFC_ISYM_MAXLOC
:
11468 gfc_conv_intrinsic_minmaxloc (se
, expr
, GT_EXPR
);
11472 gfc_conv_intrinsic_funcall (se
, expr
);
11480 switch (expr
->value
.function
.isym
->id
)
11482 case GFC_ISYM_NONE
:
11483 gcc_unreachable ();
11485 case GFC_ISYM_REPEAT
:
11486 gfc_conv_intrinsic_repeat (se
, expr
);
11489 case GFC_ISYM_TRIM
:
11490 gfc_conv_intrinsic_trim (se
, expr
);
11493 case GFC_ISYM_SC_KIND
:
11494 gfc_conv_intrinsic_sc_kind (se
, expr
);
11497 case GFC_ISYM_SI_KIND
:
11498 gfc_conv_intrinsic_si_kind (se
, expr
);
11501 case GFC_ISYM_SL_KIND
:
11502 gfc_conv_intrinsic_sl_kind (se
, expr
);
11505 case GFC_ISYM_SR_KIND
:
11506 gfc_conv_intrinsic_sr_kind (se
, expr
);
11509 case GFC_ISYM_EXPONENT
:
11510 gfc_conv_intrinsic_exponent (se
, expr
);
11513 case GFC_ISYM_SCAN
:
11514 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
11516 fndecl
= gfor_fndecl_string_scan
;
11517 else if (kind
== 4)
11518 fndecl
= gfor_fndecl_string_scan_char4
;
11520 gcc_unreachable ();
11522 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
11525 case GFC_ISYM_VERIFY
:
11526 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
11528 fndecl
= gfor_fndecl_string_verify
;
11529 else if (kind
== 4)
11530 fndecl
= gfor_fndecl_string_verify_char4
;
11532 gcc_unreachable ();
11534 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
11537 case GFC_ISYM_ALLOCATED
:
11538 gfc_conv_allocated (se
, expr
);
11541 case GFC_ISYM_ASSOCIATED
:
11542 gfc_conv_associated(se
, expr
);
11545 case GFC_ISYM_SAME_TYPE_AS
:
11546 gfc_conv_same_type_as (se
, expr
);
11550 gfc_conv_intrinsic_abs (se
, expr
);
11553 case GFC_ISYM_ADJUSTL
:
11554 if (expr
->ts
.kind
== 1)
11555 fndecl
= gfor_fndecl_adjustl
;
11556 else if (expr
->ts
.kind
== 4)
11557 fndecl
= gfor_fndecl_adjustl_char4
;
11559 gcc_unreachable ();
11561 gfc_conv_intrinsic_adjust (se
, expr
, fndecl
);
11564 case GFC_ISYM_ADJUSTR
:
11565 if (expr
->ts
.kind
== 1)
11566 fndecl
= gfor_fndecl_adjustr
;
11567 else if (expr
->ts
.kind
== 4)
11568 fndecl
= gfor_fndecl_adjustr_char4
;
11570 gcc_unreachable ();
11572 gfc_conv_intrinsic_adjust (se
, expr
, fndecl
);
11575 case GFC_ISYM_AIMAG
:
11576 gfc_conv_intrinsic_imagpart (se
, expr
);
11579 case GFC_ISYM_AINT
:
11580 gfc_conv_intrinsic_aint (se
, expr
, RND_TRUNC
);
11584 gfc_conv_intrinsic_anyall (se
, expr
, EQ_EXPR
);
11587 case GFC_ISYM_ANINT
:
11588 gfc_conv_intrinsic_aint (se
, expr
, RND_ROUND
);
11592 gfc_conv_intrinsic_bitop (se
, expr
, BIT_AND_EXPR
);
11596 gfc_conv_intrinsic_anyall (se
, expr
, NE_EXPR
);
11599 case GFC_ISYM_ACOSD
:
11600 case GFC_ISYM_ASIND
:
11601 case GFC_ISYM_ATAND
:
11602 gfc_conv_intrinsic_atrigd (se
, expr
, expr
->value
.function
.isym
->id
);
11605 case GFC_ISYM_COTAN
:
11606 gfc_conv_intrinsic_cotan (se
, expr
);
11609 case GFC_ISYM_COTAND
:
11610 gfc_conv_intrinsic_cotand (se
, expr
);
11613 case GFC_ISYM_ATAN2D
:
11614 gfc_conv_intrinsic_atan2d (se
, expr
);
11617 case GFC_ISYM_BTEST
:
11618 gfc_conv_intrinsic_btest (se
, expr
);
11622 gfc_conv_intrinsic_bitcomp (se
, expr
, GE_EXPR
);
11626 gfc_conv_intrinsic_bitcomp (se
, expr
, GT_EXPR
);
11630 gfc_conv_intrinsic_bitcomp (se
, expr
, LE_EXPR
);
11634 gfc_conv_intrinsic_bitcomp (se
, expr
, LT_EXPR
);
11637 case GFC_ISYM_C_ASSOCIATED
:
11638 case GFC_ISYM_C_FUNLOC
:
11639 case GFC_ISYM_C_LOC
:
11640 case GFC_ISYM_F_C_STRING
:
11641 conv_isocbinding_function (se
, expr
);
11644 case GFC_ISYM_ACHAR
:
11645 case GFC_ISYM_CHAR
:
11646 gfc_conv_intrinsic_char (se
, expr
);
11649 case GFC_ISYM_CONVERSION
:
11650 case GFC_ISYM_DBLE
:
11651 case GFC_ISYM_DFLOAT
:
11652 case GFC_ISYM_FLOAT
:
11653 case GFC_ISYM_LOGICAL
:
11654 case GFC_ISYM_REAL
:
11655 case GFC_ISYM_REALPART
:
11656 case GFC_ISYM_SNGL
:
11657 gfc_conv_intrinsic_conversion (se
, expr
);
11660 /* Integer conversions are handled separately to make sure we get the
11661 correct rounding mode. */
11663 case GFC_ISYM_INT2
:
11664 case GFC_ISYM_INT8
:
11665 case GFC_ISYM_LONG
:
11666 case GFC_ISYM_UINT
:
11667 gfc_conv_intrinsic_int (se
, expr
, RND_TRUNC
);
11670 case GFC_ISYM_NINT
:
11671 gfc_conv_intrinsic_int (se
, expr
, RND_ROUND
);
11674 case GFC_ISYM_CEILING
:
11675 gfc_conv_intrinsic_int (se
, expr
, RND_CEIL
);
11678 case GFC_ISYM_FLOOR
:
11679 gfc_conv_intrinsic_int (se
, expr
, RND_FLOOR
);
11683 gfc_conv_intrinsic_mod (se
, expr
, 0);
11686 case GFC_ISYM_MODULO
:
11687 gfc_conv_intrinsic_mod (se
, expr
, 1);
11690 case GFC_ISYM_CAF_GET
:
11691 gfc_conv_intrinsic_caf_get (se
, expr
, NULL_TREE
, false, NULL
);
11694 case GFC_ISYM_CMPLX
:
11695 gfc_conv_intrinsic_cmplx (se
, expr
, name
[5] == '1');
11698 case GFC_ISYM_COMMAND_ARGUMENT_COUNT
:
11699 gfc_conv_intrinsic_iargc (se
, expr
);
11702 case GFC_ISYM_COMPLEX
:
11703 gfc_conv_intrinsic_cmplx (se
, expr
, 1);
11706 case GFC_ISYM_CONJG
:
11707 gfc_conv_intrinsic_conjg (se
, expr
);
11710 case GFC_ISYM_COUNT
:
11711 gfc_conv_intrinsic_count (se
, expr
);
11714 case GFC_ISYM_CTIME
:
11715 gfc_conv_intrinsic_ctime (se
, expr
);
11719 gfc_conv_intrinsic_dim (se
, expr
);
11722 case GFC_ISYM_DOT_PRODUCT
:
11723 gfc_conv_intrinsic_dot_product (se
, expr
);
11726 case GFC_ISYM_DPROD
:
11727 gfc_conv_intrinsic_dprod (se
, expr
);
11730 case GFC_ISYM_DSHIFTL
:
11731 gfc_conv_intrinsic_dshift (se
, expr
, true);
11734 case GFC_ISYM_DSHIFTR
:
11735 gfc_conv_intrinsic_dshift (se
, expr
, false);
11738 case GFC_ISYM_FDATE
:
11739 gfc_conv_intrinsic_fdate (se
, expr
);
11742 case GFC_ISYM_FRACTION
:
11743 gfc_conv_intrinsic_fraction (se
, expr
);
11746 case GFC_ISYM_IALL
:
11747 gfc_conv_intrinsic_arith (se
, expr
, BIT_AND_EXPR
, false);
11750 case GFC_ISYM_IAND
:
11751 gfc_conv_intrinsic_bitop (se
, expr
, BIT_AND_EXPR
);
11754 case GFC_ISYM_IANY
:
11755 gfc_conv_intrinsic_arith (se
, expr
, BIT_IOR_EXPR
, false);
11758 case GFC_ISYM_IBCLR
:
11759 gfc_conv_intrinsic_singlebitop (se
, expr
, 0);
11762 case GFC_ISYM_IBITS
:
11763 gfc_conv_intrinsic_ibits (se
, expr
);
11766 case GFC_ISYM_IBSET
:
11767 gfc_conv_intrinsic_singlebitop (se
, expr
, 1);
11770 case GFC_ISYM_IACHAR
:
11771 case GFC_ISYM_ICHAR
:
11772 /* We assume ASCII character sequence. */
11773 gfc_conv_intrinsic_ichar (se
, expr
);
11776 case GFC_ISYM_IARGC
:
11777 gfc_conv_intrinsic_iargc (se
, expr
);
11780 case GFC_ISYM_IEOR
:
11781 gfc_conv_intrinsic_bitop (se
, expr
, BIT_XOR_EXPR
);
11784 case GFC_ISYM_INDEX
:
11785 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
11787 fndecl
= gfor_fndecl_string_index
;
11788 else if (kind
== 4)
11789 fndecl
= gfor_fndecl_string_index_char4
;
11791 gcc_unreachable ();
11793 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
11797 gfc_conv_intrinsic_bitop (se
, expr
, BIT_IOR_EXPR
);
11800 case GFC_ISYM_IPARITY
:
11801 gfc_conv_intrinsic_arith (se
, expr
, BIT_XOR_EXPR
, false);
11804 case GFC_ISYM_IS_IOSTAT_END
:
11805 gfc_conv_has_intvalue (se
, expr
, LIBERROR_END
);
11808 case GFC_ISYM_IS_IOSTAT_EOR
:
11809 gfc_conv_has_intvalue (se
, expr
, LIBERROR_EOR
);
11812 case GFC_ISYM_IS_CONTIGUOUS
:
11813 gfc_conv_intrinsic_is_contiguous (se
, expr
);
11816 case GFC_ISYM_ISNAN
:
11817 gfc_conv_intrinsic_isnan (se
, expr
);
11820 case GFC_ISYM_KILL
:
11821 conv_intrinsic_kill (se
, expr
);
11824 case GFC_ISYM_LSHIFT
:
11825 gfc_conv_intrinsic_shift (se
, expr
, false, false);
11828 case GFC_ISYM_RSHIFT
:
11829 gfc_conv_intrinsic_shift (se
, expr
, true, true);
11832 case GFC_ISYM_SHIFTA
:
11833 gfc_conv_intrinsic_shift (se
, expr
, true, true);
11836 case GFC_ISYM_SHIFTL
:
11837 gfc_conv_intrinsic_shift (se
, expr
, false, false);
11840 case GFC_ISYM_SHIFTR
:
11841 gfc_conv_intrinsic_shift (se
, expr
, true, false);
11844 case GFC_ISYM_ISHFT
:
11845 gfc_conv_intrinsic_ishft (se
, expr
);
11848 case GFC_ISYM_ISHFTC
:
11849 gfc_conv_intrinsic_ishftc (se
, expr
);
11852 case GFC_ISYM_LEADZ
:
11853 gfc_conv_intrinsic_leadz (se
, expr
);
11856 case GFC_ISYM_TRAILZ
:
11857 gfc_conv_intrinsic_trailz (se
, expr
);
11860 case GFC_ISYM_POPCNT
:
11861 gfc_conv_intrinsic_popcnt_poppar (se
, expr
, 0);
11864 case GFC_ISYM_POPPAR
:
11865 gfc_conv_intrinsic_popcnt_poppar (se
, expr
, 1);
11868 case GFC_ISYM_LBOUND
:
11869 gfc_conv_intrinsic_bound (se
, expr
, GFC_ISYM_LBOUND
);
11872 case GFC_ISYM_LCOBOUND
:
11873 conv_intrinsic_cobound (se
, expr
);
11876 case GFC_ISYM_TRANSPOSE
:
11877 /* The scalarizer has already been set up for reversed dimension access
11878 order ; now we just get the argument value normally. */
11879 gfc_conv_expr (se
, expr
->value
.function
.actual
->expr
);
11883 gfc_conv_intrinsic_len (se
, expr
);
11886 case GFC_ISYM_LEN_TRIM
:
11887 gfc_conv_intrinsic_len_trim (se
, expr
);
11891 gfc_conv_intrinsic_strcmp (se
, expr
, GE_EXPR
);
11895 gfc_conv_intrinsic_strcmp (se
, expr
, GT_EXPR
);
11899 gfc_conv_intrinsic_strcmp (se
, expr
, LE_EXPR
);
11903 gfc_conv_intrinsic_strcmp (se
, expr
, LT_EXPR
);
11906 case GFC_ISYM_MALLOC
:
11907 gfc_conv_intrinsic_malloc (se
, expr
);
11910 case GFC_ISYM_MASKL
:
11911 gfc_conv_intrinsic_mask (se
, expr
, 1);
11914 case GFC_ISYM_MASKR
:
11915 gfc_conv_intrinsic_mask (se
, expr
, 0);
11919 if (expr
->ts
.type
== BT_CHARACTER
)
11920 gfc_conv_intrinsic_minmax_char (se
, expr
, 1);
11922 gfc_conv_intrinsic_minmax (se
, expr
, GT_EXPR
);
11925 case GFC_ISYM_MAXLOC
:
11926 gfc_conv_intrinsic_minmaxloc (se
, expr
, GT_EXPR
);
11929 case GFC_ISYM_FINDLOC
:
11930 gfc_conv_intrinsic_findloc (se
, expr
);
11933 case GFC_ISYM_MAXVAL
:
11934 gfc_conv_intrinsic_minmaxval (se
, expr
, GT_EXPR
);
11937 case GFC_ISYM_MERGE
:
11938 gfc_conv_intrinsic_merge (se
, expr
);
11941 case GFC_ISYM_MERGE_BITS
:
11942 gfc_conv_intrinsic_merge_bits (se
, expr
);
11946 if (expr
->ts
.type
== BT_CHARACTER
)
11947 gfc_conv_intrinsic_minmax_char (se
, expr
, -1);
11949 gfc_conv_intrinsic_minmax (se
, expr
, LT_EXPR
);
11952 case GFC_ISYM_MINLOC
:
11953 gfc_conv_intrinsic_minmaxloc (se
, expr
, LT_EXPR
);
11956 case GFC_ISYM_MINVAL
:
11957 gfc_conv_intrinsic_minmaxval (se
, expr
, LT_EXPR
);
11960 case GFC_ISYM_NEAREST
:
11961 gfc_conv_intrinsic_nearest (se
, expr
);
11964 case GFC_ISYM_NORM2
:
11965 gfc_conv_intrinsic_arith (se
, expr
, PLUS_EXPR
, true);
11969 gfc_conv_intrinsic_not (se
, expr
);
11973 gfc_conv_intrinsic_bitop (se
, expr
, BIT_IOR_EXPR
);
11976 case GFC_ISYM_OUT_OF_RANGE
:
11977 gfc_conv_intrinsic_out_of_range (se
, expr
);
11980 case GFC_ISYM_PARITY
:
11981 gfc_conv_intrinsic_arith (se
, expr
, NE_EXPR
, false);
11984 case GFC_ISYM_PRESENT
:
11985 gfc_conv_intrinsic_present (se
, expr
);
11988 case GFC_ISYM_PRODUCT
:
11989 gfc_conv_intrinsic_arith (se
, expr
, MULT_EXPR
, false);
11992 case GFC_ISYM_RANK
:
11993 gfc_conv_intrinsic_rank (se
, expr
);
11996 case GFC_ISYM_RRSPACING
:
11997 gfc_conv_intrinsic_rrspacing (se
, expr
);
12000 case GFC_ISYM_SET_EXPONENT
:
12001 gfc_conv_intrinsic_set_exponent (se
, expr
);
12004 case GFC_ISYM_SCALE
:
12005 gfc_conv_intrinsic_scale (se
, expr
);
12008 case GFC_ISYM_SHAPE
:
12009 gfc_conv_intrinsic_bound (se
, expr
, GFC_ISYM_SHAPE
);
12012 case GFC_ISYM_SIGN
:
12013 gfc_conv_intrinsic_sign (se
, expr
);
12016 case GFC_ISYM_SIZE
:
12017 gfc_conv_intrinsic_size (se
, expr
);
12020 case GFC_ISYM_SIZEOF
:
12021 case GFC_ISYM_C_SIZEOF
:
12022 gfc_conv_intrinsic_sizeof (se
, expr
);
12025 case GFC_ISYM_STORAGE_SIZE
:
12026 gfc_conv_intrinsic_storage_size (se
, expr
);
12029 case GFC_ISYM_SPACING
:
12030 gfc_conv_intrinsic_spacing (se
, expr
);
12033 case GFC_ISYM_STRIDE
:
12034 conv_intrinsic_stride (se
, expr
);
12038 gfc_conv_intrinsic_arith (se
, expr
, PLUS_EXPR
, false);
12041 case GFC_ISYM_TEAM_NUMBER
:
12042 conv_intrinsic_team_number (se
, expr
);
12045 case GFC_ISYM_TRANSFER
:
12046 if (se
->ss
&& se
->ss
->info
->useflags
)
12047 /* Access the previously obtained result. */
12048 gfc_conv_tmp_array_ref (se
);
12050 gfc_conv_intrinsic_transfer (se
, expr
);
12053 case GFC_ISYM_TTYNAM
:
12054 gfc_conv_intrinsic_ttynam (se
, expr
);
12057 case GFC_ISYM_UBOUND
:
12058 gfc_conv_intrinsic_bound (se
, expr
, GFC_ISYM_UBOUND
);
12061 case GFC_ISYM_UCOBOUND
:
12062 conv_intrinsic_cobound (se
, expr
);
12066 gfc_conv_intrinsic_bitop (se
, expr
, BIT_XOR_EXPR
);
12070 gfc_conv_intrinsic_loc (se
, expr
);
12073 case GFC_ISYM_THIS_IMAGE
:
12074 /* For num_images() == 1, handle as LCOBOUND. */
12075 if (expr
->value
.function
.actual
->expr
12076 && flag_coarray
== GFC_FCOARRAY_SINGLE
)
12077 conv_intrinsic_cobound (se
, expr
);
12079 trans_this_image (se
, expr
);
12082 case GFC_ISYM_IMAGE_INDEX
:
12083 trans_image_index (se
, expr
);
12086 case GFC_ISYM_IMAGE_STATUS
:
12087 conv_intrinsic_image_status (se
, expr
);
12090 case GFC_ISYM_NUM_IMAGES
:
12091 trans_num_images (se
, expr
);
12094 case GFC_ISYM_ACCESS
:
12095 case GFC_ISYM_CHDIR
:
12096 case GFC_ISYM_CHMOD
:
12097 case GFC_ISYM_DTIME
:
12098 case GFC_ISYM_ETIME
:
12099 case GFC_ISYM_EXTENDS_TYPE_OF
:
12100 case GFC_ISYM_FGET
:
12101 case GFC_ISYM_FGETC
:
12102 case GFC_ISYM_FNUM
:
12103 case GFC_ISYM_FPUT
:
12104 case GFC_ISYM_FPUTC
:
12105 case GFC_ISYM_FSTAT
:
12106 case GFC_ISYM_FTELL
:
12107 case GFC_ISYM_GETCWD
:
12108 case GFC_ISYM_GETGID
:
12109 case GFC_ISYM_GETPID
:
12110 case GFC_ISYM_GETUID
:
12111 case GFC_ISYM_HOSTNM
:
12112 case GFC_ISYM_IERRNO
:
12113 case GFC_ISYM_IRAND
:
12114 case GFC_ISYM_ISATTY
:
12116 case GFC_ISYM_LINK
:
12117 case GFC_ISYM_LSTAT
:
12118 case GFC_ISYM_MATMUL
:
12119 case GFC_ISYM_MCLOCK
:
12120 case GFC_ISYM_MCLOCK8
:
12121 case GFC_ISYM_RAND
:
12122 case GFC_ISYM_RENAME
:
12123 case GFC_ISYM_SECOND
:
12124 case GFC_ISYM_SECNDS
:
12125 case GFC_ISYM_SIGNAL
:
12126 case GFC_ISYM_STAT
:
12127 case GFC_ISYM_SYMLNK
:
12128 case GFC_ISYM_SYSTEM
:
12129 case GFC_ISYM_TIME
:
12130 case GFC_ISYM_TIME8
:
12131 case GFC_ISYM_UMASK
:
12132 case GFC_ISYM_UNLINK
:
12134 gfc_conv_intrinsic_funcall (se
, expr
);
12137 case GFC_ISYM_EOSHIFT
:
12138 case GFC_ISYM_PACK
:
12139 case GFC_ISYM_RESHAPE
:
12140 /* For those, expr->rank should always be >0 and thus the if above the
12141 switch should have matched. */
12142 gcc_unreachable ();
12146 gfc_conv_intrinsic_lib_function (se
, expr
);
12153 walk_inline_intrinsic_transpose (gfc_ss
*ss
, gfc_expr
*expr
)
12155 gfc_ss
*arg_ss
, *tmp_ss
;
12156 gfc_actual_arglist
*arg
;
12158 arg
= expr
->value
.function
.actual
;
12160 gcc_assert (arg
->expr
);
12162 arg_ss
= gfc_walk_subexpr (gfc_ss_terminator
, arg
->expr
);
12163 gcc_assert (arg_ss
!= gfc_ss_terminator
);
12165 for (tmp_ss
= arg_ss
; ; tmp_ss
= tmp_ss
->next
)
12167 if (tmp_ss
->info
->type
!= GFC_SS_SCALAR
12168 && tmp_ss
->info
->type
!= GFC_SS_REFERENCE
)
12170 gcc_assert (tmp_ss
->dimen
== 2);
12172 /* We just invert dimensions. */
12173 std::swap (tmp_ss
->dim
[0], tmp_ss
->dim
[1]);
12176 /* Stop when tmp_ss points to the last valid element of the chain... */
12177 if (tmp_ss
->next
== gfc_ss_terminator
)
12181 /* ... so that we can attach the rest of the chain to it. */
12188 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
12189 This has the side effect of reversing the nested list, so there is no
12190 need to call gfc_reverse_ss on it (the given list is assumed not to be
12194 nest_loop_dimension (gfc_ss
*ss
, int dim
)
12197 gfc_ss
*new_ss
, *prev_ss
= gfc_ss_terminator
;
12198 gfc_loopinfo
*new_loop
;
12200 gcc_assert (ss
!= gfc_ss_terminator
);
12202 for (; ss
!= gfc_ss_terminator
; ss
= ss
->next
)
12204 new_ss
= gfc_get_ss ();
12205 new_ss
->next
= prev_ss
;
12206 new_ss
->parent
= ss
;
12207 new_ss
->info
= ss
->info
;
12208 new_ss
->info
->refcount
++;
12209 if (ss
->dimen
!= 0)
12211 gcc_assert (ss
->info
->type
!= GFC_SS_SCALAR
12212 && ss
->info
->type
!= GFC_SS_REFERENCE
);
12215 new_ss
->dim
[0] = ss
->dim
[dim
];
12217 gcc_assert (dim
< ss
->dimen
);
12219 ss_dim
= --ss
->dimen
;
12220 for (i
= dim
; i
< ss_dim
; i
++)
12221 ss
->dim
[i
] = ss
->dim
[i
+ 1];
12223 ss
->dim
[ss_dim
] = 0;
12229 ss
->nested_ss
->parent
= new_ss
;
12230 new_ss
->nested_ss
= ss
->nested_ss
;
12232 ss
->nested_ss
= new_ss
;
12235 new_loop
= gfc_get_loopinfo ();
12236 gfc_init_loopinfo (new_loop
);
12238 gcc_assert (prev_ss
!= NULL
);
12239 gcc_assert (prev_ss
!= gfc_ss_terminator
);
12240 gfc_add_ss_to_loop (new_loop
, prev_ss
);
12241 return new_ss
->parent
;
12245 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
12246 is to be inlined. */
12249 walk_inline_intrinsic_arith (gfc_ss
*ss
, gfc_expr
*expr
)
12251 gfc_ss
*tmp_ss
, *tail
, *array_ss
;
12252 gfc_actual_arglist
*arg1
, *arg2
, *arg3
;
12254 bool scalar_mask
= false;
12256 /* The rank of the result will be determined later. */
12257 arg1
= expr
->value
.function
.actual
;
12260 gcc_assert (arg3
!= NULL
);
12262 if (expr
->rank
== 0)
12265 tmp_ss
= gfc_ss_terminator
;
12271 mask_ss
= gfc_walk_subexpr (tmp_ss
, arg3
->expr
);
12272 if (mask_ss
== tmp_ss
)
12278 array_ss
= gfc_walk_subexpr (tmp_ss
, arg1
->expr
);
12279 gcc_assert (array_ss
!= tmp_ss
);
12281 /* Odd thing: If the mask is scalar, it is used by the frontend after
12282 the array (to make an if around the nested loop). Thus it shall
12283 be after array_ss once the gfc_ss list is reversed. */
12285 tmp_ss
= gfc_get_scalar_ss (array_ss
, arg3
->expr
);
12289 /* "Hide" the dimension on which we will sum in the first arg's scalarization
12291 sum_dim
= mpz_get_si (arg2
->expr
->value
.integer
) - 1;
12292 tail
= nest_loop_dimension (tmp_ss
, sum_dim
);
12299 /* Create the gfc_ss list for the arguments to MINLOC or MAXLOC when the
12300 function is to be inlined. */
12303 walk_inline_intrinsic_minmaxloc (gfc_ss
*ss
, gfc_expr
*expr ATTRIBUTE_UNUSED
)
12305 if (expr
->rank
== 0)
12308 gfc_actual_arglist
*array_arg
= expr
->value
.function
.actual
;
12309 gfc_actual_arglist
*dim_arg
= array_arg
->next
;
12310 gfc_actual_arglist
*mask_arg
= dim_arg
->next
;
12311 gfc_actual_arglist
*kind_arg
= mask_arg
->next
;
12312 gfc_actual_arglist
*back_arg
= kind_arg
->next
;
12314 gfc_expr
*array
= array_arg
->expr
;
12315 gfc_expr
*dim
= dim_arg
->expr
;
12316 gfc_expr
*mask
= mask_arg
->expr
;
12317 gfc_expr
*back
= back_arg
->expr
;
12319 if (dim
== nullptr)
12320 return gfc_get_array_ss (ss
, expr
, 1, GFC_SS_INTRINSIC
);
12322 gfc_ss
*tmp_ss
= gfc_ss_terminator
;
12324 bool scalar_mask
= false;
12327 gfc_ss
*mask_ss
= gfc_walk_subexpr (tmp_ss
, mask
);
12328 if (mask_ss
== tmp_ss
)
12329 scalar_mask
= true;
12330 else if (maybe_absent_optional_variable (mask
))
12331 mask_ss
->info
->can_be_null_ref
= true;
12336 gfc_ss
*array_ss
= gfc_walk_subexpr (tmp_ss
, array
);
12337 gcc_assert (array_ss
!= tmp_ss
);
12341 /* Move the dimension on which we will sum to a separate nested scalarization
12342 chain, "hiding" that dimension from the outer scalarization. */
12343 int dim_val
= mpz_get_si (dim
->value
.integer
);
12344 gfc_ss
*tail
= nest_loop_dimension (tmp_ss
, dim_val
- 1);
12346 if (back
&& array
->rank
> 1)
12348 /* If there are nested scalarization loops, include BACK in the
12349 scalarization chains to avoid evaluating it multiple times in a loop.
12350 Otherwise, prefer to handle it outside of scalarization. */
12351 gfc_ss
*back_ss
= gfc_get_scalar_ss (ss
, back
);
12352 back_ss
->info
->type
= GFC_SS_REFERENCE
;
12353 if (maybe_absent_optional_variable (back
))
12354 back_ss
->info
->can_be_null_ref
= true;
12356 tail
->next
= back_ss
;
12363 tmp_ss
= gfc_get_scalar_ss (tmp_ss
, mask
);
12364 /* MASK can be a forwarded optional argument, so make the necessary setup
12365 to avoid the scalarizer generating any unguarded pointer dereference in
12367 tmp_ss
->info
->type
= GFC_SS_REFERENCE
;
12368 if (maybe_absent_optional_variable (mask
))
12369 tmp_ss
->info
->can_be_null_ref
= true;
12377 walk_inline_intrinsic_function (gfc_ss
* ss
, gfc_expr
* expr
)
12380 switch (expr
->value
.function
.isym
->id
)
12382 case GFC_ISYM_PRODUCT
:
12384 return walk_inline_intrinsic_arith (ss
, expr
);
12386 case GFC_ISYM_TRANSPOSE
:
12387 return walk_inline_intrinsic_transpose (ss
, expr
);
12389 case GFC_ISYM_MAXLOC
:
12390 case GFC_ISYM_MINLOC
:
12391 return walk_inline_intrinsic_minmaxloc (ss
, expr
);
12394 gcc_unreachable ();
12396 gcc_unreachable ();
12400 /* This generates code to execute before entering the scalarization loop.
12401 Currently does nothing. */
12404 gfc_add_intrinsic_ss_code (gfc_loopinfo
* loop ATTRIBUTE_UNUSED
, gfc_ss
* ss
)
12406 switch (ss
->info
->expr
->value
.function
.isym
->id
)
12408 case GFC_ISYM_UBOUND
:
12409 case GFC_ISYM_LBOUND
:
12410 case GFC_ISYM_UCOBOUND
:
12411 case GFC_ISYM_LCOBOUND
:
12412 case GFC_ISYM_MAXLOC
:
12413 case GFC_ISYM_MINLOC
:
12414 case GFC_ISYM_THIS_IMAGE
:
12415 case GFC_ISYM_SHAPE
:
12419 gcc_unreachable ();
12424 /* The LBOUND, LCOBOUND, UBOUND, UCOBOUND, and SHAPE intrinsics with
12425 one parameter are expanded into code inside the scalarization loop. */
12428 gfc_walk_intrinsic_bound (gfc_ss
* ss
, gfc_expr
* expr
)
12430 if (expr
->value
.function
.actual
->expr
->ts
.type
== BT_CLASS
)
12431 gfc_add_class_array_ref (expr
->value
.function
.actual
->expr
);
12433 /* The two argument version returns a scalar. */
12434 if (expr
->value
.function
.isym
->id
!= GFC_ISYM_SHAPE
12435 && expr
->value
.function
.actual
->next
->expr
)
12438 return gfc_get_array_ss (ss
, expr
, 1, GFC_SS_INTRINSIC
);
12442 /* Walk an intrinsic array libcall. */
12445 gfc_walk_intrinsic_libfunc (gfc_ss
* ss
, gfc_expr
* expr
)
12447 gcc_assert (expr
->rank
> 0);
12448 return gfc_get_array_ss (ss
, expr
, expr
->rank
, GFC_SS_FUNCTION
);
12452 /* Return whether the function call expression EXPR will be expanded
12453 inline by gfc_conv_intrinsic_function. */
12456 gfc_inline_intrinsic_function_p (gfc_expr
*expr
)
12458 gfc_actual_arglist
*args
, *dim_arg
, *mask_arg
;
12459 gfc_expr
*maskexpr
;
12461 gfc_intrinsic_sym
*isym
= expr
->value
.function
.isym
;
12467 case GFC_ISYM_PRODUCT
:
12469 /* Disable inline expansion if code size matters. */
12473 args
= expr
->value
.function
.actual
;
12474 dim_arg
= args
->next
;
12476 /* We need to be able to subset the SUM argument at compile-time. */
12477 if (dim_arg
->expr
&& dim_arg
->expr
->expr_type
!= EXPR_CONSTANT
)
12480 /* FIXME: If MASK is optional for a more than two-dimensional
12481 argument, the scalarizer gets confused if the mask is
12482 absent. See PR 82995. For now, fall back to the library
12485 mask_arg
= dim_arg
->next
;
12486 maskexpr
= mask_arg
->expr
;
12488 if (expr
->rank
> 0 && maskexpr
&& maskexpr
->expr_type
== EXPR_VARIABLE
12489 && maskexpr
->symtree
->n
.sym
->attr
.dummy
12490 && maskexpr
->symtree
->n
.sym
->attr
.optional
)
12495 case GFC_ISYM_TRANSPOSE
:
12498 case GFC_ISYM_MINLOC
:
12499 case GFC_ISYM_MAXLOC
:
12501 if ((isym
->id
== GFC_ISYM_MINLOC
12502 && (flag_inline_intrinsics
12503 & GFC_FLAG_INLINE_INTRINSIC_MINLOC
) == 0)
12504 || (isym
->id
== GFC_ISYM_MAXLOC
12505 && (flag_inline_intrinsics
12506 & GFC_FLAG_INLINE_INTRINSIC_MAXLOC
) == 0))
12509 gfc_actual_arglist
*array_arg
= expr
->value
.function
.actual
;
12510 gfc_actual_arglist
*dim_arg
= array_arg
->next
;
12512 gfc_expr
*array
= array_arg
->expr
;
12513 gfc_expr
*dim
= dim_arg
->expr
;
12515 if (!(array
->ts
.type
== BT_INTEGER
12516 || array
->ts
.type
== BT_REAL
))
12519 if (array
->rank
== 1)
12523 && dim
->expr_type
!= EXPR_CONSTANT
)
12535 /* Returns nonzero if the specified intrinsic function call maps directly to
12536 an external library call. Should only be used for functions that return
12540 gfc_is_intrinsic_libcall (gfc_expr
* expr
)
12542 gcc_assert (expr
->expr_type
== EXPR_FUNCTION
&& expr
->value
.function
.isym
);
12543 gcc_assert (expr
->rank
> 0);
12545 if (gfc_inline_intrinsic_function_p (expr
))
12548 switch (expr
->value
.function
.isym
->id
)
12552 case GFC_ISYM_COUNT
:
12553 case GFC_ISYM_FINDLOC
:
12555 case GFC_ISYM_IANY
:
12556 case GFC_ISYM_IALL
:
12557 case GFC_ISYM_IPARITY
:
12558 case GFC_ISYM_MATMUL
:
12559 case GFC_ISYM_MAXLOC
:
12560 case GFC_ISYM_MAXVAL
:
12561 case GFC_ISYM_MINLOC
:
12562 case GFC_ISYM_MINVAL
:
12563 case GFC_ISYM_NORM2
:
12564 case GFC_ISYM_PARITY
:
12565 case GFC_ISYM_PRODUCT
:
12567 case GFC_ISYM_SPREAD
:
12569 /* Ignore absent optional parameters. */
12572 case GFC_ISYM_CSHIFT
:
12573 case GFC_ISYM_EOSHIFT
:
12574 case GFC_ISYM_GET_TEAM
:
12575 case GFC_ISYM_FAILED_IMAGES
:
12576 case GFC_ISYM_STOPPED_IMAGES
:
12577 case GFC_ISYM_PACK
:
12578 case GFC_ISYM_RESHAPE
:
12579 case GFC_ISYM_UNPACK
:
12580 /* Pass absent optional parameters. */
12588 /* Walk an intrinsic function. */
12590 gfc_walk_intrinsic_function (gfc_ss
* ss
, gfc_expr
* expr
,
12591 gfc_intrinsic_sym
* isym
)
12595 if (isym
->elemental
)
12596 return gfc_walk_elemental_function_args (ss
, expr
->value
.function
.actual
,
12597 expr
->value
.function
.isym
,
12600 if (expr
->rank
== 0 && expr
->corank
== 0)
12603 if (gfc_inline_intrinsic_function_p (expr
))
12604 return walk_inline_intrinsic_function (ss
, expr
);
12606 if (expr
->rank
!= 0 && gfc_is_intrinsic_libcall (expr
))
12607 return gfc_walk_intrinsic_libfunc (ss
, expr
);
12609 /* Special cases. */
12612 case GFC_ISYM_LBOUND
:
12613 case GFC_ISYM_LCOBOUND
:
12614 case GFC_ISYM_UBOUND
:
12615 case GFC_ISYM_UCOBOUND
:
12616 case GFC_ISYM_THIS_IMAGE
:
12617 case GFC_ISYM_SHAPE
:
12618 return gfc_walk_intrinsic_bound (ss
, expr
);
12620 case GFC_ISYM_TRANSFER
:
12621 case GFC_ISYM_CAF_GET
:
12622 return gfc_walk_intrinsic_libfunc (ss
, expr
);
12625 /* This probably meant someone forgot to add an intrinsic to the above
12626 list(s) when they implemented it, or something's gone horribly
12628 gcc_unreachable ();
12633 conv_co_collective (gfc_code
*code
)
12636 stmtblock_t block
, post_block
;
12637 tree fndecl
, array
= NULL_TREE
, strlen
, image_index
, stat
, errmsg
, errmsg_len
;
12638 gfc_expr
*image_idx_expr
, *stat_expr
, *errmsg_expr
, *opr_expr
;
12640 gfc_start_block (&block
);
12641 gfc_init_block (&post_block
);
12643 if (code
->resolved_isym
->id
== GFC_ISYM_CO_REDUCE
)
12645 opr_expr
= code
->ext
.actual
->next
->expr
;
12646 image_idx_expr
= code
->ext
.actual
->next
->next
->expr
;
12647 stat_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
12648 errmsg_expr
= code
->ext
.actual
->next
->next
->next
->next
->expr
;
12653 image_idx_expr
= code
->ext
.actual
->next
->expr
;
12654 stat_expr
= code
->ext
.actual
->next
->next
->expr
;
12655 errmsg_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
12661 gfc_init_se (&argse
, NULL
);
12662 gfc_conv_expr (&argse
, stat_expr
);
12663 gfc_add_block_to_block (&block
, &argse
.pre
);
12664 gfc_add_block_to_block (&post_block
, &argse
.post
);
12666 if (flag_coarray
!= GFC_FCOARRAY_SINGLE
)
12667 stat
= gfc_build_addr_expr (NULL_TREE
, stat
);
12669 else if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
12672 stat
= null_pointer_node
;
12674 /* Early exit for GFC_FCOARRAY_SINGLE. */
12675 if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
12677 if (stat
!= NULL_TREE
)
12679 /* For optional stats, check the pointer is valid before zero'ing. */
12680 if (gfc_expr_attr (stat_expr
).optional
)
12683 stmtblock_t ass_block
;
12684 gfc_start_block (&ass_block
);
12685 gfc_add_modify (&ass_block
, stat
,
12686 fold_convert (TREE_TYPE (stat
),
12687 integer_zero_node
));
12688 tmp
= fold_build2 (NE_EXPR
, logical_type_node
,
12689 gfc_build_addr_expr (NULL_TREE
, stat
),
12690 null_pointer_node
);
12691 tmp
= fold_build3 (COND_EXPR
, void_type_node
, tmp
,
12692 gfc_finish_block (&ass_block
),
12693 build_empty_stmt (input_location
));
12694 gfc_add_expr_to_block (&block
, tmp
);
12697 gfc_add_modify (&block
, stat
,
12698 fold_convert (TREE_TYPE (stat
), integer_zero_node
));
12700 return gfc_finish_block (&block
);
12703 gfc_symbol
*derived
= code
->ext
.actual
->expr
->ts
.type
== BT_DERIVED
12704 ? code
->ext
.actual
->expr
->ts
.u
.derived
: NULL
;
12706 /* Handle the array. */
12707 gfc_init_se (&argse
, NULL
);
12708 if (!derived
|| !derived
->attr
.alloc_comp
12709 || code
->resolved_isym
->id
!= GFC_ISYM_CO_BROADCAST
)
12711 if (code
->ext
.actual
->expr
->rank
== 0)
12713 symbol_attribute attr
;
12714 gfc_clear_attr (&attr
);
12715 gfc_init_se (&argse
, NULL
);
12716 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
12717 gfc_add_block_to_block (&block
, &argse
.pre
);
12718 gfc_add_block_to_block (&post_block
, &argse
.post
);
12719 array
= gfc_conv_scalar_to_descriptor (&argse
, argse
.expr
, attr
);
12720 array
= gfc_build_addr_expr (NULL_TREE
, array
);
12724 argse
.want_pointer
= 1;
12725 gfc_conv_expr_descriptor (&argse
, code
->ext
.actual
->expr
);
12726 array
= argse
.expr
;
12730 gfc_add_block_to_block (&block
, &argse
.pre
);
12731 gfc_add_block_to_block (&post_block
, &argse
.post
);
12733 if (code
->ext
.actual
->expr
->ts
.type
== BT_CHARACTER
)
12734 strlen
= argse
.string_length
;
12736 strlen
= integer_zero_node
;
12739 if (image_idx_expr
)
12741 gfc_init_se (&argse
, NULL
);
12742 gfc_conv_expr (&argse
, image_idx_expr
);
12743 gfc_add_block_to_block (&block
, &argse
.pre
);
12744 gfc_add_block_to_block (&post_block
, &argse
.post
);
12745 image_index
= fold_convert (integer_type_node
, argse
.expr
);
12748 image_index
= integer_zero_node
;
12753 gfc_init_se (&argse
, NULL
);
12754 gfc_conv_expr (&argse
, errmsg_expr
);
12755 gfc_add_block_to_block (&block
, &argse
.pre
);
12756 gfc_add_block_to_block (&post_block
, &argse
.post
);
12757 errmsg
= argse
.expr
;
12758 errmsg_len
= fold_convert (size_type_node
, argse
.string_length
);
12762 errmsg
= null_pointer_node
;
12763 errmsg_len
= build_zero_cst (size_type_node
);
12766 /* Generate the function call. */
12767 switch (code
->resolved_isym
->id
)
12769 case GFC_ISYM_CO_BROADCAST
:
12770 fndecl
= gfor_fndecl_co_broadcast
;
12772 case GFC_ISYM_CO_MAX
:
12773 fndecl
= gfor_fndecl_co_max
;
12775 case GFC_ISYM_CO_MIN
:
12776 fndecl
= gfor_fndecl_co_min
;
12778 case GFC_ISYM_CO_REDUCE
:
12779 fndecl
= gfor_fndecl_co_reduce
;
12781 case GFC_ISYM_CO_SUM
:
12782 fndecl
= gfor_fndecl_co_sum
;
12785 gcc_unreachable ();
12788 if (derived
&& derived
->attr
.alloc_comp
12789 && code
->resolved_isym
->id
== GFC_ISYM_CO_BROADCAST
)
12790 /* The derived type has the attribute 'alloc_comp'. */
12792 tree tmp
= gfc_bcast_alloc_comp (derived
, code
->ext
.actual
->expr
,
12793 code
->ext
.actual
->expr
->rank
,
12794 image_index
, stat
, errmsg
, errmsg_len
);
12795 gfc_add_expr_to_block (&block
, tmp
);
12799 if (code
->resolved_isym
->id
== GFC_ISYM_CO_SUM
12800 || code
->resolved_isym
->id
== GFC_ISYM_CO_BROADCAST
)
12801 fndecl
= build_call_expr_loc (input_location
, fndecl
, 5, array
,
12802 image_index
, stat
, errmsg
, errmsg_len
);
12803 else if (code
->resolved_isym
->id
!= GFC_ISYM_CO_REDUCE
)
12804 fndecl
= build_call_expr_loc (input_location
, fndecl
, 6, array
,
12805 image_index
, stat
, errmsg
,
12806 strlen
, errmsg_len
);
12809 tree opr
, opr_flags
;
12811 // FIXME: Handle TS29113's bind(C) strings with descriptor.
12813 if (gfc_is_proc_ptr_comp (opr_expr
))
12815 gfc_symbol
*sym
= gfc_get_proc_ptr_comp (opr_expr
)->ts
.interface
;
12816 opr_flag_int
= sym
->attr
.dimension
12817 || (sym
->ts
.type
== BT_CHARACTER
12818 && !sym
->attr
.is_bind_c
)
12819 ? GFC_CAF_BYREF
: 0;
12820 opr_flag_int
|= opr_expr
->ts
.type
== BT_CHARACTER
12821 && !sym
->attr
.is_bind_c
12822 ? GFC_CAF_HIDDENLEN
: 0;
12823 opr_flag_int
|= sym
->formal
->sym
->attr
.value
12824 ? GFC_CAF_ARG_VALUE
: 0;
12828 opr_flag_int
= gfc_return_by_reference (opr_expr
->symtree
->n
.sym
)
12829 ? GFC_CAF_BYREF
: 0;
12830 opr_flag_int
|= opr_expr
->ts
.type
== BT_CHARACTER
12831 && !opr_expr
->symtree
->n
.sym
->attr
.is_bind_c
12832 ? GFC_CAF_HIDDENLEN
: 0;
12833 opr_flag_int
|= opr_expr
->symtree
->n
.sym
->formal
->sym
->attr
.value
12834 ? GFC_CAF_ARG_VALUE
: 0;
12836 opr_flags
= build_int_cst (integer_type_node
, opr_flag_int
);
12837 gfc_conv_expr (&argse
, opr_expr
);
12839 fndecl
= build_call_expr_loc (input_location
, fndecl
, 8, array
, opr
,
12840 opr_flags
, image_index
, stat
, errmsg
,
12841 strlen
, errmsg_len
);
12845 gfc_add_expr_to_block (&block
, fndecl
);
12846 gfc_add_block_to_block (&block
, &post_block
);
12848 return gfc_finish_block (&block
);
12853 conv_intrinsic_atomic_op (gfc_code
*code
)
12856 tree tmp
, atom
, value
, old
= NULL_TREE
, stat
= NULL_TREE
;
12857 stmtblock_t block
, post_block
;
12858 gfc_expr
*atom_expr
= code
->ext
.actual
->expr
;
12859 gfc_expr
*stat_expr
;
12860 built_in_function fn
;
12862 if (atom_expr
->expr_type
== EXPR_FUNCTION
12863 && atom_expr
->value
.function
.isym
12864 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
12865 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
12867 gfc_start_block (&block
);
12868 gfc_init_block (&post_block
);
12870 gfc_init_se (&argse
, NULL
);
12871 argse
.want_pointer
= 1;
12872 gfc_conv_expr (&argse
, atom_expr
);
12873 gfc_add_block_to_block (&block
, &argse
.pre
);
12874 gfc_add_block_to_block (&post_block
, &argse
.post
);
12877 gfc_init_se (&argse
, NULL
);
12878 if (flag_coarray
== GFC_FCOARRAY_LIB
12879 && code
->ext
.actual
->next
->expr
->ts
.kind
== atom_expr
->ts
.kind
)
12880 argse
.want_pointer
= 1;
12881 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->expr
);
12882 gfc_add_block_to_block (&block
, &argse
.pre
);
12883 gfc_add_block_to_block (&post_block
, &argse
.post
);
12884 value
= argse
.expr
;
12886 switch (code
->resolved_isym
->id
)
12888 case GFC_ISYM_ATOMIC_ADD
:
12889 case GFC_ISYM_ATOMIC_AND
:
12890 case GFC_ISYM_ATOMIC_DEF
:
12891 case GFC_ISYM_ATOMIC_OR
:
12892 case GFC_ISYM_ATOMIC_XOR
:
12893 stat_expr
= code
->ext
.actual
->next
->next
->expr
;
12894 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12895 old
= null_pointer_node
;
12898 gfc_init_se (&argse
, NULL
);
12899 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12900 argse
.want_pointer
= 1;
12901 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->expr
);
12902 gfc_add_block_to_block (&block
, &argse
.pre
);
12903 gfc_add_block_to_block (&post_block
, &argse
.post
);
12905 stat_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
12909 if (stat_expr
!= NULL
)
12911 gcc_assert (stat_expr
->expr_type
== EXPR_VARIABLE
);
12912 gfc_init_se (&argse
, NULL
);
12913 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12914 argse
.want_pointer
= 1;
12915 gfc_conv_expr_val (&argse
, stat_expr
);
12916 gfc_add_block_to_block (&block
, &argse
.pre
);
12917 gfc_add_block_to_block (&post_block
, &argse
.post
);
12920 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
12921 stat
= null_pointer_node
;
12923 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12925 tree image_index
, caf_decl
, offset
, token
;
12928 switch (code
->resolved_isym
->id
)
12930 case GFC_ISYM_ATOMIC_ADD
:
12931 case GFC_ISYM_ATOMIC_FETCH_ADD
:
12932 op
= (int) GFC_CAF_ATOMIC_ADD
;
12934 case GFC_ISYM_ATOMIC_AND
:
12935 case GFC_ISYM_ATOMIC_FETCH_AND
:
12936 op
= (int) GFC_CAF_ATOMIC_AND
;
12938 case GFC_ISYM_ATOMIC_OR
:
12939 case GFC_ISYM_ATOMIC_FETCH_OR
:
12940 op
= (int) GFC_CAF_ATOMIC_OR
;
12942 case GFC_ISYM_ATOMIC_XOR
:
12943 case GFC_ISYM_ATOMIC_FETCH_XOR
:
12944 op
= (int) GFC_CAF_ATOMIC_XOR
;
12946 case GFC_ISYM_ATOMIC_DEF
:
12947 op
= 0; /* Unused. */
12950 gcc_unreachable ();
12953 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
12954 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
12955 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
12957 if (gfc_is_coindexed (atom_expr
))
12958 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
12960 image_index
= integer_zero_node
;
12962 if (!POINTER_TYPE_P (TREE_TYPE (value
)))
12964 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (atom
)), "value");
12965 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), value
));
12966 value
= gfc_build_addr_expr (NULL_TREE
, tmp
);
12969 gfc_init_se (&argse
, NULL
);
12970 gfc_get_caf_token_offset (&argse
, &token
, &offset
, caf_decl
, atom
,
12973 gfc_add_block_to_block (&block
, &argse
.pre
);
12974 if (code
->resolved_isym
->id
== GFC_ISYM_ATOMIC_DEF
)
12975 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_def
, 7,
12976 token
, offset
, image_index
, value
, stat
,
12977 build_int_cst (integer_type_node
,
12978 (int) atom_expr
->ts
.type
),
12979 build_int_cst (integer_type_node
,
12980 (int) atom_expr
->ts
.kind
));
12982 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_op
, 9,
12983 build_int_cst (integer_type_node
, op
),
12984 token
, offset
, image_index
, value
, old
, stat
,
12985 build_int_cst (integer_type_node
,
12986 (int) atom_expr
->ts
.type
),
12987 build_int_cst (integer_type_node
,
12988 (int) atom_expr
->ts
.kind
));
12990 gfc_add_expr_to_block (&block
, tmp
);
12991 gfc_add_block_to_block (&block
, &argse
.post
);
12992 gfc_add_block_to_block (&block
, &post_block
);
12993 return gfc_finish_block (&block
);
12997 switch (code
->resolved_isym
->id
)
12999 case GFC_ISYM_ATOMIC_ADD
:
13000 case GFC_ISYM_ATOMIC_FETCH_ADD
:
13001 fn
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
13003 case GFC_ISYM_ATOMIC_AND
:
13004 case GFC_ISYM_ATOMIC_FETCH_AND
:
13005 fn
= BUILT_IN_ATOMIC_FETCH_AND_N
;
13007 case GFC_ISYM_ATOMIC_DEF
:
13008 fn
= BUILT_IN_ATOMIC_STORE_N
;
13010 case GFC_ISYM_ATOMIC_OR
:
13011 case GFC_ISYM_ATOMIC_FETCH_OR
:
13012 fn
= BUILT_IN_ATOMIC_FETCH_OR_N
;
13014 case GFC_ISYM_ATOMIC_XOR
:
13015 case GFC_ISYM_ATOMIC_FETCH_XOR
:
13016 fn
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
13019 gcc_unreachable ();
13022 tmp
= TREE_TYPE (TREE_TYPE (atom
));
13023 fn
= (built_in_function
) ((int) fn
13024 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
13026 tree itype
= TREE_TYPE (TREE_TYPE (atom
));
13027 tmp
= builtin_decl_explicit (fn
);
13029 switch (code
->resolved_isym
->id
)
13031 case GFC_ISYM_ATOMIC_ADD
:
13032 case GFC_ISYM_ATOMIC_AND
:
13033 case GFC_ISYM_ATOMIC_DEF
:
13034 case GFC_ISYM_ATOMIC_OR
:
13035 case GFC_ISYM_ATOMIC_XOR
:
13036 tmp
= build_call_expr_loc (input_location
, tmp
, 3, atom
,
13037 fold_convert (itype
, value
),
13038 build_int_cst (NULL
, MEMMODEL_RELAXED
));
13039 gfc_add_expr_to_block (&block
, tmp
);
13042 tmp
= build_call_expr_loc (input_location
, tmp
, 3, atom
,
13043 fold_convert (itype
, value
),
13044 build_int_cst (NULL
, MEMMODEL_RELAXED
));
13045 gfc_add_modify (&block
, old
, fold_convert (TREE_TYPE (old
), tmp
));
13049 if (stat
!= NULL_TREE
)
13050 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
13051 gfc_add_block_to_block (&block
, &post_block
);
13052 return gfc_finish_block (&block
);
13057 conv_intrinsic_atomic_ref (gfc_code
*code
)
13060 tree tmp
, atom
, value
, stat
= NULL_TREE
;
13061 stmtblock_t block
, post_block
;
13062 built_in_function fn
;
13063 gfc_expr
*atom_expr
= code
->ext
.actual
->next
->expr
;
13065 if (atom_expr
->expr_type
== EXPR_FUNCTION
13066 && atom_expr
->value
.function
.isym
13067 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
13068 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
13070 gfc_start_block (&block
);
13071 gfc_init_block (&post_block
);
13072 gfc_init_se (&argse
, NULL
);
13073 argse
.want_pointer
= 1;
13074 gfc_conv_expr (&argse
, atom_expr
);
13075 gfc_add_block_to_block (&block
, &argse
.pre
);
13076 gfc_add_block_to_block (&post_block
, &argse
.post
);
13079 gfc_init_se (&argse
, NULL
);
13080 if (flag_coarray
== GFC_FCOARRAY_LIB
13081 && code
->ext
.actual
->expr
->ts
.kind
== atom_expr
->ts
.kind
)
13082 argse
.want_pointer
= 1;
13083 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
13084 gfc_add_block_to_block (&block
, &argse
.pre
);
13085 gfc_add_block_to_block (&post_block
, &argse
.post
);
13086 value
= argse
.expr
;
13089 if (code
->ext
.actual
->next
->next
->expr
!= NULL
)
13091 gcc_assert (code
->ext
.actual
->next
->next
->expr
->expr_type
13093 gfc_init_se (&argse
, NULL
);
13094 if (flag_coarray
== GFC_FCOARRAY_LIB
)
13095 argse
.want_pointer
= 1;
13096 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->next
->expr
);
13097 gfc_add_block_to_block (&block
, &argse
.pre
);
13098 gfc_add_block_to_block (&post_block
, &argse
.post
);
13101 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
13102 stat
= null_pointer_node
;
13104 if (flag_coarray
== GFC_FCOARRAY_LIB
)
13106 tree image_index
, caf_decl
, offset
, token
;
13107 tree orig_value
= NULL_TREE
, vardecl
= NULL_TREE
;
13109 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
13110 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
13111 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
13113 if (gfc_is_coindexed (atom_expr
))
13114 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
13116 image_index
= integer_zero_node
;
13118 gfc_init_se (&argse
, NULL
);
13119 gfc_get_caf_token_offset (&argse
, &token
, &offset
, caf_decl
, atom
,
13121 gfc_add_block_to_block (&block
, &argse
.pre
);
13123 /* Different type, need type conversion. */
13124 if (!POINTER_TYPE_P (TREE_TYPE (value
)))
13126 vardecl
= gfc_create_var (TREE_TYPE (TREE_TYPE (atom
)), "value");
13127 orig_value
= value
;
13128 value
= gfc_build_addr_expr (NULL_TREE
, vardecl
);
13131 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_ref
, 7,
13132 token
, offset
, image_index
, value
, stat
,
13133 build_int_cst (integer_type_node
,
13134 (int) atom_expr
->ts
.type
),
13135 build_int_cst (integer_type_node
,
13136 (int) atom_expr
->ts
.kind
));
13137 gfc_add_expr_to_block (&block
, tmp
);
13138 if (vardecl
!= NULL_TREE
)
13139 gfc_add_modify (&block
, orig_value
,
13140 fold_convert (TREE_TYPE (orig_value
), vardecl
));
13141 gfc_add_block_to_block (&block
, &argse
.post
);
13142 gfc_add_block_to_block (&block
, &post_block
);
13143 return gfc_finish_block (&block
);
13146 tmp
= TREE_TYPE (TREE_TYPE (atom
));
13147 fn
= (built_in_function
) ((int) BUILT_IN_ATOMIC_LOAD_N
13148 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
13150 tmp
= builtin_decl_explicit (fn
);
13151 tmp
= build_call_expr_loc (input_location
, tmp
, 2, atom
,
13152 build_int_cst (integer_type_node
,
13153 MEMMODEL_RELAXED
));
13154 gfc_add_modify (&block
, value
, fold_convert (TREE_TYPE (value
), tmp
));
13156 if (stat
!= NULL_TREE
)
13157 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
13158 gfc_add_block_to_block (&block
, &post_block
);
13159 return gfc_finish_block (&block
);
13164 conv_intrinsic_atomic_cas (gfc_code
*code
)
13167 tree tmp
, atom
, old
, new_val
, comp
, stat
= NULL_TREE
;
13168 stmtblock_t block
, post_block
;
13169 built_in_function fn
;
13170 gfc_expr
*atom_expr
= code
->ext
.actual
->expr
;
13172 if (atom_expr
->expr_type
== EXPR_FUNCTION
13173 && atom_expr
->value
.function
.isym
13174 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
13175 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
13177 gfc_init_block (&block
);
13178 gfc_init_block (&post_block
);
13179 gfc_init_se (&argse
, NULL
);
13180 argse
.want_pointer
= 1;
13181 gfc_conv_expr (&argse
, atom_expr
);
13184 gfc_init_se (&argse
, NULL
);
13185 if (flag_coarray
== GFC_FCOARRAY_LIB
)
13186 argse
.want_pointer
= 1;
13187 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->expr
);
13188 gfc_add_block_to_block (&block
, &argse
.pre
);
13189 gfc_add_block_to_block (&post_block
, &argse
.post
);
13192 gfc_init_se (&argse
, NULL
);
13193 if (flag_coarray
== GFC_FCOARRAY_LIB
)
13194 argse
.want_pointer
= 1;
13195 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->expr
);
13196 gfc_add_block_to_block (&block
, &argse
.pre
);
13197 gfc_add_block_to_block (&post_block
, &argse
.post
);
13200 gfc_init_se (&argse
, NULL
);
13201 if (flag_coarray
== GFC_FCOARRAY_LIB
13202 && code
->ext
.actual
->next
->next
->next
->expr
->ts
.kind
13203 == atom_expr
->ts
.kind
)
13204 argse
.want_pointer
= 1;
13205 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->next
->expr
);
13206 gfc_add_block_to_block (&block
, &argse
.pre
);
13207 gfc_add_block_to_block (&post_block
, &argse
.post
);
13208 new_val
= argse
.expr
;
13211 if (code
->ext
.actual
->next
->next
->next
->next
->expr
!= NULL
)
13213 gcc_assert (code
->ext
.actual
->next
->next
->next
->next
->expr
->expr_type
13215 gfc_init_se (&argse
, NULL
);
13216 if (flag_coarray
== GFC_FCOARRAY_LIB
)
13217 argse
.want_pointer
= 1;
13218 gfc_conv_expr_val (&argse
,
13219 code
->ext
.actual
->next
->next
->next
->next
->expr
);
13220 gfc_add_block_to_block (&block
, &argse
.pre
);
13221 gfc_add_block_to_block (&post_block
, &argse
.post
);
13224 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
13225 stat
= null_pointer_node
;
13227 if (flag_coarray
== GFC_FCOARRAY_LIB
)
13229 tree image_index
, caf_decl
, offset
, token
;
13231 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
13232 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
13233 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
13235 if (gfc_is_coindexed (atom_expr
))
13236 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
13238 image_index
= integer_zero_node
;
13240 if (TREE_TYPE (TREE_TYPE (new_val
)) != TREE_TYPE (TREE_TYPE (old
)))
13242 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (old
)), "new");
13243 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), new_val
));
13244 new_val
= gfc_build_addr_expr (NULL_TREE
, tmp
);
13247 /* Convert a constant to a pointer. */
13248 if (!POINTER_TYPE_P (TREE_TYPE (comp
)))
13250 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (old
)), "comp");
13251 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), comp
));
13252 comp
= gfc_build_addr_expr (NULL_TREE
, tmp
);
13255 gfc_init_se (&argse
, NULL
);
13256 gfc_get_caf_token_offset (&argse
, &token
, &offset
, caf_decl
, atom
,
13258 gfc_add_block_to_block (&block
, &argse
.pre
);
13260 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_cas
, 9,
13261 token
, offset
, image_index
, old
, comp
, new_val
,
13262 stat
, build_int_cst (integer_type_node
,
13263 (int) atom_expr
->ts
.type
),
13264 build_int_cst (integer_type_node
,
13265 (int) atom_expr
->ts
.kind
));
13266 gfc_add_expr_to_block (&block
, tmp
);
13267 gfc_add_block_to_block (&block
, &argse
.post
);
13268 gfc_add_block_to_block (&block
, &post_block
);
13269 return gfc_finish_block (&block
);
13272 tmp
= TREE_TYPE (TREE_TYPE (atom
));
13273 fn
= (built_in_function
) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
13274 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
13276 tmp
= builtin_decl_explicit (fn
);
13278 gfc_add_modify (&block
, old
, comp
);
13279 tmp
= build_call_expr_loc (input_location
, tmp
, 6, atom
,
13280 gfc_build_addr_expr (NULL
, old
),
13281 fold_convert (TREE_TYPE (old
), new_val
),
13282 boolean_false_node
,
13283 build_int_cst (NULL
, MEMMODEL_RELAXED
),
13284 build_int_cst (NULL
, MEMMODEL_RELAXED
));
13285 gfc_add_expr_to_block (&block
, tmp
);
13287 if (stat
!= NULL_TREE
)
13288 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
13289 gfc_add_block_to_block (&block
, &post_block
);
13290 return gfc_finish_block (&block
);
13294 conv_intrinsic_event_query (gfc_code
*code
)
13297 tree stat
= NULL_TREE
, stat2
= NULL_TREE
;
13298 tree count
= NULL_TREE
, count2
= NULL_TREE
;
13300 gfc_expr
*event_expr
= code
->ext
.actual
->expr
;
13302 if (code
->ext
.actual
->next
->next
->expr
)
13304 gcc_assert (code
->ext
.actual
->next
->next
->expr
->expr_type
13306 gfc_init_se (&argse
, NULL
);
13307 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->next
->expr
);
13310 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
13311 stat
= null_pointer_node
;
13313 if (code
->ext
.actual
->next
->expr
)
13315 gcc_assert (code
->ext
.actual
->next
->expr
->expr_type
== EXPR_VARIABLE
);
13316 gfc_init_se (&argse
, NULL
);
13317 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->expr
);
13318 count
= argse
.expr
;
13321 gfc_start_block (&se
.pre
);
13322 if (flag_coarray
== GFC_FCOARRAY_LIB
)
13324 tree tmp
, token
, image_index
;
13325 tree index
= build_zero_cst (gfc_array_index_type
);
13327 if (event_expr
->expr_type
== EXPR_FUNCTION
13328 && event_expr
->value
.function
.isym
13329 && event_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
13330 event_expr
= event_expr
->value
.function
.actual
->expr
;
13332 tree caf_decl
= gfc_get_tree_for_caf_expr (event_expr
);
13334 if (event_expr
->symtree
->n
.sym
->ts
.type
!= BT_DERIVED
13335 || event_expr
->symtree
->n
.sym
->ts
.u
.derived
->from_intmod
13336 != INTMOD_ISO_FORTRAN_ENV
13337 || event_expr
->symtree
->n
.sym
->ts
.u
.derived
->intmod_sym_id
13338 != ISOFORTRAN_EVENT_TYPE
)
13340 gfc_error ("Sorry, the event component of derived type at %L is not "
13341 "yet supported", &event_expr
->where
);
13345 if (gfc_is_coindexed (event_expr
))
13347 gfc_error ("The event variable at %L shall not be coindexed",
13348 &event_expr
->where
);
13352 image_index
= integer_zero_node
;
13354 gfc_get_caf_token_offset (&se
, &token
, NULL
, caf_decl
, NULL_TREE
,
13357 /* For arrays, obtain the array index. */
13358 if (gfc_expr_attr (event_expr
).dimension
)
13360 tree desc
, tmp
, extent
, lbound
, ubound
;
13361 gfc_array_ref
*ar
, ar2
;
13364 /* TODO: Extend this, once DT components are supported. */
13365 ar
= &event_expr
->ref
->u
.ar
;
13367 memset (ar
, '\0', sizeof (*ar
));
13369 ar
->type
= AR_FULL
;
13371 gfc_init_se (&argse
, NULL
);
13372 argse
.descriptor_only
= 1;
13373 gfc_conv_expr_descriptor (&argse
, event_expr
);
13374 gfc_add_block_to_block (&se
.pre
, &argse
.pre
);
13378 extent
= build_one_cst (gfc_array_index_type
);
13379 for (i
= 0; i
< ar
->dimen
; i
++)
13381 gfc_init_se (&argse
, NULL
);
13382 gfc_conv_expr_type (&argse
, ar
->start
[i
], gfc_array_index_type
);
13383 gfc_add_block_to_block (&argse
.pre
, &argse
.pre
);
13384 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[i
]);
13385 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
13386 TREE_TYPE (lbound
), argse
.expr
, lbound
);
13387 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
13388 TREE_TYPE (tmp
), extent
, tmp
);
13389 index
= fold_build2_loc (input_location
, PLUS_EXPR
,
13390 TREE_TYPE (tmp
), index
, tmp
);
13391 if (i
< ar
->dimen
- 1)
13393 ubound
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[i
]);
13394 tmp
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
13395 extent
= fold_build2_loc (input_location
, MULT_EXPR
,
13396 TREE_TYPE (tmp
), extent
, tmp
);
13401 if (count
!= null_pointer_node
&& TREE_TYPE (count
) != integer_type_node
)
13404 count
= gfc_create_var (integer_type_node
, "count");
13407 if (stat
!= null_pointer_node
&& TREE_TYPE (stat
) != integer_type_node
)
13410 stat
= gfc_create_var (integer_type_node
, "stat");
13413 index
= fold_convert (size_type_node
, index
);
13414 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_event_query
, 5,
13415 token
, index
, image_index
, count
13416 ? gfc_build_addr_expr (NULL
, count
) : count
,
13417 stat
!= null_pointer_node
13418 ? gfc_build_addr_expr (NULL
, stat
) : stat
);
13419 gfc_add_expr_to_block (&se
.pre
, tmp
);
13421 if (count2
!= NULL_TREE
)
13422 gfc_add_modify (&se
.pre
, count2
,
13423 fold_convert (TREE_TYPE (count2
), count
));
13425 if (stat2
!= NULL_TREE
)
13426 gfc_add_modify (&se
.pre
, stat2
,
13427 fold_convert (TREE_TYPE (stat2
), stat
));
13429 return gfc_finish_block (&se
.pre
);
13432 gfc_init_se (&argse
, NULL
);
13433 gfc_conv_expr_val (&argse
, code
->ext
.actual
->expr
);
13434 gfc_add_modify (&se
.pre
, count
, fold_convert (TREE_TYPE (count
), argse
.expr
));
13436 if (stat
!= NULL_TREE
)
13437 gfc_add_modify (&se
.pre
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
13439 return gfc_finish_block (&se
.pre
);
13443 /* This is a peculiar case because of the need to do dependency checking.
13444 It is called via trans-stmt.cc(gfc_trans_call), where it is picked out as
13445 a special case and this function called instead of
13446 gfc_conv_procedure_call. */
13448 gfc_conv_intrinsic_mvbits (gfc_se
*se
, gfc_actual_arglist
*actual_args
,
13449 gfc_loopinfo
*loop
)
13451 gfc_actual_arglist
*actual
;
13457 tree from
, frompos
, len
, to
, topos
;
13458 tree lenmask
, oldbits
, newbits
, bitsize
;
13459 tree type
, utype
, above
, mask1
, mask2
;
13464 lss
= gfc_ss_terminator
;
13466 actual
= actual_args
;
13467 for (n
= 0; n
< 5; n
++, actual
= actual
->next
)
13469 arg
[n
] = actual
->expr
;
13470 gfc_init_se (&argse
[n
], NULL
);
13472 if (lss
!= gfc_ss_terminator
)
13474 gfc_copy_loopinfo_to_se (&argse
[n
], loop
);
13475 /* Find the ss for the expression if it is there. */
13477 gfc_mark_ss_chain_used (lss
, 1);
13480 gfc_conv_expr (&argse
[n
], arg
[n
]);
13486 from
= argse
[0].expr
;
13487 frompos
= argse
[1].expr
;
13488 len
= argse
[2].expr
;
13489 to
= argse
[3].expr
;
13490 topos
= argse
[4].expr
;
13492 /* The type of the result (TO). */
13493 type
= TREE_TYPE (to
);
13494 bitsize
= build_int_cst (integer_type_node
, TYPE_PRECISION (type
));
13496 /* Optionally generate code for runtime argument check. */
13497 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
13499 tree nbits
, below
, ccond
;
13500 tree fp
= fold_convert (long_integer_type_node
, frompos
);
13501 tree ln
= fold_convert (long_integer_type_node
, len
);
13502 tree tp
= fold_convert (long_integer_type_node
, topos
);
13503 below
= fold_build2_loc (input_location
, LT_EXPR
,
13504 logical_type_node
, frompos
,
13505 build_int_cst (TREE_TYPE (frompos
), 0));
13506 above
= fold_build2_loc (input_location
, GT_EXPR
,
13507 logical_type_node
, frompos
,
13508 fold_convert (TREE_TYPE (frompos
), bitsize
));
13509 ccond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
13510 logical_type_node
, below
, above
);
13511 gfc_trans_runtime_check (true, false, ccond
, &argse
[1].pre
,
13513 "FROMPOS argument (%ld) out of range 0:%d "
13514 "in intrinsic MVBITS", fp
, bitsize
);
13515 below
= fold_build2_loc (input_location
, LT_EXPR
,
13516 logical_type_node
, len
,
13517 build_int_cst (TREE_TYPE (len
), 0));
13518 above
= fold_build2_loc (input_location
, GT_EXPR
,
13519 logical_type_node
, len
,
13520 fold_convert (TREE_TYPE (len
), bitsize
));
13521 ccond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
13522 logical_type_node
, below
, above
);
13523 gfc_trans_runtime_check (true, false, ccond
, &argse
[2].pre
,
13525 "LEN argument (%ld) out of range 0:%d "
13526 "in intrinsic MVBITS", ln
, bitsize
);
13527 below
= fold_build2_loc (input_location
, LT_EXPR
,
13528 logical_type_node
, topos
,
13529 build_int_cst (TREE_TYPE (topos
), 0));
13530 above
= fold_build2_loc (input_location
, GT_EXPR
,
13531 logical_type_node
, topos
,
13532 fold_convert (TREE_TYPE (topos
), bitsize
));
13533 ccond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
13534 logical_type_node
, below
, above
);
13535 gfc_trans_runtime_check (true, false, ccond
, &argse
[4].pre
,
13537 "TOPOS argument (%ld) out of range 0:%d "
13538 "in intrinsic MVBITS", tp
, bitsize
);
13540 /* The tests above ensure that FROMPOS, LEN and TOPOS fit into short
13541 integers. Additions below cannot overflow. */
13542 nbits
= fold_convert (long_integer_type_node
, bitsize
);
13543 above
= fold_build2_loc (input_location
, PLUS_EXPR
,
13544 long_integer_type_node
, fp
, ln
);
13545 ccond
= fold_build2_loc (input_location
, GT_EXPR
,
13546 logical_type_node
, above
, nbits
);
13547 gfc_trans_runtime_check (true, false, ccond
, &argse
[1].pre
,
13549 "FROMPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
13550 "in intrinsic MVBITS", fp
, ln
, bitsize
);
13551 above
= fold_build2_loc (input_location
, PLUS_EXPR
,
13552 long_integer_type_node
, tp
, ln
);
13553 ccond
= fold_build2_loc (input_location
, GT_EXPR
,
13554 logical_type_node
, above
, nbits
);
13555 gfc_trans_runtime_check (true, false, ccond
, &argse
[4].pre
,
13557 "TOPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
13558 "in intrinsic MVBITS", tp
, ln
, bitsize
);
13561 for (n
= 0; n
< 5; n
++)
13563 gfc_add_block_to_block (&se
->pre
, &argse
[n
].pre
);
13564 gfc_add_block_to_block (&se
->post
, &argse
[n
].post
);
13567 /* lenmask = (LEN >= bit_size (TYPE)) ? ~(TYPE)0 : ((TYPE)1 << LEN) - 1 */
13568 above
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
13569 len
, fold_convert (TREE_TYPE (len
), bitsize
));
13570 mask1
= build_int_cst (type
, -1);
13571 mask2
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
13572 build_int_cst (type
, 1), len
);
13573 mask2
= fold_build2_loc (input_location
, MINUS_EXPR
, type
,
13574 mask2
, build_int_cst (type
, 1));
13575 lenmask
= fold_build3_loc (input_location
, COND_EXPR
, type
,
13576 above
, mask1
, mask2
);
13578 /* newbits = (((UTYPE)(FROM) >> FROMPOS) & lenmask) << TOPOS.
13579 * For valid frompos+len <= bit_size(FROM) the conversion to unsigned is
13580 * not strictly necessary; artificial bits from rshift will be masked. */
13581 utype
= unsigned_type_for (type
);
13582 newbits
= fold_build2_loc (input_location
, RSHIFT_EXPR
, utype
,
13583 fold_convert (utype
, from
), frompos
);
13584 newbits
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
,
13585 fold_convert (type
, newbits
), lenmask
);
13586 newbits
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
13589 /* oldbits = TO & (~(lenmask << TOPOS)). */
13590 oldbits
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
13592 oldbits
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, type
, oldbits
);
13593 oldbits
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, oldbits
, to
);
13595 /* TO = newbits | oldbits. */
13596 se
->expr
= fold_build2_loc (input_location
, BIT_IOR_EXPR
, type
,
13599 /* Return the assignment. */
13600 se
->expr
= fold_build2_loc (input_location
, MODIFY_EXPR
,
13601 void_type_node
, to
, se
->expr
);
13606 conv_intrinsic_move_alloc (gfc_code
*code
)
13609 gfc_expr
*from_expr
, *to_expr
;
13610 gfc_se from_se
, to_se
;
13611 tree tmp
, to_tree
, from_tree
;
13612 bool coarray
, from_is_class
, from_is_scalar
;
13614 gfc_start_block (&block
);
13616 from_expr
= code
->ext
.actual
->expr
;
13617 to_expr
= code
->ext
.actual
->next
->expr
;
13619 gfc_init_se (&from_se
, NULL
);
13620 gfc_init_se (&to_se
, NULL
);
13622 gcc_assert (from_expr
->ts
.type
!= BT_CLASS
|| to_expr
->ts
.type
== BT_CLASS
);
13623 coarray
= from_expr
->corank
!= 0;
13625 from_is_class
= from_expr
->ts
.type
== BT_CLASS
;
13626 from_is_scalar
= from_expr
->rank
== 0 && !coarray
;
13627 if (to_expr
->ts
.type
== BT_CLASS
|| from_is_scalar
)
13629 from_se
.want_pointer
= 1;
13630 if (from_is_scalar
)
13631 gfc_conv_expr (&from_se
, from_expr
);
13633 gfc_conv_expr_descriptor (&from_se
, from_expr
);
13635 from_tree
= gfc_class_data_get (from_se
.expr
);
13639 from_tree
= from_se
.expr
;
13641 if (to_expr
->ts
.type
== BT_CLASS
)
13643 vtab
= gfc_find_vtab (&from_expr
->ts
);
13645 from_se
.expr
= gfc_get_symbol_decl (vtab
);
13648 gfc_add_block_to_block (&block
, &from_se
.pre
);
13650 to_se
.want_pointer
= 1;
13651 if (to_expr
->rank
== 0)
13652 gfc_conv_expr (&to_se
, to_expr
);
13654 gfc_conv_expr_descriptor (&to_se
, to_expr
);
13655 if (to_expr
->ts
.type
== BT_CLASS
)
13656 to_tree
= gfc_class_data_get (to_se
.expr
);
13658 to_tree
= to_se
.expr
;
13659 gfc_add_block_to_block (&block
, &to_se
.pre
);
13661 /* Deallocate "to". */
13662 if (to_expr
->rank
== 0)
13665 = gfc_deallocate_scalar_with_status (to_tree
, NULL_TREE
, NULL_TREE
,
13666 true, to_expr
, to_expr
->ts
);
13667 gfc_add_expr_to_block (&block
, tmp
);
13670 if (from_is_scalar
)
13672 /* Assign (_data) pointers. */
13673 gfc_add_modify_loc (input_location
, &block
, to_tree
,
13674 fold_convert (TREE_TYPE (to_tree
), from_tree
));
13676 /* Set "from" to NULL. */
13677 gfc_add_modify_loc (input_location
, &block
, from_tree
,
13678 fold_convert (TREE_TYPE (from_tree
),
13679 null_pointer_node
));
13681 gfc_add_block_to_block (&block
, &from_se
.post
);
13683 gfc_add_block_to_block (&block
, &to_se
.post
);
13686 if (to_expr
->ts
.type
== BT_CLASS
)
13688 gfc_class_set_vptr (&block
, to_se
.expr
, from_se
.expr
);
13690 gfc_reset_vptr (&block
, from_expr
);
13691 if (UNLIMITED_POLY (to_expr
))
13693 tree to_len
= gfc_class_len_get (to_se
.class_container
);
13694 tmp
= from_expr
->ts
.type
== BT_CHARACTER
&& from_se
.string_length
13695 ? from_se
.string_length
13697 gfc_add_modify_loc (input_location
, &block
, to_len
,
13698 fold_convert (TREE_TYPE (to_len
), tmp
));
13702 if (from_is_scalar
)
13704 if (to_expr
->ts
.type
== BT_CHARACTER
&& to_expr
->ts
.deferred
)
13706 gfc_add_modify_loc (input_location
, &block
, to_se
.string_length
,
13707 fold_convert (TREE_TYPE (to_se
.string_length
),
13708 from_se
.string_length
));
13709 if (from_expr
->ts
.deferred
)
13710 gfc_add_modify_loc (
13711 input_location
, &block
, from_se
.string_length
,
13712 build_int_cst (TREE_TYPE (from_se
.string_length
), 0));
13714 if (UNLIMITED_POLY (from_expr
))
13715 gfc_reset_len (&block
, from_expr
);
13717 return gfc_finish_block (&block
);
13720 gfc_init_se (&to_se
, NULL
);
13721 gfc_init_se (&from_se
, NULL
);
13724 /* Deallocate "to". */
13725 if (from_expr
->rank
== 0)
13727 to_se
.want_coarray
= 1;
13728 from_se
.want_coarray
= 1;
13730 gfc_conv_expr_descriptor (&to_se
, to_expr
);
13731 gfc_conv_expr_descriptor (&from_se
, from_expr
);
13733 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
13734 is an image control "statement", cf. IR F08/0040 in 12-006A. */
13735 if (coarray
&& flag_coarray
== GFC_FCOARRAY_LIB
)
13739 tmp
= gfc_deallocate_with_status (to_se
.expr
, NULL_TREE
, NULL_TREE
,
13740 NULL_TREE
, NULL_TREE
, true, to_expr
,
13741 GFC_CAF_COARRAY_DEALLOCATE_ONLY
);
13742 gfc_add_expr_to_block (&block
, tmp
);
13744 tmp
= gfc_conv_descriptor_data_get (to_se
.expr
);
13745 cond
= fold_build2_loc (input_location
, EQ_EXPR
,
13746 logical_type_node
, tmp
,
13747 fold_convert (TREE_TYPE (tmp
),
13748 null_pointer_node
));
13749 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_sync_all
,
13750 3, null_pointer_node
, null_pointer_node
,
13751 integer_zero_node
);
13753 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
,
13754 tmp
, build_empty_stmt (input_location
));
13755 gfc_add_expr_to_block (&block
, tmp
);
13759 if (to_expr
->ts
.type
== BT_DERIVED
13760 && to_expr
->ts
.u
.derived
->attr
.alloc_comp
)
13762 tmp
= gfc_deallocate_alloc_comp (to_expr
->ts
.u
.derived
,
13763 to_se
.expr
, to_expr
->rank
);
13764 gfc_add_expr_to_block (&block
, tmp
);
13767 tmp
= gfc_deallocate_with_status (to_se
.expr
, NULL_TREE
, NULL_TREE
,
13768 NULL_TREE
, NULL_TREE
, true, to_expr
,
13769 GFC_CAF_COARRAY_NOCOARRAY
);
13770 gfc_add_expr_to_block (&block
, tmp
);
13773 /* Copy the array descriptor data. */
13774 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
, from_se
.expr
);
13776 /* Set "from" to NULL. */
13777 tmp
= gfc_conv_descriptor_data_get (from_se
.expr
);
13778 gfc_add_modify_loc (input_location
, &block
, tmp
,
13779 fold_convert (TREE_TYPE (tmp
), null_pointer_node
));
13782 if (to_expr
->ts
.type
== BT_CHARACTER
&& to_expr
->ts
.deferred
)
13784 gfc_add_modify_loc (input_location
, &block
, to_se
.string_length
,
13785 fold_convert (TREE_TYPE (to_se
.string_length
),
13786 from_se
.string_length
));
13787 if (from_expr
->ts
.deferred
)
13788 gfc_add_modify_loc (input_location
, &block
, from_se
.string_length
,
13789 build_int_cst (TREE_TYPE (from_se
.string_length
), 0));
13792 return gfc_finish_block (&block
);
13797 gfc_conv_intrinsic_subroutine (gfc_code
*code
)
13801 gcc_assert (code
->resolved_isym
);
13803 switch (code
->resolved_isym
->id
)
13805 case GFC_ISYM_MOVE_ALLOC
:
13806 res
= conv_intrinsic_move_alloc (code
);
13809 case GFC_ISYM_ATOMIC_CAS
:
13810 res
= conv_intrinsic_atomic_cas (code
);
13813 case GFC_ISYM_ATOMIC_ADD
:
13814 case GFC_ISYM_ATOMIC_AND
:
13815 case GFC_ISYM_ATOMIC_DEF
:
13816 case GFC_ISYM_ATOMIC_OR
:
13817 case GFC_ISYM_ATOMIC_XOR
:
13818 case GFC_ISYM_ATOMIC_FETCH_ADD
:
13819 case GFC_ISYM_ATOMIC_FETCH_AND
:
13820 case GFC_ISYM_ATOMIC_FETCH_OR
:
13821 case GFC_ISYM_ATOMIC_FETCH_XOR
:
13822 res
= conv_intrinsic_atomic_op (code
);
13825 case GFC_ISYM_ATOMIC_REF
:
13826 res
= conv_intrinsic_atomic_ref (code
);
13829 case GFC_ISYM_EVENT_QUERY
:
13830 res
= conv_intrinsic_event_query (code
);
13833 case GFC_ISYM_C_F_POINTER
:
13834 case GFC_ISYM_C_F_PROCPOINTER
:
13835 res
= conv_isocbinding_subroutine (code
);
13838 case GFC_ISYM_CAF_SEND
:
13839 res
= conv_caf_send (code
);
13842 case GFC_ISYM_CO_BROADCAST
:
13843 case GFC_ISYM_CO_MIN
:
13844 case GFC_ISYM_CO_MAX
:
13845 case GFC_ISYM_CO_REDUCE
:
13846 case GFC_ISYM_CO_SUM
:
13847 res
= conv_co_collective (code
);
13850 case GFC_ISYM_FREE
:
13851 res
= conv_intrinsic_free (code
);
13854 case GFC_ISYM_RANDOM_INIT
:
13855 res
= conv_intrinsic_random_init (code
);
13858 case GFC_ISYM_KILL
:
13859 res
= conv_intrinsic_kill_sub (code
);
13862 case GFC_ISYM_MVBITS
:
13866 case GFC_ISYM_SYSTEM_CLOCK
:
13867 res
= conv_intrinsic_system_clock (code
);
13878 #include "gt-fortran-trans-intrinsic.h"