1 /* Intrinsic translation
2 Copyright (C) 2002-2024 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. */
46 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
48 /* This maps Fortran intrinsic math functions to external library or GCC
50 typedef struct GTY(()) gfc_intrinsic_map_t
{
51 /* The explicit enum is required to work around inadequacies in the
52 garbage collection/gengtype parsing mechanism. */
55 /* Enum value from the "language-independent", aka C-centric, part
56 of gcc, or END_BUILTINS of no such value set. */
57 enum built_in_function float_built_in
;
58 enum built_in_function double_built_in
;
59 enum built_in_function long_double_built_in
;
60 enum built_in_function complex_float_built_in
;
61 enum built_in_function complex_double_built_in
;
62 enum built_in_function complex_long_double_built_in
;
64 /* True if the naming pattern is to prepend "c" for complex and
65 append "f" for kind=4. False if the naming pattern is to
66 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
69 /* True if a complex version of the function exists. */
70 bool complex_available
;
72 /* True if the function should be marked const. */
75 /* The base library name of this function. */
78 /* Cache decls created for the various operand types. */
90 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
91 defines complex variants of all of the entries in mathbuiltins.def
93 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
94 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
95 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
96 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
97 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
99 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
100 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
101 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
102 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
103 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
105 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
106 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
107 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
108 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
109 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
111 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
112 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
113 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
114 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
115 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
117 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map
[] =
119 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
120 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
121 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
122 #include "mathbuiltins.def"
124 /* Functions in libgfortran. */
125 LIB_FUNCTION (ERFC_SCALED
, "erfc_scaled", false),
126 LIB_FUNCTION (SIND
, "sind", false),
127 LIB_FUNCTION (COSD
, "cosd", false),
128 LIB_FUNCTION (TAND
, "tand", false),
131 LIB_FUNCTION (NONE
, NULL
, false)
136 #undef DEFINE_MATH_BUILTIN
137 #undef DEFINE_MATH_BUILTIN_C
140 enum rounding_mode
{ RND_ROUND
, RND_TRUNC
, RND_CEIL
, RND_FLOOR
};
143 /* Find the correct variant of a given builtin from its argument. */
145 builtin_decl_for_precision (enum built_in_function base_built_in
,
148 enum built_in_function i
= END_BUILTINS
;
150 gfc_intrinsic_map_t
*m
;
151 for (m
= gfc_intrinsic_map
; m
->double_built_in
!= base_built_in
; m
++)
154 if (precision
== TYPE_PRECISION (float_type_node
))
155 i
= m
->float_built_in
;
156 else if (precision
== TYPE_PRECISION (double_type_node
))
157 i
= m
->double_built_in
;
158 else if (precision
== TYPE_PRECISION (long_double_type_node
)
159 && (!gfc_real16_is_float128
160 || long_double_type_node
!= gfc_float128_type_node
))
161 i
= m
->long_double_built_in
;
162 else if (precision
== TYPE_PRECISION (gfc_float128_type_node
))
164 /* Special treatment, because it is not exactly a built-in, but
165 a library function. */
166 return m
->real16_decl
;
169 return (i
== END_BUILTINS
? NULL_TREE
: builtin_decl_explicit (i
));
174 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in
,
177 int i
= gfc_validate_kind (BT_REAL
, kind
, false);
179 if (gfc_real_kinds
[i
].c_float128
)
181 /* For _Float128, the story is a bit different, because we return
182 a decl to a library function rather than a built-in. */
183 gfc_intrinsic_map_t
*m
;
184 for (m
= gfc_intrinsic_map
; m
->double_built_in
!= double_built_in
; m
++)
187 return m
->real16_decl
;
190 return builtin_decl_for_precision (double_built_in
,
191 gfc_real_kinds
[i
].mode_precision
);
195 /* Evaluate the arguments to an intrinsic function. The value
196 of NARGS may be less than the actual number of arguments in EXPR
197 to allow optional "KIND" arguments that are not included in the
198 generated code to be ignored. */
201 gfc_conv_intrinsic_function_args (gfc_se
*se
, gfc_expr
*expr
,
202 tree
*argarray
, int nargs
)
204 gfc_actual_arglist
*actual
;
206 gfc_intrinsic_arg
*formal
;
210 formal
= expr
->value
.function
.isym
->formal
;
211 actual
= expr
->value
.function
.actual
;
213 for (curr_arg
= 0; curr_arg
< nargs
; curr_arg
++,
214 actual
= actual
->next
,
215 formal
= formal
? formal
->next
: NULL
)
219 /* Skip omitted optional arguments. */
226 /* Evaluate the parameter. This will substitute scalarized
227 references automatically. */
228 gfc_init_se (&argse
, se
);
230 if (e
->ts
.type
== BT_CHARACTER
)
232 gfc_conv_expr (&argse
, e
);
233 gfc_conv_string_parameter (&argse
);
234 argarray
[curr_arg
++] = argse
.string_length
;
235 gcc_assert (curr_arg
< nargs
);
238 gfc_conv_expr_val (&argse
, e
);
240 /* If an optional argument is itself an optional dummy argument,
241 check its presence and substitute a null if absent. */
242 if (e
->expr_type
== EXPR_VARIABLE
243 && e
->symtree
->n
.sym
->attr
.optional
246 gfc_conv_missing_dummy (&argse
, e
, formal
->ts
, 0);
248 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
249 gfc_add_block_to_block (&se
->post
, &argse
.post
);
250 argarray
[curr_arg
] = argse
.expr
;
254 /* Count the number of actual arguments to the intrinsic function EXPR
255 including any "hidden" string length arguments. */
258 gfc_intrinsic_argument_list_length (gfc_expr
*expr
)
261 gfc_actual_arglist
*actual
;
263 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
268 if (actual
->expr
->ts
.type
== BT_CHARACTER
)
278 /* Conversions between different types are output by the frontend as
279 intrinsic functions. We implement these directly with inline code. */
282 gfc_conv_intrinsic_conversion (gfc_se
* se
, gfc_expr
* expr
)
288 nargs
= gfc_intrinsic_argument_list_length (expr
);
289 args
= XALLOCAVEC (tree
, nargs
);
291 /* Evaluate all the arguments passed. Whilst we're only interested in the
292 first one here, there are other parts of the front-end that assume this
293 and will trigger an ICE if it's not the case. */
294 type
= gfc_typenode_for_spec (&expr
->ts
);
295 gcc_assert (expr
->value
.function
.actual
->expr
);
296 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
298 /* Conversion between character kinds involves a call to a library
300 if (expr
->ts
.type
== BT_CHARACTER
)
302 tree fndecl
, var
, addr
, tmp
;
304 if (expr
->ts
.kind
== 1
305 && expr
->value
.function
.actual
->expr
->ts
.kind
== 4)
306 fndecl
= gfor_fndecl_convert_char4_to_char1
;
307 else if (expr
->ts
.kind
== 4
308 && expr
->value
.function
.actual
->expr
->ts
.kind
== 1)
309 fndecl
= gfor_fndecl_convert_char1_to_char4
;
313 /* Create the variable storing the converted value. */
314 type
= gfc_get_pchar_type (expr
->ts
.kind
);
315 var
= gfc_create_var (type
, "str");
316 addr
= gfc_build_addr_expr (build_pointer_type (type
), var
);
318 /* Call the library function that will perform the conversion. */
319 gcc_assert (nargs
>= 2);
320 tmp
= build_call_expr_loc (input_location
,
321 fndecl
, 3, addr
, args
[0], args
[1]);
322 gfc_add_expr_to_block (&se
->pre
, tmp
);
324 /* Free the temporary afterwards. */
325 tmp
= gfc_call_free (var
);
326 gfc_add_expr_to_block (&se
->post
, tmp
);
329 se
->string_length
= args
[0];
334 /* Conversion from complex to non-complex involves taking the real
335 component of the value. */
336 if (TREE_CODE (TREE_TYPE (args
[0])) == COMPLEX_TYPE
337 && expr
->ts
.type
!= BT_COMPLEX
)
341 artype
= TREE_TYPE (TREE_TYPE (args
[0]));
342 args
[0] = fold_build1_loc (input_location
, REALPART_EXPR
, artype
,
346 se
->expr
= convert (type
, args
[0]);
349 /* This is needed because the gcc backend only implements
350 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
351 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
352 Similarly for CEILING. */
355 build_fixbound_expr (stmtblock_t
* pblock
, tree arg
, tree type
, int up
)
362 argtype
= TREE_TYPE (arg
);
363 arg
= gfc_evaluate_now (arg
, pblock
);
365 intval
= convert (type
, arg
);
366 intval
= gfc_evaluate_now (intval
, pblock
);
368 tmp
= convert (argtype
, intval
);
369 cond
= fold_build2_loc (input_location
, up
? GE_EXPR
: LE_EXPR
,
370 logical_type_node
, tmp
, arg
);
372 tmp
= fold_build2_loc (input_location
, up
? PLUS_EXPR
: MINUS_EXPR
, type
,
373 intval
, build_int_cst (type
, 1));
374 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
, intval
, tmp
);
379 /* Round to nearest integer, away from zero. */
382 build_round_expr (tree arg
, tree restype
)
386 int argprec
, resprec
;
388 argtype
= TREE_TYPE (arg
);
389 argprec
= TYPE_PRECISION (argtype
);
390 resprec
= TYPE_PRECISION (restype
);
392 /* Depending on the type of the result, choose the int intrinsic (iround,
393 available only as a builtin, therefore cannot use it for _Float128), long
394 int intrinsic (lround family) or long long intrinsic (llround). If we
395 don't have an appropriate function that converts directly to the integer
396 type (such as kind == 16), just use ROUND, and then convert the result to
397 an integer. We might also need to convert the result afterwards. */
398 if (resprec
<= INT_TYPE_SIZE
399 && argprec
<= TYPE_PRECISION (long_double_type_node
))
400 fn
= builtin_decl_for_precision (BUILT_IN_IROUND
, argprec
);
401 else if (resprec
<= LONG_TYPE_SIZE
)
402 fn
= builtin_decl_for_precision (BUILT_IN_LROUND
, argprec
);
403 else if (resprec
<= LONG_LONG_TYPE_SIZE
)
404 fn
= builtin_decl_for_precision (BUILT_IN_LLROUND
, argprec
);
405 else if (resprec
>= argprec
)
406 fn
= builtin_decl_for_precision (BUILT_IN_ROUND
, argprec
);
410 return convert (restype
, build_call_expr_loc (input_location
,
415 /* Convert a real to an integer using a specific rounding mode.
416 Ideally we would just build the corresponding GENERIC node,
417 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
420 build_fix_expr (stmtblock_t
* pblock
, tree arg
, tree type
,
421 enum rounding_mode op
)
426 return build_fixbound_expr (pblock
, arg
, type
, 0);
429 return build_fixbound_expr (pblock
, arg
, type
, 1);
432 return build_round_expr (arg
, type
);
435 return fold_build1_loc (input_location
, FIX_TRUNC_EXPR
, type
, arg
);
443 /* Round a real value using the specified rounding mode.
444 We use a temporary integer of that same kind size as the result.
445 Values larger than those that can be represented by this kind are
446 unchanged, as they will not be accurate enough to represent the
448 huge = HUGE (KIND (a))
449 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
453 gfc_conv_intrinsic_aint (gfc_se
* se
, gfc_expr
* expr
, enum rounding_mode op
)
465 kind
= expr
->ts
.kind
;
466 nargs
= gfc_intrinsic_argument_list_length (expr
);
469 /* We have builtin functions for some cases. */
473 decl
= gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND
, kind
);
477 decl
= gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC
, kind
);
484 /* Evaluate the argument. */
485 gcc_assert (expr
->value
.function
.actual
->expr
);
486 gfc_conv_intrinsic_function_args (se
, expr
, arg
, nargs
);
488 /* Use a builtin function if one exists. */
489 if (decl
!= NULL_TREE
)
491 se
->expr
= build_call_expr_loc (input_location
, decl
, 1, arg
[0]);
495 /* This code is probably redundant, but we'll keep it lying around just
497 type
= gfc_typenode_for_spec (&expr
->ts
);
498 arg
[0] = gfc_evaluate_now (arg
[0], &se
->pre
);
500 /* Test if the value is too large to handle sensibly. */
501 gfc_set_model_kind (kind
);
503 n
= gfc_validate_kind (BT_INTEGER
, kind
, false);
504 mpfr_set_z (huge
, gfc_integer_kinds
[n
].huge
, GFC_RND_MODE
);
505 tmp
= gfc_conv_mpfr_to_tree (huge
, kind
, 0);
506 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
, arg
[0],
509 mpfr_neg (huge
, huge
, GFC_RND_MODE
);
510 tmp
= gfc_conv_mpfr_to_tree (huge
, kind
, 0);
511 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
, arg
[0],
513 cond
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
, logical_type_node
,
515 itype
= gfc_get_int_type (kind
);
517 tmp
= build_fix_expr (&se
->pre
, arg
[0], itype
, op
);
518 tmp
= convert (type
, tmp
);
519 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
, tmp
,
525 /* Convert to an integer using the specified rounding mode. */
528 gfc_conv_intrinsic_int (gfc_se
* se
, gfc_expr
* expr
, enum rounding_mode op
)
534 nargs
= gfc_intrinsic_argument_list_length (expr
);
535 args
= XALLOCAVEC (tree
, nargs
);
537 /* Evaluate the argument, we process all arguments even though we only
538 use the first one for code generation purposes. */
539 type
= gfc_typenode_for_spec (&expr
->ts
);
540 gcc_assert (expr
->value
.function
.actual
->expr
);
541 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
543 if (TREE_CODE (TREE_TYPE (args
[0])) == INTEGER_TYPE
)
545 /* Conversion to a different integer kind. */
546 se
->expr
= convert (type
, args
[0]);
550 /* Conversion from complex to non-complex involves taking the real
551 component of the value. */
552 if (TREE_CODE (TREE_TYPE (args
[0])) == COMPLEX_TYPE
553 && expr
->ts
.type
!= BT_COMPLEX
)
557 artype
= TREE_TYPE (TREE_TYPE (args
[0]));
558 args
[0] = fold_build1_loc (input_location
, REALPART_EXPR
, artype
,
562 se
->expr
= build_fix_expr (&se
->pre
, args
[0], type
, op
);
567 /* Get the imaginary component of a value. */
570 gfc_conv_intrinsic_imagpart (gfc_se
* se
, gfc_expr
* expr
)
574 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
575 se
->expr
= fold_build1_loc (input_location
, IMAGPART_EXPR
,
576 TREE_TYPE (TREE_TYPE (arg
)), arg
);
580 /* Get the complex conjugate of a value. */
583 gfc_conv_intrinsic_conjg (gfc_se
* se
, gfc_expr
* expr
)
587 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
588 se
->expr
= fold_build1_loc (input_location
, CONJ_EXPR
, TREE_TYPE (arg
), arg
);
594 define_quad_builtin (const char *name
, tree type
, bool is_const
)
597 fndecl
= build_decl (input_location
, FUNCTION_DECL
, get_identifier (name
),
600 /* Mark the decl as external. */
601 DECL_EXTERNAL (fndecl
) = 1;
602 TREE_PUBLIC (fndecl
) = 1;
604 /* Mark it __attribute__((const)). */
605 TREE_READONLY (fndecl
) = is_const
;
607 rest_of_decl_compilation (fndecl
, 1, 0);
612 /* Add SIMD attribute for FNDECL built-in if the built-in
613 name is in VECTORIZED_BUILTINS. */
616 add_simd_flag_for_built_in (tree fndecl
)
618 if (gfc_vectorized_builtins
== NULL
619 || fndecl
== NULL_TREE
)
622 const char *name
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
623 int *clauses
= gfc_vectorized_builtins
->get (name
);
626 for (unsigned i
= 0; i
< 3; i
++)
627 if (*clauses
& (1 << i
))
629 gfc_simd_clause simd_type
= (gfc_simd_clause
)*clauses
;
630 tree omp_clause
= NULL_TREE
;
631 if (simd_type
== SIMD_NONE
)
632 ; /* No SIMD clause. */
636 = (simd_type
== SIMD_INBRANCH
637 ? OMP_CLAUSE_INBRANCH
: OMP_CLAUSE_NOTINBRANCH
);
638 omp_clause
= build_omp_clause (UNKNOWN_LOCATION
, code
);
639 omp_clause
= build_tree_list (NULL_TREE
, omp_clause
);
642 DECL_ATTRIBUTES (fndecl
)
643 = tree_cons (get_identifier ("omp declare simd"), omp_clause
,
644 DECL_ATTRIBUTES (fndecl
));
649 /* Set SIMD attribute to all built-in functions that are mentioned
650 in gfc_vectorized_builtins vector. */
653 gfc_adjust_builtins (void)
655 gfc_intrinsic_map_t
*m
;
656 for (m
= gfc_intrinsic_map
;
657 m
->id
!= GFC_ISYM_NONE
|| m
->double_built_in
!= END_BUILTINS
; m
++)
659 add_simd_flag_for_built_in (m
->real4_decl
);
660 add_simd_flag_for_built_in (m
->complex4_decl
);
661 add_simd_flag_for_built_in (m
->real8_decl
);
662 add_simd_flag_for_built_in (m
->complex8_decl
);
663 add_simd_flag_for_built_in (m
->real10_decl
);
664 add_simd_flag_for_built_in (m
->complex10_decl
);
665 add_simd_flag_for_built_in (m
->real16_decl
);
666 add_simd_flag_for_built_in (m
->complex16_decl
);
667 add_simd_flag_for_built_in (m
->real16_decl
);
668 add_simd_flag_for_built_in (m
->complex16_decl
);
671 /* Release all strings. */
672 if (gfc_vectorized_builtins
!= NULL
)
674 for (hash_map
<nofree_string_hash
, int>::iterator it
675 = gfc_vectorized_builtins
->begin ();
676 it
!= gfc_vectorized_builtins
->end (); ++it
)
677 free (CONST_CAST (char *, (*it
).first
));
679 delete gfc_vectorized_builtins
;
680 gfc_vectorized_builtins
= NULL
;
684 /* Initialize function decls for library functions. The external functions
685 are created as required. Builtin functions are added here. */
688 gfc_build_intrinsic_lib_fndecls (void)
690 gfc_intrinsic_map_t
*m
;
691 tree quad_decls
[END_BUILTINS
+ 1];
693 if (gfc_real16_is_float128
)
695 /* If we have soft-float types, we create the decls for their
696 C99-like library functions. For now, we only handle _Float128
697 q-suffixed or IEC 60559 f128-suffixed functions. */
699 tree type
, complex_type
, func_1
, func_2
, func_3
, func_cabs
, func_frexp
;
700 tree func_iround
, func_lround
, func_llround
, func_scalbn
, func_cpow
;
702 memset (quad_decls
, 0, sizeof(tree
) * (END_BUILTINS
+ 1));
704 type
= gfc_float128_type_node
;
705 complex_type
= gfc_complex_float128_type_node
;
706 /* type (*) (type) */
707 func_1
= build_function_type_list (type
, type
, NULL_TREE
);
709 func_iround
= build_function_type_list (integer_type_node
,
711 /* long (*) (type) */
712 func_lround
= build_function_type_list (long_integer_type_node
,
714 /* long long (*) (type) */
715 func_llround
= build_function_type_list (long_long_integer_type_node
,
717 /* type (*) (type, type) */
718 func_2
= build_function_type_list (type
, type
, type
, NULL_TREE
);
719 /* type (*) (type, type, type) */
720 func_3
= build_function_type_list (type
, type
, type
, type
, NULL_TREE
);
721 /* type (*) (type, &int) */
723 = build_function_type_list (type
,
725 build_pointer_type (integer_type_node
),
727 /* type (*) (type, int) */
728 func_scalbn
= build_function_type_list (type
,
729 type
, integer_type_node
, NULL_TREE
);
730 /* type (*) (complex type) */
731 func_cabs
= build_function_type_list (type
, complex_type
, NULL_TREE
);
732 /* complex type (*) (complex type, complex type) */
734 = build_function_type_list (complex_type
,
735 complex_type
, complex_type
, NULL_TREE
);
737 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
738 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
739 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
741 /* Only these built-ins are actually needed here. These are used directly
742 from the code, when calling builtin_decl_for_precision() or
743 builtin_decl_for_float_type(). The others are all constructed by
744 gfc_get_intrinsic_lib_fndecl(). */
745 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
746 quad_decls[BUILT_IN_ ## ID] \
747 = define_quad_builtin (gfc_real16_use_iec_60559 \
748 ? NAME "f128" : NAME "q", func_ ## TYPE, \
751 #include "mathbuiltins.def"
755 #undef DEFINE_MATH_BUILTIN
756 #undef DEFINE_MATH_BUILTIN_C
758 /* There is one built-in we defined manually, because it gets called
759 with builtin_decl_for_precision() or builtin_decl_for_float_type()
760 even though it is not an OTHER_BUILTIN: it is SQRT. */
761 quad_decls
[BUILT_IN_SQRT
]
762 = define_quad_builtin (gfc_real16_use_iec_60559
763 ? "sqrtf128" : "sqrtq", func_1
, true);
766 /* Add GCC builtin functions. */
767 for (m
= gfc_intrinsic_map
;
768 m
->id
!= GFC_ISYM_NONE
|| m
->double_built_in
!= END_BUILTINS
; m
++)
770 if (m
->float_built_in
!= END_BUILTINS
)
771 m
->real4_decl
= builtin_decl_explicit (m
->float_built_in
);
772 if (m
->complex_float_built_in
!= END_BUILTINS
)
773 m
->complex4_decl
= builtin_decl_explicit (m
->complex_float_built_in
);
774 if (m
->double_built_in
!= END_BUILTINS
)
775 m
->real8_decl
= builtin_decl_explicit (m
->double_built_in
);
776 if (m
->complex_double_built_in
!= END_BUILTINS
)
777 m
->complex8_decl
= builtin_decl_explicit (m
->complex_double_built_in
);
779 /* If real(kind=10) exists, it is always long double. */
780 if (m
->long_double_built_in
!= END_BUILTINS
)
781 m
->real10_decl
= builtin_decl_explicit (m
->long_double_built_in
);
782 if (m
->complex_long_double_built_in
!= END_BUILTINS
)
784 = builtin_decl_explicit (m
->complex_long_double_built_in
);
786 if (!gfc_real16_is_float128
)
788 if (m
->long_double_built_in
!= END_BUILTINS
)
789 m
->real16_decl
= builtin_decl_explicit (m
->long_double_built_in
);
790 if (m
->complex_long_double_built_in
!= END_BUILTINS
)
792 = builtin_decl_explicit (m
->complex_long_double_built_in
);
794 else if (quad_decls
[m
->double_built_in
] != NULL_TREE
)
796 /* Quad-precision function calls are constructed when first
797 needed by builtin_decl_for_precision(), except for those
798 that will be used directly (define by OTHER_BUILTIN). */
799 m
->real16_decl
= quad_decls
[m
->double_built_in
];
801 else if (quad_decls
[m
->complex_double_built_in
] != NULL_TREE
)
803 /* Same thing for the complex ones. */
804 m
->complex16_decl
= quad_decls
[m
->double_built_in
];
810 /* Create a fndecl for a simple intrinsic library function. */
813 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t
* m
, gfc_expr
* expr
)
816 vec
<tree
, va_gc
> *argtypes
;
818 gfc_actual_arglist
*actual
;
821 char name
[GFC_MAX_SYMBOL_LEN
+ 3];
824 if (ts
->type
== BT_REAL
)
829 pdecl
= &m
->real4_decl
;
832 pdecl
= &m
->real8_decl
;
835 pdecl
= &m
->real10_decl
;
838 pdecl
= &m
->real16_decl
;
844 else if (ts
->type
== BT_COMPLEX
)
846 gcc_assert (m
->complex_available
);
851 pdecl
= &m
->complex4_decl
;
854 pdecl
= &m
->complex8_decl
;
857 pdecl
= &m
->complex10_decl
;
860 pdecl
= &m
->complex16_decl
;
874 int n
= gfc_validate_kind (BT_REAL
, ts
->kind
, false);
875 if (gfc_real_kinds
[n
].c_float
)
876 snprintf (name
, sizeof (name
), "%s%s%s",
877 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
, "f");
878 else if (gfc_real_kinds
[n
].c_double
)
879 snprintf (name
, sizeof (name
), "%s%s",
880 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
);
881 else if (gfc_real_kinds
[n
].c_long_double
)
882 snprintf (name
, sizeof (name
), "%s%s%s",
883 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
, "l");
884 else if (gfc_real_kinds
[n
].c_float128
)
885 snprintf (name
, sizeof (name
), "%s%s%s",
886 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
,
887 gfc_real_kinds
[n
].use_iec_60559
? "f128" : "q");
893 snprintf (name
, sizeof (name
), PREFIX ("%s_%c%d"), m
->name
,
894 ts
->type
== BT_COMPLEX
? 'c' : 'r',
895 gfc_type_abi_kind (ts
));
899 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
901 type
= gfc_typenode_for_spec (&actual
->expr
->ts
);
902 vec_safe_push (argtypes
, type
);
904 type
= build_function_type_vec (gfc_typenode_for_spec (ts
), argtypes
);
905 fndecl
= build_decl (input_location
,
906 FUNCTION_DECL
, get_identifier (name
), type
);
908 /* Mark the decl as external. */
909 DECL_EXTERNAL (fndecl
) = 1;
910 TREE_PUBLIC (fndecl
) = 1;
912 /* Mark it __attribute__((const)), if possible. */
913 TREE_READONLY (fndecl
) = m
->is_constant
;
915 rest_of_decl_compilation (fndecl
, 1, 0);
922 /* Convert an intrinsic function into an external or builtin call. */
925 gfc_conv_intrinsic_lib_function (gfc_se
* se
, gfc_expr
* expr
)
927 gfc_intrinsic_map_t
*m
;
931 unsigned int num_args
;
934 id
= expr
->value
.function
.isym
->id
;
935 /* Find the entry for this function. */
936 for (m
= gfc_intrinsic_map
;
937 m
->id
!= GFC_ISYM_NONE
|| m
->double_built_in
!= END_BUILTINS
; m
++)
943 if (m
->id
== GFC_ISYM_NONE
)
945 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
946 expr
->value
.function
.name
, id
);
949 /* Get the decl and generate the call. */
950 num_args
= gfc_intrinsic_argument_list_length (expr
);
951 args
= XALLOCAVEC (tree
, num_args
);
953 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
954 fndecl
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
955 rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
957 fndecl
= build_addr (fndecl
);
958 se
->expr
= build_call_array_loc (input_location
, rettype
, fndecl
, num_args
, args
);
962 /* If bounds-checking is enabled, create code to verify at runtime that the
963 string lengths for both expressions are the same (needed for e.g. MERGE).
964 If bounds-checking is not enabled, does nothing. */
967 gfc_trans_same_strlen_check (const char* intr_name
, locus
* where
,
968 tree a
, tree b
, stmtblock_t
* target
)
973 /* If bounds-checking is disabled, do nothing. */
974 if (!(gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
))
977 /* Compare the two string lengths. */
978 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, a
, b
);
980 /* Output the runtime-check. */
981 name
= gfc_build_cstring_const (intr_name
);
982 name
= gfc_build_addr_expr (pchar_type_node
, name
);
983 gfc_trans_runtime_check (true, false, cond
, target
, where
,
984 "Unequal character lengths (%ld/%ld) in %s",
985 fold_convert (long_integer_type_node
, a
),
986 fold_convert (long_integer_type_node
, b
), name
);
990 /* The EXPONENT(X) intrinsic function is translated into
992 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
993 so that if X is a NaN or infinity, the result is HUGE(0).
997 gfc_conv_intrinsic_exponent (gfc_se
*se
, gfc_expr
*expr
)
999 tree arg
, type
, res
, tmp
, frexp
, cond
, huge
;
1002 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
,
1003 expr
->value
.function
.actual
->expr
->ts
.kind
);
1005 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
1006 arg
= gfc_evaluate_now (arg
, &se
->pre
);
1008 i
= gfc_validate_kind (BT_INTEGER
, gfc_c_int_kind
, false);
1009 huge
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].huge
, gfc_c_int_kind
);
1010 cond
= build_call_expr_loc (input_location
,
1011 builtin_decl_explicit (BUILT_IN_ISFINITE
),
1014 res
= gfc_create_var (integer_type_node
, NULL
);
1015 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
1016 gfc_build_addr_expr (NULL_TREE
, res
));
1017 tmp
= fold_build2_loc (input_location
, COMPOUND_EXPR
, integer_type_node
,
1019 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
1022 type
= gfc_typenode_for_spec (&expr
->ts
);
1023 se
->expr
= fold_convert (type
, se
->expr
);
1027 /* Fill in the following structure
1028 struct caf_vector_t {
1029 size_t nvec; // size of the vector
1036 ptrdiff_t lower_bound;
1037 ptrdiff_t upper_bound;
1044 conv_caf_vector_subscript_elem (stmtblock_t
*block
, int i
, tree desc
,
1045 tree lower
, tree upper
, tree stride
,
1046 tree vector
, int kind
, tree nvec
)
1048 tree field
, type
, tmp
;
1050 desc
= gfc_build_array_ref (desc
, gfc_rank_cst
[i
], NULL_TREE
);
1051 type
= TREE_TYPE (desc
);
1053 field
= gfc_advance_chain (TYPE_FIELDS (type
), 0);
1054 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1055 desc
, field
, NULL_TREE
);
1056 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), nvec
));
1059 field
= gfc_advance_chain (TYPE_FIELDS (type
), 1);
1060 desc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1061 desc
, field
, NULL_TREE
);
1062 type
= TREE_TYPE (desc
);
1064 /* Access the inner struct. */
1065 field
= gfc_advance_chain (TYPE_FIELDS (type
), vector
!= NULL_TREE
? 0 : 1);
1066 desc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1067 desc
, field
, NULL_TREE
);
1068 type
= TREE_TYPE (desc
);
1070 if (vector
!= NULL_TREE
)
1072 /* Set vector and kind. */
1073 field
= gfc_advance_chain (TYPE_FIELDS (type
), 0);
1074 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1075 desc
, field
, NULL_TREE
);
1076 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), vector
));
1077 field
= gfc_advance_chain (TYPE_FIELDS (type
), 1);
1078 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1079 desc
, field
, NULL_TREE
);
1080 gfc_add_modify (block
, tmp
, build_int_cst (integer_type_node
, kind
));
1084 /* Set dim.lower/upper/stride. */
1085 field
= gfc_advance_chain (TYPE_FIELDS (type
), 0);
1086 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1087 desc
, field
, NULL_TREE
);
1088 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), lower
));
1090 field
= gfc_advance_chain (TYPE_FIELDS (type
), 1);
1091 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1092 desc
, field
, NULL_TREE
);
1093 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), upper
));
1095 field
= gfc_advance_chain (TYPE_FIELDS (type
), 2);
1096 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1097 desc
, field
, NULL_TREE
);
1098 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), stride
));
1104 conv_caf_vector_subscript (stmtblock_t
*block
, tree desc
, gfc_array_ref
*ar
)
1107 tree var
, lower
, upper
= NULL_TREE
, stride
= NULL_TREE
, vector
, nvec
;
1108 tree lbound
, ubound
, tmp
;
1111 var
= gfc_create_var (gfc_get_caf_vector_type (ar
->dimen
), "vector");
1113 for (i
= 0; i
< ar
->dimen
; i
++)
1114 switch (ar
->dimen_type
[i
])
1119 gfc_init_se (&argse
, NULL
);
1120 gfc_conv_expr (&argse
, ar
->end
[i
]);
1121 gfc_add_block_to_block (block
, &argse
.pre
);
1122 upper
= gfc_evaluate_now (argse
.expr
, block
);
1125 upper
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[i
]);
1128 gfc_init_se (&argse
, NULL
);
1129 gfc_conv_expr (&argse
, ar
->stride
[i
]);
1130 gfc_add_block_to_block (block
, &argse
.pre
);
1131 stride
= gfc_evaluate_now (argse
.expr
, block
);
1134 stride
= gfc_index_one_node
;
1140 gfc_init_se (&argse
, NULL
);
1141 gfc_conv_expr (&argse
, ar
->start
[i
]);
1142 gfc_add_block_to_block (block
, &argse
.pre
);
1143 lower
= gfc_evaluate_now (argse
.expr
, block
);
1146 lower
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[i
]);
1147 if (ar
->dimen_type
[i
] == DIMEN_ELEMENT
)
1150 stride
= gfc_index_one_node
;
1153 nvec
= size_zero_node
;
1154 conv_caf_vector_subscript_elem (block
, i
, var
, lower
, upper
, stride
,
1159 gfc_init_se (&argse
, NULL
);
1160 argse
.descriptor_only
= 1;
1161 gfc_conv_expr_descriptor (&argse
, ar
->start
[i
]);
1162 gfc_add_block_to_block (block
, &argse
.pre
);
1163 vector
= argse
.expr
;
1164 lbound
= gfc_conv_descriptor_lbound_get (vector
, gfc_rank_cst
[0]);
1165 ubound
= gfc_conv_descriptor_ubound_get (vector
, gfc_rank_cst
[0]);
1166 nvec
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
1167 tmp
= gfc_conv_descriptor_stride_get (vector
, gfc_rank_cst
[0]);
1168 nvec
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
1169 TREE_TYPE (nvec
), nvec
, tmp
);
1170 lower
= gfc_index_zero_node
;
1171 upper
= gfc_index_zero_node
;
1172 stride
= gfc_index_zero_node
;
1173 vector
= gfc_conv_descriptor_data_get (vector
);
1174 conv_caf_vector_subscript_elem (block
, i
, var
, lower
, upper
, stride
,
1175 vector
, ar
->start
[i
]->ts
.kind
, nvec
);
1180 return gfc_build_addr_expr (NULL_TREE
, var
);
1185 compute_component_offset (tree field
, tree type
)
1188 if (DECL_FIELD_BIT_OFFSET (field
) != NULL_TREE
1189 && !integer_zerop (DECL_FIELD_BIT_OFFSET (field
)))
1191 tmp
= fold_build2 (TRUNC_DIV_EXPR
, type
,
1192 DECL_FIELD_BIT_OFFSET (field
),
1194 return fold_build2 (PLUS_EXPR
, type
, DECL_FIELD_OFFSET (field
), tmp
);
1197 return DECL_FIELD_OFFSET (field
);
1202 conv_expr_ref_to_caf_ref (stmtblock_t
*block
, gfc_expr
*expr
)
1204 gfc_ref
*ref
= expr
->ref
, *last_comp_ref
;
1205 tree caf_ref
= NULL_TREE
, prev_caf_ref
= NULL_TREE
, reference_type
, tmp
, tmp2
,
1206 field
, last_type
, inner_struct
, mode
, mode_rhs
, dim_array
, dim
, dim_type
,
1207 start
, end
, stride
, vector
, nvec
;
1209 bool ref_static_array
= false;
1210 tree last_component_ref_tree
= NULL_TREE
;
1215 last_component_ref_tree
= expr
->symtree
->n
.sym
->backend_decl
;
1216 ref_static_array
= !expr
->symtree
->n
.sym
->attr
.allocatable
1217 && !expr
->symtree
->n
.sym
->attr
.pointer
;
1220 /* Prevent uninit-warning. */
1221 reference_type
= NULL_TREE
;
1223 /* Skip refs upto the first coarray-ref. */
1224 last_comp_ref
= NULL
;
1225 while (ref
&& (ref
->type
!= REF_ARRAY
|| ref
->u
.ar
.codimen
== 0))
1227 /* Remember the type of components skipped. */
1228 if (ref
->type
== REF_COMPONENT
)
1229 last_comp_ref
= ref
;
1232 /* When a component was skipped, get the type information of the last
1233 component ref, else get the type from the symbol. */
1236 last_type
= gfc_typenode_for_spec (&last_comp_ref
->u
.c
.component
->ts
);
1237 last_type_n
= last_comp_ref
->u
.c
.component
->ts
.type
;
1241 last_type
= gfc_typenode_for_spec (&expr
->symtree
->n
.sym
->ts
);
1242 last_type_n
= expr
->symtree
->n
.sym
->ts
.type
;
1247 if (ref
->type
== REF_ARRAY
&& ref
->u
.ar
.codimen
> 0
1248 && ref
->u
.ar
.dimen
== 0)
1250 /* Skip pure coindexes. */
1254 tmp
= gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
1255 reference_type
= TREE_TYPE (tmp
);
1257 if (caf_ref
== NULL_TREE
)
1260 /* Construct the chain of refs. */
1261 if (prev_caf_ref
!= NULL_TREE
)
1263 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 0);
1264 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1265 TREE_TYPE (field
), prev_caf_ref
, field
,
1267 gfc_add_modify (block
, tmp2
, gfc_build_addr_expr (TREE_TYPE (field
),
1275 last_type
= gfc_typenode_for_spec (&ref
->u
.c
.component
->ts
);
1276 last_type_n
= ref
->u
.c
.component
->ts
.type
;
1277 /* Set the type of the ref. */
1278 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 1);
1279 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1280 TREE_TYPE (field
), prev_caf_ref
, field
,
1282 gfc_add_modify (block
, tmp
, build_int_cst (integer_type_node
,
1283 GFC_CAF_REF_COMPONENT
));
1285 /* Ref the c in union u. */
1286 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 3);
1287 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1288 TREE_TYPE (field
), prev_caf_ref
, field
,
1290 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field
)), 0);
1291 inner_struct
= fold_build3_loc (input_location
, COMPONENT_REF
,
1292 TREE_TYPE (field
), tmp
, field
,
1295 /* Set the offset. */
1296 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)), 0);
1297 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1298 TREE_TYPE (field
), inner_struct
, field
,
1300 /* Computing the offset is somewhat harder. The bit_offset has to be
1301 taken into account. When the bit_offset in the field_decl is non-
1302 null, divide it by the bitsize_unit and add it to the regular
1304 tmp2
= compute_component_offset (ref
->u
.c
.component
->backend_decl
,
1306 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (tmp
), tmp2
));
1308 /* Set caf_token_offset. */
1309 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)), 1);
1310 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1311 TREE_TYPE (field
), inner_struct
, field
,
1313 if ((ref
->u
.c
.component
->attr
.allocatable
1314 || ref
->u
.c
.component
->attr
.pointer
)
1315 && ref
->u
.c
.component
->attr
.dimension
)
1317 tree arr_desc_token_offset
;
1318 /* Get the token field from the descriptor. */
1319 arr_desc_token_offset
= TREE_OPERAND (
1320 gfc_conv_descriptor_token (ref
->u
.c
.component
->backend_decl
), 1);
1321 arr_desc_token_offset
1322 = compute_component_offset (arr_desc_token_offset
,
1324 tmp2
= fold_build2_loc (input_location
, PLUS_EXPR
,
1325 TREE_TYPE (tmp2
), tmp2
,
1326 arr_desc_token_offset
);
1328 else if (ref
->u
.c
.component
->caf_token
)
1329 tmp2
= compute_component_offset (ref
->u
.c
.component
->caf_token
,
1332 tmp2
= integer_zero_node
;
1333 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (tmp
), tmp2
));
1335 /* Remember whether this ref was to a non-allocatable/non-pointer
1336 component so the next array ref can be tailored correctly. */
1337 ref_static_array
= !ref
->u
.c
.component
->attr
.allocatable
1338 && !ref
->u
.c
.component
->attr
.pointer
;
1339 last_component_ref_tree
= ref_static_array
1340 ? ref
->u
.c
.component
->backend_decl
: NULL_TREE
;
1343 if (ref_static_array
&& ref
->u
.ar
.as
->type
== AS_DEFERRED
)
1344 ref_static_array
= false;
1345 /* Set the type of the ref. */
1346 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 1);
1347 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1348 TREE_TYPE (field
), prev_caf_ref
, field
,
1350 gfc_add_modify (block
, tmp
, build_int_cst (integer_type_node
,
1352 ? GFC_CAF_REF_STATIC_ARRAY
1353 : GFC_CAF_REF_ARRAY
));
1355 /* Ref the a in union u. */
1356 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 3);
1357 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1358 TREE_TYPE (field
), prev_caf_ref
, field
,
1360 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field
)), 1);
1361 inner_struct
= fold_build3_loc (input_location
, COMPONENT_REF
,
1362 TREE_TYPE (field
), tmp
, field
,
1365 /* Set the static_array_type in a for static arrays. */
1366 if (ref_static_array
)
1368 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)),
1370 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1371 TREE_TYPE (field
), inner_struct
, field
,
1373 gfc_add_modify (block
, tmp
, build_int_cst (TREE_TYPE (tmp
),
1376 /* Ref the mode in the inner_struct. */
1377 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)), 0);
1378 mode
= fold_build3_loc (input_location
, COMPONENT_REF
,
1379 TREE_TYPE (field
), inner_struct
, field
,
1381 /* Ref the dim in the inner_struct. */
1382 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)), 2);
1383 dim_array
= fold_build3_loc (input_location
, COMPONENT_REF
,
1384 TREE_TYPE (field
), inner_struct
, field
,
1386 for (i
= 0; i
< ref
->u
.ar
.dimen
; ++i
)
1389 dim
= gfc_build_array_ref (dim_array
, gfc_rank_cst
[i
], NULL_TREE
);
1390 dim_type
= TREE_TYPE (dim
);
1391 mode_rhs
= start
= end
= stride
= NULL_TREE
;
1392 switch (ref
->u
.ar
.dimen_type
[i
])
1395 if (ref
->u
.ar
.end
[i
])
1397 gfc_init_se (&se
, NULL
);
1398 gfc_conv_expr (&se
, ref
->u
.ar
.end
[i
]);
1399 gfc_add_block_to_block (block
, &se
.pre
);
1400 if (ref_static_array
)
1402 /* Make the index zero-based, when reffing a static
1405 gfc_init_se (&se
, NULL
);
1406 gfc_conv_expr (&se
, ref
->u
.ar
.as
->lower
[i
]);
1407 gfc_add_block_to_block (block
, &se
.pre
);
1408 se
.expr
= fold_build2 (MINUS_EXPR
,
1409 gfc_array_index_type
,
1411 gfc_array_index_type
,
1414 end
= gfc_evaluate_now (fold_convert (
1415 gfc_array_index_type
,
1419 else if (ref_static_array
)
1420 end
= fold_build2 (MINUS_EXPR
,
1421 gfc_array_index_type
,
1422 gfc_conv_array_ubound (
1423 last_component_ref_tree
, i
),
1424 gfc_conv_array_lbound (
1425 last_component_ref_tree
, i
));
1429 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1430 GFC_CAF_ARR_REF_OPEN_END
);
1432 if (ref
->u
.ar
.stride
[i
])
1434 gfc_init_se (&se
, NULL
);
1435 gfc_conv_expr (&se
, ref
->u
.ar
.stride
[i
]);
1436 gfc_add_block_to_block (block
, &se
.pre
);
1437 stride
= gfc_evaluate_now (fold_convert (
1438 gfc_array_index_type
,
1441 if (ref_static_array
)
1443 /* Make the index zero-based, when reffing a static
1445 stride
= fold_build2 (MULT_EXPR
,
1446 gfc_array_index_type
,
1447 gfc_conv_array_stride (
1448 last_component_ref_tree
,
1451 gcc_assert (end
!= NULL_TREE
);
1452 /* Multiply with the product of array's stride and
1453 the step of the ref to a virtual upper bound.
1454 We cannot compute the actual upper bound here or
1455 the caflib would compute the extend
1457 end
= fold_build2 (MULT_EXPR
, gfc_array_index_type
,
1458 end
, gfc_conv_array_stride (
1459 last_component_ref_tree
,
1461 end
= gfc_evaluate_now (end
, block
);
1462 stride
= gfc_evaluate_now (stride
, block
);
1465 else if (ref_static_array
)
1467 stride
= gfc_conv_array_stride (last_component_ref_tree
,
1469 end
= fold_build2 (MULT_EXPR
, gfc_array_index_type
,
1471 end
= gfc_evaluate_now (end
, block
);
1474 /* Always set a ref stride of one to make caflib's
1476 stride
= gfc_index_one_node
;
1480 if (ref
->u
.ar
.start
[i
])
1482 gfc_init_se (&se
, NULL
);
1483 gfc_conv_expr (&se
, ref
->u
.ar
.start
[i
]);
1484 gfc_add_block_to_block (block
, &se
.pre
);
1485 if (ref_static_array
)
1487 /* Make the index zero-based, when reffing a static
1489 start
= fold_convert (gfc_array_index_type
, se
.expr
);
1490 gfc_init_se (&se
, NULL
);
1491 gfc_conv_expr (&se
, ref
->u
.ar
.as
->lower
[i
]);
1492 gfc_add_block_to_block (block
, &se
.pre
);
1493 se
.expr
= fold_build2 (MINUS_EXPR
,
1494 gfc_array_index_type
,
1495 start
, fold_convert (
1496 gfc_array_index_type
,
1498 /* Multiply with the stride. */
1499 se
.expr
= fold_build2 (MULT_EXPR
,
1500 gfc_array_index_type
,
1502 gfc_conv_array_stride (
1503 last_component_ref_tree
,
1506 start
= gfc_evaluate_now (fold_convert (
1507 gfc_array_index_type
,
1510 if (mode_rhs
== NULL_TREE
)
1511 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1512 ref
->u
.ar
.dimen_type
[i
]
1514 ? GFC_CAF_ARR_REF_SINGLE
1515 : GFC_CAF_ARR_REF_RANGE
);
1517 else if (ref_static_array
)
1519 start
= integer_zero_node
;
1520 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1521 ref
->u
.ar
.start
[i
] == NULL
1522 ? GFC_CAF_ARR_REF_FULL
1523 : GFC_CAF_ARR_REF_RANGE
);
1525 else if (end
== NULL_TREE
)
1526 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1527 GFC_CAF_ARR_REF_FULL
);
1529 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1530 GFC_CAF_ARR_REF_OPEN_START
);
1532 /* Ref the s in dim. */
1533 field
= gfc_advance_chain (TYPE_FIELDS (dim_type
), 0);
1534 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1535 TREE_TYPE (field
), dim
, field
,
1538 /* Set start in s. */
1539 if (start
!= NULL_TREE
)
1541 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)),
1543 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1544 TREE_TYPE (field
), tmp
, field
,
1546 gfc_add_modify (block
, tmp2
,
1547 fold_convert (TREE_TYPE (tmp2
), start
));
1551 if (end
!= NULL_TREE
)
1553 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)),
1555 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1556 TREE_TYPE (field
), tmp
, field
,
1558 gfc_add_modify (block
, tmp2
,
1559 fold_convert (TREE_TYPE (tmp2
), end
));
1563 if (stride
!= NULL_TREE
)
1565 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)),
1567 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1568 TREE_TYPE (field
), tmp
, field
,
1570 gfc_add_modify (block
, tmp2
,
1571 fold_convert (TREE_TYPE (tmp2
), stride
));
1575 /* TODO: In case of static array. */
1576 gcc_assert (!ref_static_array
);
1577 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1578 GFC_CAF_ARR_REF_VECTOR
);
1579 gfc_init_se (&se
, NULL
);
1580 se
.descriptor_only
= 1;
1581 gfc_conv_expr_descriptor (&se
, ref
->u
.ar
.start
[i
]);
1582 gfc_add_block_to_block (block
, &se
.pre
);
1584 tmp
= gfc_conv_descriptor_lbound_get (vector
,
1586 tmp2
= gfc_conv_descriptor_ubound_get (vector
,
1588 nvec
= gfc_conv_array_extent_dim (tmp
, tmp2
, NULL
);
1589 tmp
= gfc_conv_descriptor_stride_get (vector
,
1591 nvec
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
1592 TREE_TYPE (nvec
), nvec
, tmp
);
1593 vector
= gfc_conv_descriptor_data_get (vector
);
1595 /* Ref the v in dim. */
1596 field
= gfc_advance_chain (TYPE_FIELDS (dim_type
), 1);
1597 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1598 TREE_TYPE (field
), dim
, field
,
1601 /* Set vector in v. */
1602 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)), 0);
1603 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1604 TREE_TYPE (field
), tmp
, field
,
1606 gfc_add_modify (block
, tmp2
, fold_convert (TREE_TYPE (tmp2
),
1609 /* Set nvec in v. */
1610 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)), 1);
1611 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1612 TREE_TYPE (field
), tmp
, field
,
1614 gfc_add_modify (block
, tmp2
, fold_convert (TREE_TYPE (tmp2
),
1617 /* Set kind in v. */
1618 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)), 2);
1619 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1620 TREE_TYPE (field
), tmp
, field
,
1622 gfc_add_modify (block
, tmp2
, build_int_cst (integer_type_node
,
1623 ref
->u
.ar
.start
[i
]->ts
.kind
));
1628 /* Set the mode for dim i. */
1629 tmp
= gfc_build_array_ref (mode
, gfc_rank_cst
[i
], NULL_TREE
);
1630 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (tmp
),
1634 /* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
1635 if (i
< GFC_MAX_DIMENSIONS
)
1637 tmp
= gfc_build_array_ref (mode
, gfc_rank_cst
[i
], NULL_TREE
);
1638 gfc_add_modify (block
, tmp
,
1639 build_int_cst (unsigned_char_type_node
,
1640 GFC_CAF_ARR_REF_NONE
));
1647 /* Set the size of the current type. */
1648 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 2);
1649 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1650 prev_caf_ref
, field
, NULL_TREE
);
1651 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
),
1652 TYPE_SIZE_UNIT (last_type
)));
1657 if (prev_caf_ref
!= NULL_TREE
)
1659 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 0);
1660 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1661 prev_caf_ref
, field
, NULL_TREE
);
1662 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
),
1663 null_pointer_node
));
1665 return caf_ref
!= NULL_TREE
? gfc_build_addr_expr (NULL_TREE
, caf_ref
)
1669 /* Get data from a remote coarray. */
1672 gfc_conv_intrinsic_caf_get (gfc_se
*se
, gfc_expr
*expr
, tree lhs
, tree lhs_kind
,
1673 tree may_require_tmp
, bool may_realloc
,
1674 symbol_attribute
*caf_attr
)
1676 gfc_expr
*array_expr
, *tmp_stat
;
1678 tree caf_decl
, token
, offset
, image_index
, tmp
;
1679 tree res_var
, dst_var
, type
, kind
, vec
, stat
;
1681 symbol_attribute caf_attr_store
;
1683 gcc_assert (flag_coarray
== GFC_FCOARRAY_LIB
);
1685 if (se
->ss
&& se
->ss
->info
->useflags
)
1687 /* Access the previously obtained result. */
1688 gfc_conv_tmp_array_ref (se
);
1692 /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1693 array_expr
= (lhs
== NULL_TREE
) ? expr
->value
.function
.actual
->expr
: expr
;
1694 type
= gfc_typenode_for_spec (&array_expr
->ts
);
1696 if (caf_attr
== NULL
)
1698 caf_attr_store
= gfc_caf_attr (array_expr
);
1699 caf_attr
= &caf_attr_store
;
1705 vec
= null_pointer_node
;
1706 tmp_stat
= gfc_find_stat_co (expr
);
1711 gfc_init_se (&stat_se
, NULL
);
1712 gfc_conv_expr_reference (&stat_se
, tmp_stat
);
1713 stat
= stat_se
.expr
;
1714 gfc_add_block_to_block (&se
->pre
, &stat_se
.pre
);
1715 gfc_add_block_to_block (&se
->post
, &stat_se
.post
);
1718 stat
= null_pointer_node
;
1720 /* Only use the new get_by_ref () where it is necessary. I.e., when the lhs
1721 is reallocatable or the right-hand side has allocatable components. */
1722 if (caf_attr
->alloc_comp
|| caf_attr
->pointer_comp
|| may_realloc
)
1724 /* Get using caf_get_by_ref. */
1725 caf_reference
= conv_expr_ref_to_caf_ref (&se
->pre
, array_expr
);
1727 if (caf_reference
!= NULL_TREE
)
1729 if (lhs
== NULL_TREE
)
1731 if (array_expr
->ts
.type
== BT_CHARACTER
)
1732 gfc_init_se (&argse
, NULL
);
1733 if (array_expr
->rank
== 0)
1735 symbol_attribute attr
;
1736 gfc_clear_attr (&attr
);
1737 if (array_expr
->ts
.type
== BT_CHARACTER
)
1739 res_var
= gfc_conv_string_tmp (se
,
1740 build_pointer_type (type
),
1741 array_expr
->ts
.u
.cl
->backend_decl
);
1742 argse
.string_length
= array_expr
->ts
.u
.cl
->backend_decl
;
1745 res_var
= gfc_create_var (type
, "caf_res");
1746 dst_var
= gfc_conv_scalar_to_descriptor (se
, res_var
, attr
);
1747 dst_var
= gfc_build_addr_expr (NULL_TREE
, dst_var
);
1751 /* Create temporary. */
1752 if (array_expr
->ts
.type
== BT_CHARACTER
)
1753 gfc_conv_expr_descriptor (&argse
, array_expr
);
1754 may_realloc
= gfc_trans_create_temp_array (&se
->pre
,
1761 res_var
= se
->ss
->info
->data
.array
.descriptor
;
1762 dst_var
= gfc_build_addr_expr (NULL_TREE
, res_var
);
1765 tmp
= gfc_conv_descriptor_data_get (res_var
);
1766 tmp
= gfc_deallocate_with_status (tmp
, NULL_TREE
,
1767 NULL_TREE
, NULL_TREE
,
1770 GFC_CAF_COARRAY_NOCOARRAY
);
1771 gfc_add_expr_to_block (&se
->post
, tmp
);
1776 kind
= build_int_cst (integer_type_node
, expr
->ts
.kind
);
1777 if (lhs_kind
== NULL_TREE
)
1780 caf_decl
= gfc_get_tree_for_caf_expr (array_expr
);
1781 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
1782 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
1783 image_index
= gfc_caf_get_image_index (&se
->pre
, array_expr
,
1785 gfc_get_caf_token_offset (se
, &token
, NULL
, caf_decl
, NULL
,
1788 /* No overlap possible as we have generated a temporary. */
1789 if (lhs
== NULL_TREE
)
1790 may_require_tmp
= boolean_false_node
;
1792 /* It guarantees memory consistency within the same segment. */
1793 tmp
= gfc_build_string_const (strlen ("memory") + 1, "memory");
1794 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
1795 gfc_build_string_const (1, ""), NULL_TREE
,
1796 NULL_TREE
, tree_cons (NULL_TREE
, tmp
, NULL_TREE
),
1798 ASM_VOLATILE_P (tmp
) = 1;
1799 gfc_add_expr_to_block (&se
->pre
, tmp
);
1801 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_get_by_ref
,
1802 10, token
, image_index
, dst_var
,
1803 caf_reference
, lhs_kind
, kind
,
1805 may_realloc
? boolean_true_node
:
1807 stat
, build_int_cst (integer_type_node
,
1808 array_expr
->ts
.type
));
1810 gfc_add_expr_to_block (&se
->pre
, tmp
);
1813 gfc_advance_se_ss_chain (se
);
1816 if (array_expr
->ts
.type
== BT_CHARACTER
)
1817 se
->string_length
= argse
.string_length
;
1823 gfc_init_se (&argse
, NULL
);
1824 if (array_expr
->rank
== 0)
1826 symbol_attribute attr
;
1828 gfc_clear_attr (&attr
);
1829 gfc_conv_expr (&argse
, array_expr
);
1831 if (lhs
== NULL_TREE
)
1833 gfc_clear_attr (&attr
);
1834 if (array_expr
->ts
.type
== BT_CHARACTER
)
1835 res_var
= gfc_conv_string_tmp (se
, build_pointer_type (type
),
1836 argse
.string_length
);
1838 res_var
= gfc_create_var (type
, "caf_res");
1839 dst_var
= gfc_conv_scalar_to_descriptor (&argse
, res_var
, attr
);
1840 dst_var
= gfc_build_addr_expr (NULL_TREE
, dst_var
);
1842 argse
.expr
= gfc_conv_scalar_to_descriptor (&argse
, argse
.expr
, attr
);
1843 argse
.expr
= gfc_build_addr_expr (NULL_TREE
, argse
.expr
);
1847 /* If has_vector, pass descriptor for whole array and the
1848 vector bounds separately. */
1849 gfc_array_ref
*ar
, ar2
;
1850 bool has_vector
= false;
1852 if (gfc_is_coindexed (expr
) && gfc_has_vector_subscript (expr
))
1855 ar
= gfc_find_array_ref (expr
);
1857 memset (ar
, '\0', sizeof (*ar
));
1861 // TODO: Check whether argse.want_coarray = 1 can help with the below.
1862 gfc_conv_expr_descriptor (&argse
, array_expr
);
1863 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1864 has the wrong type if component references are done. */
1865 gfc_add_modify (&argse
.pre
, gfc_conv_descriptor_dtype (argse
.expr
),
1866 gfc_get_dtype_rank_type (has_vector
? ar2
.dimen
1871 vec
= conv_caf_vector_subscript (&argse
.pre
, argse
.expr
, &ar2
);
1875 if (lhs
== NULL_TREE
)
1877 /* Create temporary. */
1878 for (int n
= 0; n
< se
->ss
->loop
->dimen
; n
++)
1879 if (se
->loop
->to
[n
] == NULL_TREE
)
1881 se
->loop
->from
[n
] = gfc_conv_descriptor_lbound_get (argse
.expr
,
1883 se
->loop
->to
[n
] = gfc_conv_descriptor_ubound_get (argse
.expr
,
1886 gfc_trans_create_temp_array (&argse
.pre
, &argse
.post
, se
->ss
, type
,
1887 NULL_TREE
, false, true, false,
1888 &array_expr
->where
);
1889 res_var
= se
->ss
->info
->data
.array
.descriptor
;
1890 dst_var
= gfc_build_addr_expr (NULL_TREE
, res_var
);
1892 argse
.expr
= gfc_build_addr_expr (NULL_TREE
, argse
.expr
);
1895 kind
= build_int_cst (integer_type_node
, expr
->ts
.kind
);
1896 if (lhs_kind
== NULL_TREE
)
1899 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1900 gfc_add_block_to_block (&se
->post
, &argse
.post
);
1902 caf_decl
= gfc_get_tree_for_caf_expr (array_expr
);
1903 if (POINTER_TYPE_P (TREE_TYPE (caf_decl
)))
1904 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
1905 image_index
= gfc_caf_get_image_index (&se
->pre
, array_expr
, caf_decl
);
1906 gfc_get_caf_token_offset (se
, &token
, &offset
, caf_decl
, argse
.expr
,
1909 /* No overlap possible as we have generated a temporary. */
1910 if (lhs
== NULL_TREE
)
1911 may_require_tmp
= boolean_false_node
;
1913 /* It guarantees memory consistency within the same segment. */
1914 tmp
= gfc_build_string_const (strlen ("memory") + 1, "memory");
1915 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
1916 gfc_build_string_const (1, ""), NULL_TREE
, NULL_TREE
,
1917 tree_cons (NULL_TREE
, tmp
, NULL_TREE
), NULL_TREE
);
1918 ASM_VOLATILE_P (tmp
) = 1;
1919 gfc_add_expr_to_block (&se
->pre
, tmp
);
1921 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_get
, 10,
1922 token
, offset
, image_index
, argse
.expr
, vec
,
1923 dst_var
, kind
, lhs_kind
, may_require_tmp
, stat
);
1925 gfc_add_expr_to_block (&se
->pre
, tmp
);
1928 gfc_advance_se_ss_chain (se
);
1931 if (array_expr
->ts
.type
== BT_CHARACTER
)
1932 se
->string_length
= argse
.string_length
;
1936 /* Send data to a remote coarray. */
1939 conv_caf_send (gfc_code
*code
) {
1940 gfc_expr
*lhs_expr
, *rhs_expr
, *tmp_stat
, *tmp_team
;
1941 gfc_se lhs_se
, rhs_se
;
1943 tree caf_decl
, token
, offset
, image_index
, tmp
, lhs_kind
, rhs_kind
;
1944 tree may_require_tmp
, src_stat
, dst_stat
, dst_team
;
1945 tree lhs_type
= NULL_TREE
;
1946 tree vec
= null_pointer_node
, rhs_vec
= null_pointer_node
;
1947 symbol_attribute lhs_caf_attr
, rhs_caf_attr
;
1948 bool lhs_is_coindexed
, rhs_is_coindexed
;
1950 gcc_assert (flag_coarray
== GFC_FCOARRAY_LIB
);
1952 lhs_expr
= code
->ext
.actual
->expr
;
1953 rhs_expr
= code
->ext
.actual
->next
->expr
;
1954 lhs_is_coindexed
= gfc_is_coindexed (lhs_expr
);
1955 rhs_is_coindexed
= gfc_is_coindexed (rhs_expr
);
1956 may_require_tmp
= gfc_check_dependency (lhs_expr
, rhs_expr
, true) == 0
1957 ? boolean_false_node
: boolean_true_node
;
1958 gfc_init_block (&block
);
1960 lhs_caf_attr
= gfc_caf_attr (lhs_expr
);
1961 rhs_caf_attr
= gfc_caf_attr (rhs_expr
);
1962 src_stat
= dst_stat
= null_pointer_node
;
1963 dst_team
= null_pointer_node
;
1966 gfc_init_se (&lhs_se
, NULL
);
1967 if (lhs_expr
->rank
== 0)
1969 if (lhs_expr
->ts
.type
== BT_CHARACTER
&& lhs_expr
->ts
.deferred
)
1971 lhs_se
.expr
= gfc_get_tree_for_caf_expr (lhs_expr
);
1972 if (!POINTER_TYPE_P (TREE_TYPE (lhs_se
.expr
)))
1973 lhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, lhs_se
.expr
);
1977 symbol_attribute attr
;
1978 gfc_clear_attr (&attr
);
1979 gfc_conv_expr (&lhs_se
, lhs_expr
);
1980 lhs_type
= TREE_TYPE (lhs_se
.expr
);
1981 lhs_se
.expr
= gfc_conv_scalar_to_descriptor (&lhs_se
, lhs_se
.expr
,
1983 lhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, lhs_se
.expr
);
1986 else if ((lhs_caf_attr
.alloc_comp
|| lhs_caf_attr
.pointer_comp
)
1987 && lhs_caf_attr
.codimension
)
1989 lhs_se
.want_pointer
= 1;
1990 gfc_conv_expr_descriptor (&lhs_se
, lhs_expr
);
1991 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1992 has the wrong type if component references are done. */
1993 lhs_type
= gfc_typenode_for_spec (&lhs_expr
->ts
);
1994 tmp
= build_fold_indirect_ref_loc (input_location
, lhs_se
.expr
);
1995 gfc_add_modify (&lhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
1996 gfc_get_dtype_rank_type (
1997 gfc_has_vector_subscript (lhs_expr
)
1998 ? gfc_find_array_ref (lhs_expr
)->dimen
2004 bool has_vector
= gfc_has_vector_subscript (lhs_expr
);
2006 if (lhs_is_coindexed
|| !has_vector
)
2008 /* If has_vector, pass descriptor for whole array and the
2009 vector bounds separately. */
2010 gfc_array_ref
*ar
, ar2
;
2011 bool has_tmp_lhs_array
= false;
2014 has_tmp_lhs_array
= true;
2015 ar
= gfc_find_array_ref (lhs_expr
);
2017 memset (ar
, '\0', sizeof (*ar
));
2021 lhs_se
.want_pointer
= 1;
2022 gfc_conv_expr_descriptor (&lhs_se
, lhs_expr
);
2023 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but
2024 that has the wrong type if component references are done. */
2025 lhs_type
= gfc_typenode_for_spec (&lhs_expr
->ts
);
2026 tmp
= build_fold_indirect_ref_loc (input_location
, lhs_se
.expr
);
2027 gfc_add_modify (&lhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
2028 gfc_get_dtype_rank_type (has_vector
? ar2
.dimen
2031 if (has_tmp_lhs_array
)
2033 vec
= conv_caf_vector_subscript (&block
, lhs_se
.expr
, &ar2
);
2037 else if (rhs_is_coindexed
)
2039 /* Special casing for arr1 ([...]) = arr2[...], i.e. caf_get to
2040 indexed array expression. This is rewritten to:
2042 tmp_array = arr2[...]
2043 arr1 ([...]) = tmp_array
2045 because using the standard gfc_conv_expr (lhs_expr) did the
2046 assignment with lhs and rhs exchanged. */
2048 gfc_ss
*lss_for_tmparray
, *lss_real
;
2052 tree tmparr_desc
, src
;
2053 tree index
= gfc_index_zero_node
;
2054 tree stride
= gfc_index_zero_node
;
2057 /* Walk both sides of the assignment, once to get the shape of the
2058 temporary array to create right. */
2059 lss_for_tmparray
= gfc_walk_expr (lhs_expr
);
2060 /* And a second time to be able to create an assignment of the
2061 temporary to the lhs_expr. gfc_trans_create_temp_array replaces
2062 the tree in the descriptor with the one for the temporary
2064 lss_real
= gfc_walk_expr (lhs_expr
);
2065 gfc_init_loopinfo (&loop
);
2066 gfc_add_ss_to_loop (&loop
, lss_for_tmparray
);
2067 gfc_add_ss_to_loop (&loop
, lss_real
);
2068 gfc_conv_ss_startstride (&loop
);
2069 gfc_conv_loop_setup (&loop
, &lhs_expr
->where
);
2070 lhs_type
= gfc_typenode_for_spec (&lhs_expr
->ts
);
2071 gfc_trans_create_temp_array (&lhs_se
.pre
, &lhs_se
.post
,
2072 lss_for_tmparray
, lhs_type
, NULL_TREE
,
2075 tmparr_desc
= lss_for_tmparray
->info
->data
.array
.descriptor
;
2076 gfc_start_scalarized_body (&loop
, &body
);
2077 gfc_init_se (&se
, NULL
);
2078 gfc_copy_loopinfo_to_se (&se
, &loop
);
2080 gfc_conv_expr (&se
, lhs_expr
);
2081 gfc_add_block_to_block (&body
, &se
.pre
);
2083 /* Walk over all indexes of the loop. */
2084 for (n
= loop
.dimen
- 1; n
> 0; --n
)
2086 tmp
= loop
.loopvar
[n
];
2087 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
2088 gfc_array_index_type
, tmp
, loop
.from
[n
]);
2089 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
2090 gfc_array_index_type
, tmp
, index
);
2092 stride
= fold_build2_loc (input_location
, MINUS_EXPR
,
2093 gfc_array_index_type
,
2094 loop
.to
[n
- 1], loop
.from
[n
- 1]);
2095 stride
= fold_build2_loc (input_location
, PLUS_EXPR
,
2096 gfc_array_index_type
,
2097 stride
, gfc_index_one_node
);
2099 index
= fold_build2_loc (input_location
, MULT_EXPR
,
2100 gfc_array_index_type
, tmp
, stride
);
2103 index
= fold_build2_loc (input_location
, MINUS_EXPR
,
2104 gfc_array_index_type
,
2105 index
, loop
.from
[0]);
2107 index
= fold_build2_loc (input_location
, PLUS_EXPR
,
2108 gfc_array_index_type
,
2109 loop
.loopvar
[0], index
);
2111 src
= build_fold_indirect_ref (gfc_conv_array_data (tmparr_desc
));
2112 src
= gfc_build_array_ref (src
, index
, NULL
);
2113 /* Now create the assignment of lhs_expr = tmp_array. */
2114 gfc_add_modify (&body
, se
.expr
, src
);
2115 gfc_add_block_to_block (&body
, &se
.post
);
2116 lhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, tmparr_desc
);
2117 gfc_trans_scalarizing_loops (&loop
, &body
);
2118 gfc_add_block_to_block (&loop
.pre
, &loop
.post
);
2119 gfc_add_expr_to_block (&lhs_se
.post
, gfc_finish_block (&loop
.pre
));
2120 gfc_free_ss (lss_for_tmparray
);
2121 gfc_free_ss (lss_real
);
2125 lhs_kind
= build_int_cst (integer_type_node
, lhs_expr
->ts
.kind
);
2127 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
2128 temporary and a loop. */
2129 if (!lhs_is_coindexed
&& rhs_is_coindexed
2130 && (!lhs_caf_attr
.codimension
2131 || !(lhs_expr
->rank
> 0
2132 && (lhs_caf_attr
.allocatable
|| lhs_caf_attr
.pointer
))))
2134 bool lhs_may_realloc
= lhs_expr
->rank
> 0 && lhs_caf_attr
.allocatable
;
2135 gfc_init_se (&rhs_se
, NULL
);
2136 if (lhs_expr
->rank
== 0 && lhs_caf_attr
.allocatable
)
2139 gfc_init_se (&scal_se
, NULL
);
2140 scal_se
.want_pointer
= 1;
2141 gfc_conv_expr (&scal_se
, lhs_expr
);
2142 /* Ensure scalar on lhs is allocated. */
2143 gfc_add_block_to_block (&block
, &scal_se
.pre
);
2145 gfc_allocate_using_malloc (&scal_se
.pre
, scal_se
.expr
,
2147 gfc_typenode_for_spec (&lhs_expr
->ts
)),
2149 tmp
= fold_build2 (EQ_EXPR
, logical_type_node
, scal_se
.expr
,
2151 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
2152 tmp
, gfc_finish_block (&scal_se
.pre
),
2153 build_empty_stmt (input_location
));
2154 gfc_add_expr_to_block (&block
, tmp
);
2157 lhs_may_realloc
= lhs_may_realloc
2158 && gfc_full_array_ref_p (lhs_expr
->ref
, NULL
);
2159 gfc_add_block_to_block (&block
, &lhs_se
.pre
);
2160 gfc_conv_intrinsic_caf_get (&rhs_se
, rhs_expr
, lhs_se
.expr
, lhs_kind
,
2161 may_require_tmp
, lhs_may_realloc
,
2163 gfc_add_block_to_block (&block
, &rhs_se
.pre
);
2164 gfc_add_block_to_block (&block
, &rhs_se
.post
);
2165 gfc_add_block_to_block (&block
, &lhs_se
.post
);
2166 return gfc_finish_block (&block
);
2169 gfc_add_block_to_block (&block
, &lhs_se
.pre
);
2171 /* Obtain token, offset and image index for the LHS. */
2172 caf_decl
= gfc_get_tree_for_caf_expr (lhs_expr
);
2173 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
2174 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
2175 image_index
= gfc_caf_get_image_index (&block
, lhs_expr
, caf_decl
);
2177 if (lhs_caf_attr
.alloc_comp
)
2178 gfc_get_caf_token_offset (&lhs_se
, &token
, NULL
, caf_decl
, NULL_TREE
,
2181 gfc_get_caf_token_offset (&lhs_se
, &token
, &offset
, caf_decl
, tmp
,
2186 gfc_init_se (&rhs_se
, NULL
);
2187 if (rhs_expr
->expr_type
== EXPR_FUNCTION
&& rhs_expr
->value
.function
.isym
2188 && rhs_expr
->value
.function
.isym
->id
== GFC_ISYM_CONVERSION
)
2189 rhs_expr
= rhs_expr
->value
.function
.actual
->expr
;
2190 if (rhs_expr
->rank
== 0)
2192 symbol_attribute attr
;
2193 gfc_clear_attr (&attr
);
2194 gfc_conv_expr (&rhs_se
, rhs_expr
);
2195 rhs_se
.expr
= gfc_conv_scalar_to_descriptor (&rhs_se
, rhs_se
.expr
, attr
);
2196 rhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, rhs_se
.expr
);
2198 else if ((rhs_caf_attr
.alloc_comp
|| rhs_caf_attr
.pointer_comp
)
2199 && rhs_caf_attr
.codimension
)
2202 rhs_se
.want_pointer
= 1;
2203 gfc_conv_expr_descriptor (&rhs_se
, rhs_expr
);
2204 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2205 has the wrong type if component references are done. */
2206 tmp2
= gfc_typenode_for_spec (&rhs_expr
->ts
);
2207 tmp
= build_fold_indirect_ref_loc (input_location
, rhs_se
.expr
);
2208 gfc_add_modify (&rhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
2209 gfc_get_dtype_rank_type (
2210 gfc_has_vector_subscript (rhs_expr
)
2211 ? gfc_find_array_ref (rhs_expr
)->dimen
2217 /* If has_vector, pass descriptor for whole array and the
2218 vector bounds separately. */
2219 gfc_array_ref
*ar
, ar2
;
2220 bool has_vector
= false;
2223 if (rhs_is_coindexed
&& gfc_has_vector_subscript (rhs_expr
))
2226 ar
= gfc_find_array_ref (rhs_expr
);
2228 memset (ar
, '\0', sizeof (*ar
));
2232 rhs_se
.want_pointer
= 1;
2233 gfc_conv_expr_descriptor (&rhs_se
, rhs_expr
);
2234 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2235 has the wrong type if component references are done. */
2236 tmp
= build_fold_indirect_ref_loc (input_location
, rhs_se
.expr
);
2237 tmp2
= gfc_typenode_for_spec (&rhs_expr
->ts
);
2238 gfc_add_modify (&rhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
2239 gfc_get_dtype_rank_type (has_vector
? ar2
.dimen
2244 rhs_vec
= conv_caf_vector_subscript (&block
, rhs_se
.expr
, &ar2
);
2249 gfc_add_block_to_block (&block
, &rhs_se
.pre
);
2251 rhs_kind
= build_int_cst (integer_type_node
, rhs_expr
->ts
.kind
);
2253 tmp_stat
= gfc_find_stat_co (lhs_expr
);
2258 gfc_init_se (&stat_se
, NULL
);
2259 gfc_conv_expr_reference (&stat_se
, tmp_stat
);
2260 dst_stat
= stat_se
.expr
;
2261 gfc_add_block_to_block (&block
, &stat_se
.pre
);
2262 gfc_add_block_to_block (&block
, &stat_se
.post
);
2265 tmp_team
= gfc_find_team_co (lhs_expr
);
2270 gfc_init_se (&team_se
, NULL
);
2271 gfc_conv_expr_reference (&team_se
, tmp_team
);
2272 dst_team
= team_se
.expr
;
2273 gfc_add_block_to_block (&block
, &team_se
.pre
);
2274 gfc_add_block_to_block (&block
, &team_se
.post
);
2277 if (!rhs_is_coindexed
)
2279 if (lhs_caf_attr
.alloc_comp
|| lhs_caf_attr
.pointer_comp
)
2281 tree reference
, dst_realloc
;
2282 reference
= conv_expr_ref_to_caf_ref (&block
, lhs_expr
);
2283 dst_realloc
= lhs_caf_attr
.allocatable
? boolean_true_node
2284 : boolean_false_node
;
2285 tmp
= build_call_expr_loc (input_location
,
2286 gfor_fndecl_caf_send_by_ref
,
2287 10, token
, image_index
, rhs_se
.expr
,
2288 reference
, lhs_kind
, rhs_kind
,
2289 may_require_tmp
, dst_realloc
, src_stat
,
2290 build_int_cst (integer_type_node
,
2291 lhs_expr
->ts
.type
));
2294 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_send
, 11,
2295 token
, offset
, image_index
, lhs_se
.expr
, vec
,
2296 rhs_se
.expr
, lhs_kind
, rhs_kind
,
2297 may_require_tmp
, src_stat
, dst_team
);
2301 tree rhs_token
, rhs_offset
, rhs_image_index
;
2303 /* It guarantees memory consistency within the same segment. */
2304 tmp
= gfc_build_string_const (strlen ("memory") + 1, "memory");
2305 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
2306 gfc_build_string_const (1, ""), NULL_TREE
, NULL_TREE
,
2307 tree_cons (NULL_TREE
, tmp
, NULL_TREE
), NULL_TREE
);
2308 ASM_VOLATILE_P (tmp
) = 1;
2309 gfc_add_expr_to_block (&block
, tmp
);
2311 caf_decl
= gfc_get_tree_for_caf_expr (rhs_expr
);
2312 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
2313 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
2314 rhs_image_index
= gfc_caf_get_image_index (&block
, rhs_expr
, caf_decl
);
2316 if (rhs_caf_attr
.alloc_comp
|| rhs_caf_attr
.pointer_comp
)
2318 tmp_stat
= gfc_find_stat_co (lhs_expr
);
2323 gfc_init_se (&stat_se
, NULL
);
2324 gfc_conv_expr_reference (&stat_se
, tmp_stat
);
2325 src_stat
= stat_se
.expr
;
2326 gfc_add_block_to_block (&block
, &stat_se
.pre
);
2327 gfc_add_block_to_block (&block
, &stat_se
.post
);
2330 gfc_get_caf_token_offset (&rhs_se
, &rhs_token
, NULL
, caf_decl
,
2332 tree lhs_reference
, rhs_reference
;
2333 lhs_reference
= conv_expr_ref_to_caf_ref (&block
, lhs_expr
);
2334 rhs_reference
= conv_expr_ref_to_caf_ref (&block
, rhs_expr
);
2335 tmp
= build_call_expr_loc (input_location
,
2336 gfor_fndecl_caf_sendget_by_ref
, 13,
2337 token
, image_index
, lhs_reference
,
2338 rhs_token
, rhs_image_index
, rhs_reference
,
2339 lhs_kind
, rhs_kind
, may_require_tmp
,
2341 build_int_cst (integer_type_node
,
2343 build_int_cst (integer_type_node
,
2344 rhs_expr
->ts
.type
));
2348 gfc_get_caf_token_offset (&rhs_se
, &rhs_token
, &rhs_offset
, caf_decl
,
2350 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_sendget
,
2351 14, token
, offset
, image_index
,
2352 lhs_se
.expr
, vec
, rhs_token
, rhs_offset
,
2353 rhs_image_index
, tmp
, rhs_vec
, lhs_kind
,
2354 rhs_kind
, may_require_tmp
, src_stat
);
2357 gfc_add_expr_to_block (&block
, tmp
);
2358 gfc_add_block_to_block (&block
, &lhs_se
.post
);
2359 gfc_add_block_to_block (&block
, &rhs_se
.post
);
2361 /* It guarantees memory consistency within the same segment. */
2362 tmp
= gfc_build_string_const (strlen ("memory") + 1, "memory");
2363 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
2364 gfc_build_string_const (1, ""), NULL_TREE
, NULL_TREE
,
2365 tree_cons (NULL_TREE
, tmp
, NULL_TREE
), NULL_TREE
);
2366 ASM_VOLATILE_P (tmp
) = 1;
2367 gfc_add_expr_to_block (&block
, tmp
);
2369 return gfc_finish_block (&block
);
2374 trans_this_image (gfc_se
* se
, gfc_expr
*expr
)
2377 tree type
, desc
, dim_arg
, cond
, tmp
, m
, loop_var
, exit_label
, min_var
,
2378 lbound
, ubound
, extent
, ml
;
2381 gfc_expr
*distance
= expr
->value
.function
.actual
->next
->next
->expr
;
2383 if (expr
->value
.function
.actual
->expr
2384 && !gfc_is_coarray (expr
->value
.function
.actual
->expr
))
2385 distance
= expr
->value
.function
.actual
->expr
;
2387 /* The case -fcoarray=single is handled elsewhere. */
2388 gcc_assert (flag_coarray
!= GFC_FCOARRAY_SINGLE
);
2390 /* Argument-free version: THIS_IMAGE(). */
2391 if (distance
|| expr
->value
.function
.actual
->expr
== NULL
)
2395 gfc_init_se (&argse
, NULL
);
2396 gfc_conv_expr_val (&argse
, distance
);
2397 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2398 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2399 tmp
= fold_convert (integer_type_node
, argse
.expr
);
2402 tmp
= integer_zero_node
;
2403 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_this_image
, 1,
2405 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
),
2410 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2412 type
= gfc_get_int_type (gfc_default_integer_kind
);
2413 corank
= expr
->value
.function
.actual
->expr
->corank
;
2414 rank
= expr
->value
.function
.actual
->expr
->rank
;
2416 /* Obtain the descriptor of the COARRAY. */
2417 gfc_init_se (&argse
, NULL
);
2418 argse
.want_coarray
= 1;
2419 gfc_conv_expr_descriptor (&argse
, expr
->value
.function
.actual
->expr
);
2420 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2421 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2426 /* Create an implicit second parameter from the loop variable. */
2427 gcc_assert (!expr
->value
.function
.actual
->next
->expr
);
2428 gcc_assert (corank
> 0);
2429 gcc_assert (se
->loop
->dimen
== 1);
2430 gcc_assert (se
->ss
->info
->expr
== expr
);
2432 dim_arg
= se
->loop
->loopvar
[0];
2433 dim_arg
= fold_build2_loc (input_location
, PLUS_EXPR
,
2434 gfc_array_index_type
, dim_arg
,
2435 build_int_cst (TREE_TYPE (dim_arg
), 1));
2436 gfc_advance_se_ss_chain (se
);
2440 /* Use the passed DIM= argument. */
2441 gcc_assert (expr
->value
.function
.actual
->next
->expr
);
2442 gfc_init_se (&argse
, NULL
);
2443 gfc_conv_expr_type (&argse
, expr
->value
.function
.actual
->next
->expr
,
2444 gfc_array_index_type
);
2445 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2446 dim_arg
= argse
.expr
;
2448 if (INTEGER_CST_P (dim_arg
))
2450 if (wi::ltu_p (wi::to_wide (dim_arg
), 1)
2451 || wi::gtu_p (wi::to_wide (dim_arg
),
2452 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))))
2453 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2454 "dimension index", expr
->value
.function
.isym
->name
,
2457 else if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
2459 dim_arg
= gfc_evaluate_now (dim_arg
, &se
->pre
);
2460 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
2462 build_int_cst (TREE_TYPE (dim_arg
), 1));
2463 tmp
= gfc_rank_cst
[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))];
2464 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
2466 cond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
2467 logical_type_node
, cond
, tmp
);
2468 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
2473 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2474 one always has a dim_arg argument.
2476 m = this_image() - 1
2479 sub(1) = m + lcobound(corank)
2483 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2486 extent = gfc_extent(i)
2494 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2495 : m + lcobound(corank)
2498 /* this_image () - 1. */
2499 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_this_image
, 1,
2501 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, type
,
2502 fold_convert (type
, tmp
), build_int_cst (type
, 1));
2505 /* sub(1) = m + lcobound(corank). */
2506 lbound
= gfc_conv_descriptor_lbound_get (desc
,
2507 build_int_cst (TREE_TYPE (gfc_array_index_type
),
2509 lbound
= fold_convert (type
, lbound
);
2510 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, tmp
, lbound
);
2516 m
= gfc_create_var (type
, NULL
);
2517 ml
= gfc_create_var (type
, NULL
);
2518 loop_var
= gfc_create_var (integer_type_node
, NULL
);
2519 min_var
= gfc_create_var (integer_type_node
, NULL
);
2521 /* m = this_image () - 1. */
2522 gfc_add_modify (&se
->pre
, m
, tmp
);
2524 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2525 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, integer_type_node
,
2526 fold_convert (integer_type_node
, dim_arg
),
2527 build_int_cst (integer_type_node
, rank
- 1));
2528 tmp
= fold_build2_loc (input_location
, MIN_EXPR
, integer_type_node
,
2529 build_int_cst (integer_type_node
, rank
+ corank
- 2),
2531 gfc_add_modify (&se
->pre
, min_var
, tmp
);
2534 tmp
= build_int_cst (integer_type_node
, rank
);
2535 gfc_add_modify (&se
->pre
, loop_var
, tmp
);
2537 exit_label
= gfc_build_label_decl (NULL_TREE
);
2538 TREE_USED (exit_label
) = 1;
2541 gfc_init_block (&loop
);
2544 gfc_add_modify (&loop
, ml
, m
);
2547 lbound
= gfc_conv_descriptor_lbound_get (desc
, loop_var
);
2548 ubound
= gfc_conv_descriptor_ubound_get (desc
, loop_var
);
2549 extent
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
2550 extent
= fold_convert (type
, extent
);
2553 gfc_add_modify (&loop
, m
,
2554 fold_build2_loc (input_location
, TRUNC_DIV_EXPR
, type
,
2557 /* Exit condition: if (i >= min_var) goto exit_label. */
2558 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, loop_var
,
2560 tmp
= build1_v (GOTO_EXPR
, exit_label
);
2561 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
, tmp
,
2562 build_empty_stmt (input_location
));
2563 gfc_add_expr_to_block (&loop
, tmp
);
2565 /* Increment loop variable: i++. */
2566 gfc_add_modify (&loop
, loop_var
,
2567 fold_build2_loc (input_location
, PLUS_EXPR
, integer_type_node
,
2571 /* Making the loop... actually loop! */
2572 tmp
= gfc_finish_block (&loop
);
2573 tmp
= build1_v (LOOP_EXPR
, tmp
);
2574 gfc_add_expr_to_block (&se
->pre
, tmp
);
2576 /* The exit label. */
2577 tmp
= build1_v (LABEL_EXPR
, exit_label
);
2578 gfc_add_expr_to_block (&se
->pre
, tmp
);
2580 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2581 : m + lcobound(corank) */
2583 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
, dim_arg
,
2584 build_int_cst (TREE_TYPE (dim_arg
), corank
));
2586 lbound
= gfc_conv_descriptor_lbound_get (desc
,
2587 fold_build2_loc (input_location
, PLUS_EXPR
,
2588 gfc_array_index_type
, dim_arg
,
2589 build_int_cst (TREE_TYPE (dim_arg
), rank
-1)));
2590 lbound
= fold_convert (type
, lbound
);
2592 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, type
, ml
,
2593 fold_build2_loc (input_location
, MULT_EXPR
, type
,
2595 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, tmp
, lbound
);
2597 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
, tmp
,
2598 fold_build2_loc (input_location
, PLUS_EXPR
, type
,
2603 /* Convert a call to image_status. */
2606 conv_intrinsic_image_status (gfc_se
*se
, gfc_expr
*expr
)
2608 unsigned int num_args
;
2611 num_args
= gfc_intrinsic_argument_list_length (expr
);
2612 args
= XALLOCAVEC (tree
, num_args
);
2613 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
2614 /* In args[0] the number of the image the status is desired for has to be
2617 if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
2620 arg
= gfc_evaluate_now (args
[0], &se
->pre
);
2621 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
2622 fold_convert (integer_type_node
, arg
),
2624 tmp
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
2625 tmp
, integer_zero_node
,
2626 build_int_cst (integer_type_node
,
2627 GFC_STAT_STOPPED_IMAGE
));
2629 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
2630 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_image_status
, 2,
2631 args
[0], build_int_cst (integer_type_node
, -1));
2635 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
), tmp
);
2639 conv_intrinsic_team_number (gfc_se
*se
, gfc_expr
*expr
)
2641 unsigned int num_args
;
2645 num_args
= gfc_intrinsic_argument_list_length (expr
);
2646 args
= XALLOCAVEC (tree
, num_args
);
2647 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
2650 GFC_FCOARRAY_SINGLE
&& expr
->value
.function
.actual
->expr
)
2654 arg
= gfc_evaluate_now (args
[0], &se
->pre
);
2655 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
2656 fold_convert (integer_type_node
, arg
),
2658 tmp
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
2659 tmp
, integer_zero_node
,
2660 build_int_cst (integer_type_node
,
2661 GFC_STAT_STOPPED_IMAGE
));
2663 else if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
2665 // the value -1 represents that no team has been created yet
2666 tmp
= build_int_cst (integer_type_node
, -1);
2668 else if (flag_coarray
== GFC_FCOARRAY_LIB
&& expr
->value
.function
.actual
->expr
)
2669 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_team_number
, 1,
2670 args
[0], build_int_cst (integer_type_node
, -1));
2671 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
2672 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_team_number
, 1,
2673 integer_zero_node
, build_int_cst (integer_type_node
, -1));
2677 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
), tmp
);
2682 trans_image_index (gfc_se
* se
, gfc_expr
*expr
)
2684 tree num_images
, cond
, coindex
, type
, lbound
, ubound
, desc
, subdesc
,
2686 gfc_se argse
, subse
;
2687 int rank
, corank
, codim
;
2689 type
= gfc_get_int_type (gfc_default_integer_kind
);
2690 corank
= expr
->value
.function
.actual
->expr
->corank
;
2691 rank
= expr
->value
.function
.actual
->expr
->rank
;
2693 /* Obtain the descriptor of the COARRAY. */
2694 gfc_init_se (&argse
, NULL
);
2695 argse
.want_coarray
= 1;
2696 gfc_conv_expr_descriptor (&argse
, expr
->value
.function
.actual
->expr
);
2697 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2698 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2701 /* Obtain a handle to the SUB argument. */
2702 gfc_init_se (&subse
, NULL
);
2703 gfc_conv_expr_descriptor (&subse
, expr
->value
.function
.actual
->next
->expr
);
2704 gfc_add_block_to_block (&se
->pre
, &subse
.pre
);
2705 gfc_add_block_to_block (&se
->post
, &subse
.post
);
2706 subdesc
= build_fold_indirect_ref_loc (input_location
,
2707 gfc_conv_descriptor_data_get (subse
.expr
));
2709 /* Fortran 2008 does not require that the values remain in the cobounds,
2710 thus we need explicitly check this - and return 0 if they are exceeded. */
2712 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[rank
+corank
-1]);
2713 tmp
= gfc_build_array_ref (subdesc
, gfc_rank_cst
[corank
-1], NULL
);
2714 invalid_bound
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
2715 fold_convert (gfc_array_index_type
, tmp
),
2718 for (codim
= corank
+ rank
- 2; codim
>= rank
; codim
--)
2720 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[codim
]);
2721 ubound
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[codim
]);
2722 tmp
= gfc_build_array_ref (subdesc
, gfc_rank_cst
[codim
-rank
], NULL
);
2723 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
2724 fold_convert (gfc_array_index_type
, tmp
),
2726 invalid_bound
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
2727 logical_type_node
, invalid_bound
, cond
);
2728 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
2729 fold_convert (gfc_array_index_type
, tmp
),
2731 invalid_bound
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
2732 logical_type_node
, invalid_bound
, cond
);
2735 invalid_bound
= gfc_unlikely (invalid_bound
, PRED_FORTRAN_INVALID_BOUND
);
2737 /* See Fortran 2008, C.10 for the following algorithm. */
2739 /* coindex = sub(corank) - lcobound(n). */
2740 coindex
= fold_convert (gfc_array_index_type
,
2741 gfc_build_array_ref (subdesc
, gfc_rank_cst
[corank
-1],
2743 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[rank
+corank
-1]);
2744 coindex
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
2745 fold_convert (gfc_array_index_type
, coindex
),
2748 for (codim
= corank
+ rank
- 2; codim
>= rank
; codim
--)
2750 tree extent
, ubound
;
2752 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2753 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[codim
]);
2754 ubound
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[codim
]);
2755 extent
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
2757 /* coindex *= extent. */
2758 coindex
= fold_build2_loc (input_location
, MULT_EXPR
,
2759 gfc_array_index_type
, coindex
, extent
);
2761 /* coindex += sub(codim). */
2762 tmp
= gfc_build_array_ref (subdesc
, gfc_rank_cst
[codim
-rank
], NULL
);
2763 coindex
= fold_build2_loc (input_location
, PLUS_EXPR
,
2764 gfc_array_index_type
, coindex
,
2765 fold_convert (gfc_array_index_type
, tmp
));
2767 /* coindex -= lbound(codim). */
2768 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[codim
]);
2769 coindex
= fold_build2_loc (input_location
, MINUS_EXPR
,
2770 gfc_array_index_type
, coindex
, lbound
);
2773 coindex
= fold_build2_loc (input_location
, PLUS_EXPR
, type
,
2774 fold_convert(type
, coindex
),
2775 build_int_cst (type
, 1));
2777 /* Return 0 if "coindex" exceeds num_images(). */
2779 if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
2780 num_images
= build_int_cst (type
, 1);
2783 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
, 2,
2785 build_int_cst (integer_type_node
, -1));
2786 num_images
= fold_convert (type
, tmp
);
2789 tmp
= gfc_create_var (type
, NULL
);
2790 gfc_add_modify (&se
->pre
, tmp
, coindex
);
2792 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
, tmp
,
2794 cond
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
, logical_type_node
,
2796 fold_convert (logical_type_node
, invalid_bound
));
2797 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
2798 build_int_cst (type
, 0), tmp
);
2802 trans_num_images (gfc_se
* se
, gfc_expr
*expr
)
2804 tree tmp
, distance
, failed
;
2807 if (expr
->value
.function
.actual
->expr
)
2809 gfc_init_se (&argse
, NULL
);
2810 gfc_conv_expr_val (&argse
, expr
->value
.function
.actual
->expr
);
2811 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2812 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2813 distance
= fold_convert (integer_type_node
, argse
.expr
);
2816 distance
= integer_zero_node
;
2818 if (expr
->value
.function
.actual
->next
->expr
)
2820 gfc_init_se (&argse
, NULL
);
2821 gfc_conv_expr_val (&argse
, expr
->value
.function
.actual
->next
->expr
);
2822 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2823 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2824 failed
= fold_convert (integer_type_node
, argse
.expr
);
2827 failed
= build_int_cst (integer_type_node
, -1);
2828 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
, 2,
2830 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
), tmp
);
2835 gfc_conv_intrinsic_rank (gfc_se
*se
, gfc_expr
*expr
)
2839 gfc_init_se (&argse
, NULL
);
2840 argse
.data_not_needed
= 1;
2841 argse
.descriptor_only
= 1;
2843 gfc_conv_expr_descriptor (&argse
, expr
->value
.function
.actual
->expr
);
2844 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2845 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2847 se
->expr
= gfc_conv_descriptor_rank (argse
.expr
);
2848 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
),
2854 gfc_conv_intrinsic_is_contiguous (gfc_se
* se
, gfc_expr
* expr
)
2857 arg
= expr
->value
.function
.actual
->expr
;
2858 gfc_conv_is_contiguous_expr (se
, arg
);
2859 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
2862 /* This function does the work for gfc_conv_intrinsic_is_contiguous,
2863 plus it can be called directly. */
2866 gfc_conv_is_contiguous_expr (gfc_se
*se
, gfc_expr
*arg
)
2870 tree desc
, tmp
, stride
, extent
, cond
;
2875 if (arg
->ts
.type
== BT_CLASS
)
2876 gfc_add_class_array_ref (arg
);
2878 ss
= gfc_walk_expr (arg
);
2879 gcc_assert (ss
!= gfc_ss_terminator
);
2880 gfc_init_se (&argse
, NULL
);
2881 argse
.data_not_needed
= 1;
2882 gfc_conv_expr_descriptor (&argse
, arg
);
2884 as
= gfc_get_full_arrayspec_from_expr (arg
);
2886 /* Create: stride[0] == 1 && stride[1] == extend[0]*stride[0] && ...
2887 Note in addition that zero-sized arrays don't count as contiguous. */
2889 if (as
&& as
->type
== AS_ASSUMED_RANK
)
2891 /* Build the call to is_contiguous0. */
2892 argse
.want_pointer
= 1;
2893 gfc_conv_expr_descriptor (&argse
, arg
);
2894 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2895 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2896 desc
= gfc_evaluate_now (argse
.expr
, &se
->pre
);
2897 fncall0
= build_call_expr_loc (input_location
,
2898 gfor_fndecl_is_contiguous0
, 1, desc
);
2900 se
->expr
= convert (logical_type_node
, se
->expr
);
2904 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2905 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2906 desc
= gfc_evaluate_now (argse
.expr
, &se
->pre
);
2908 stride
= gfc_conv_descriptor_stride_get (desc
, gfc_rank_cst
[0]);
2909 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
2910 stride
, build_int_cst (TREE_TYPE (stride
), 1));
2912 for (i
= 0; i
< arg
->rank
- 1; i
++)
2914 tmp
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[i
]);
2915 extent
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[i
]);
2916 extent
= fold_build2_loc (input_location
, MINUS_EXPR
,
2917 gfc_array_index_type
, extent
, tmp
);
2918 extent
= fold_build2_loc (input_location
, PLUS_EXPR
,
2919 gfc_array_index_type
, extent
,
2920 gfc_index_one_node
);
2921 tmp
= gfc_conv_descriptor_stride_get (desc
, gfc_rank_cst
[i
]);
2922 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, TREE_TYPE (tmp
),
2924 stride
= gfc_conv_descriptor_stride_get (desc
, gfc_rank_cst
[i
+1]);
2925 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
2927 cond
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
2928 boolean_type_node
, cond
, tmp
);
2935 /* Evaluate a single upper or lower bound. */
2936 /* TODO: bound intrinsic generates way too much unnecessary code. */
2939 gfc_conv_intrinsic_bound (gfc_se
* se
, gfc_expr
* expr
, enum gfc_isym_id op
)
2941 gfc_actual_arglist
*arg
;
2942 gfc_actual_arglist
*arg2
;
2952 gfc_array_spec
* as
;
2953 bool assumed_rank_lb_one
;
2955 arg
= expr
->value
.function
.actual
;
2960 /* Create an implicit second parameter from the loop variable. */
2961 gcc_assert (!arg2
->expr
|| op
== GFC_ISYM_SHAPE
);
2962 gcc_assert (se
->loop
->dimen
== 1);
2963 gcc_assert (se
->ss
->info
->expr
== expr
);
2964 gfc_advance_se_ss_chain (se
);
2965 bound
= se
->loop
->loopvar
[0];
2966 bound
= fold_build2_loc (input_location
, MINUS_EXPR
,
2967 gfc_array_index_type
, bound
,
2972 /* use the passed argument. */
2973 gcc_assert (arg2
->expr
);
2974 gfc_init_se (&argse
, NULL
);
2975 gfc_conv_expr_type (&argse
, arg2
->expr
, gfc_array_index_type
);
2976 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2978 /* Convert from one based to zero based. */
2979 bound
= fold_build2_loc (input_location
, MINUS_EXPR
,
2980 gfc_array_index_type
, bound
,
2981 gfc_index_one_node
);
2984 /* TODO: don't re-evaluate the descriptor on each iteration. */
2985 /* Get a descriptor for the first parameter. */
2986 gfc_init_se (&argse
, NULL
);
2987 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
2988 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2989 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2993 as
= gfc_get_full_arrayspec_from_expr (arg
->expr
);
2995 if (INTEGER_CST_P (bound
))
2997 gcc_assert (op
!= GFC_ISYM_SHAPE
);
2998 if (((!as
|| as
->type
!= AS_ASSUMED_RANK
)
2999 && wi::geu_p (wi::to_wide (bound
),
3000 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc
))))
3001 || wi::gtu_p (wi::to_wide (bound
), GFC_MAX_DIMENSIONS
))
3002 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3004 (op
== GFC_ISYM_UBOUND
) ? "UBOUND" : "LBOUND",
3008 if (!INTEGER_CST_P (bound
) || (as
&& as
->type
== AS_ASSUMED_RANK
))
3010 if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
3012 bound
= gfc_evaluate_now (bound
, &se
->pre
);
3013 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3014 bound
, build_int_cst (TREE_TYPE (bound
), 0));
3015 if (as
&& as
->type
== AS_ASSUMED_RANK
)
3016 tmp
= gfc_conv_descriptor_rank (desc
);
3018 tmp
= gfc_rank_cst
[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc
))];
3019 tmp
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
3020 bound
, fold_convert(TREE_TYPE (bound
), tmp
));
3021 cond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
3022 logical_type_node
, cond
, tmp
);
3023 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
3028 /* Take care of the lbound shift for assumed-rank arrays that are
3029 nonallocatable and nonpointers. Those have a lbound of 1. */
3030 assumed_rank_lb_one
= as
&& as
->type
== AS_ASSUMED_RANK
3031 && ((arg
->expr
->ts
.type
!= BT_CLASS
3032 && !arg
->expr
->symtree
->n
.sym
->attr
.allocatable
3033 && !arg
->expr
->symtree
->n
.sym
->attr
.pointer
)
3034 || (arg
->expr
->ts
.type
== BT_CLASS
3035 && !CLASS_DATA (arg
->expr
)->attr
.allocatable
3036 && !CLASS_DATA (arg
->expr
)->attr
.class_pointer
));
3038 ubound
= gfc_conv_descriptor_ubound_get (desc
, bound
);
3039 lbound
= gfc_conv_descriptor_lbound_get (desc
, bound
);
3040 size
= fold_build2_loc (input_location
, MINUS_EXPR
,
3041 gfc_array_index_type
, ubound
, lbound
);
3042 size
= fold_build2_loc (input_location
, PLUS_EXPR
,
3043 gfc_array_index_type
, size
, gfc_index_one_node
);
3045 /* 13.14.53: Result value for LBOUND
3047 Case (i): For an array section or for an array expression other than a
3048 whole array or array structure component, LBOUND(ARRAY, DIM)
3049 has the value 1. For a whole array or array structure
3050 component, LBOUND(ARRAY, DIM) has the value:
3051 (a) equal to the lower bound for subscript DIM of ARRAY if
3052 dimension DIM of ARRAY does not have extent zero
3053 or if ARRAY is an assumed-size array of rank DIM,
3056 13.14.113: Result value for UBOUND
3058 Case (i): For an array section or for an array expression other than a
3059 whole array or array structure component, UBOUND(ARRAY, DIM)
3060 has the value equal to the number of elements in the given
3061 dimension; otherwise, it has a value equal to the upper bound
3062 for subscript DIM of ARRAY if dimension DIM of ARRAY does
3063 not have size zero and has value zero if dimension DIM has
3066 if (op
== GFC_ISYM_LBOUND
&& assumed_rank_lb_one
)
3067 se
->expr
= gfc_index_one_node
;
3070 if (op
== GFC_ISYM_UBOUND
)
3072 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3073 size
, gfc_index_zero_node
);
3074 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
3075 gfc_array_index_type
, cond
,
3076 (assumed_rank_lb_one
? size
: ubound
),
3077 gfc_index_zero_node
);
3079 else if (op
== GFC_ISYM_LBOUND
)
3081 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3082 size
, gfc_index_zero_node
);
3083 if (as
->type
== AS_ASSUMED_SIZE
)
3085 cond1
= fold_build2_loc (input_location
, EQ_EXPR
,
3086 logical_type_node
, bound
,
3087 build_int_cst (TREE_TYPE (bound
),
3088 arg
->expr
->rank
- 1));
3089 cond
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
3090 logical_type_node
, cond
, cond1
);
3092 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
3093 gfc_array_index_type
, cond
,
3094 lbound
, gfc_index_one_node
);
3096 else if (op
== GFC_ISYM_SHAPE
)
3097 se
->expr
= fold_build2_loc (input_location
, MAX_EXPR
,
3098 gfc_array_index_type
, size
,
3099 gfc_index_zero_node
);
3103 /* According to F2018 16.9.172, para 5, an assumed rank object,
3104 argument associated with and assumed size array, has the ubound
3105 of the final dimension set to -1 and UBOUND must return this.
3106 Similarly for the SHAPE intrinsic. */
3107 if (op
!= GFC_ISYM_LBOUND
&& assumed_rank_lb_one
)
3109 tree minus_one
= build_int_cst (gfc_array_index_type
, -1);
3110 tree rank
= fold_convert (gfc_array_index_type
,
3111 gfc_conv_descriptor_rank (desc
));
3112 rank
= fold_build2_loc (input_location
, PLUS_EXPR
,
3113 gfc_array_index_type
, rank
, minus_one
);
3115 /* Fix the expression to stop it from becoming even more
3117 se
->expr
= gfc_evaluate_now (se
->expr
, &se
->pre
);
3119 /* Descriptors for assumed-size arrays have ubound = -1
3120 in the last dimension. */
3121 cond1
= fold_build2_loc (input_location
, EQ_EXPR
,
3122 logical_type_node
, ubound
, minus_one
);
3123 cond
= fold_build2_loc (input_location
, EQ_EXPR
,
3124 logical_type_node
, bound
, rank
);
3125 cond
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
3126 logical_type_node
, cond
, cond1
);
3127 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
3128 gfc_array_index_type
, cond
,
3129 minus_one
, se
->expr
);
3132 else /* as is null; this is an old-fashioned 1-based array. */
3134 if (op
!= GFC_ISYM_LBOUND
)
3136 se
->expr
= fold_build2_loc (input_location
, MAX_EXPR
,
3137 gfc_array_index_type
, size
,
3138 gfc_index_zero_node
);
3141 se
->expr
= gfc_index_one_node
;
3145 type
= gfc_typenode_for_spec (&expr
->ts
);
3146 se
->expr
= convert (type
, se
->expr
);
3151 conv_intrinsic_cobound (gfc_se
* se
, gfc_expr
* expr
)
3153 gfc_actual_arglist
*arg
;
3154 gfc_actual_arglist
*arg2
;
3156 tree bound
, resbound
, resbound2
, desc
, cond
, tmp
;
3160 gcc_assert (expr
->value
.function
.isym
->id
== GFC_ISYM_LCOBOUND
3161 || expr
->value
.function
.isym
->id
== GFC_ISYM_UCOBOUND
3162 || expr
->value
.function
.isym
->id
== GFC_ISYM_THIS_IMAGE
);
3164 arg
= expr
->value
.function
.actual
;
3167 gcc_assert (arg
->expr
->expr_type
== EXPR_VARIABLE
);
3168 corank
= arg
->expr
->corank
;
3170 gfc_init_se (&argse
, NULL
);
3171 argse
.want_coarray
= 1;
3173 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
3174 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3175 gfc_add_block_to_block (&se
->post
, &argse
.post
);
3180 /* Create an implicit second parameter from the loop variable. */
3181 gcc_assert (!arg2
->expr
);
3182 gcc_assert (corank
> 0);
3183 gcc_assert (se
->loop
->dimen
== 1);
3184 gcc_assert (se
->ss
->info
->expr
== expr
);
3186 bound
= se
->loop
->loopvar
[0];
3187 bound
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
3188 bound
, gfc_rank_cst
[arg
->expr
->rank
]);
3189 gfc_advance_se_ss_chain (se
);
3193 /* use the passed argument. */
3194 gcc_assert (arg2
->expr
);
3195 gfc_init_se (&argse
, NULL
);
3196 gfc_conv_expr_type (&argse
, arg2
->expr
, gfc_array_index_type
);
3197 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3200 if (INTEGER_CST_P (bound
))
3202 if (wi::ltu_p (wi::to_wide (bound
), 1)
3203 || wi::gtu_p (wi::to_wide (bound
),
3204 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))))
3205 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3206 "dimension index", expr
->value
.function
.isym
->name
,
3209 else if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
3211 bound
= gfc_evaluate_now (bound
, &se
->pre
);
3212 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3213 bound
, build_int_cst (TREE_TYPE (bound
), 1));
3214 tmp
= gfc_rank_cst
[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))];
3215 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3217 cond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
3218 logical_type_node
, cond
, tmp
);
3219 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
3224 /* Subtract 1 to get to zero based and add dimensions. */
3225 switch (arg
->expr
->rank
)
3228 bound
= fold_build2_loc (input_location
, MINUS_EXPR
,
3229 gfc_array_index_type
, bound
,
3230 gfc_index_one_node
);
3234 bound
= fold_build2_loc (input_location
, PLUS_EXPR
,
3235 gfc_array_index_type
, bound
,
3236 gfc_rank_cst
[arg
->expr
->rank
- 1]);
3240 resbound
= gfc_conv_descriptor_lbound_get (desc
, bound
);
3242 /* Handle UCOBOUND with special handling of the last codimension. */
3243 if (expr
->value
.function
.isym
->id
== GFC_ISYM_UCOBOUND
)
3245 /* Last codimension: For -fcoarray=single just return
3246 the lcobound - otherwise add
3247 ceiling (real (num_images ()) / real (size)) - 1
3248 = (num_images () + size - 1) / size - 1
3249 = (num_images - 1) / size(),
3250 where size is the product of the extent of all but the last
3253 if (flag_coarray
!= GFC_FCOARRAY_SINGLE
&& corank
> 1)
3257 cosize
= gfc_conv_descriptor_cosize (desc
, arg
->expr
->rank
, corank
);
3258 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
,
3259 2, integer_zero_node
,
3260 build_int_cst (integer_type_node
, -1));
3261 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
3262 gfc_array_index_type
,
3263 fold_convert (gfc_array_index_type
, tmp
),
3264 build_int_cst (gfc_array_index_type
, 1));
3265 tmp
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
3266 gfc_array_index_type
, tmp
,
3267 fold_convert (gfc_array_index_type
, cosize
));
3268 resbound
= fold_build2_loc (input_location
, PLUS_EXPR
,
3269 gfc_array_index_type
, resbound
, tmp
);
3271 else if (flag_coarray
!= GFC_FCOARRAY_SINGLE
)
3273 /* ubound = lbound + num_images() - 1. */
3274 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
,
3275 2, integer_zero_node
,
3276 build_int_cst (integer_type_node
, -1));
3277 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
3278 gfc_array_index_type
,
3279 fold_convert (gfc_array_index_type
, tmp
),
3280 build_int_cst (gfc_array_index_type
, 1));
3281 resbound
= fold_build2_loc (input_location
, PLUS_EXPR
,
3282 gfc_array_index_type
, resbound
, tmp
);
3287 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
3289 build_int_cst (TREE_TYPE (bound
),
3290 arg
->expr
->rank
+ corank
- 1));
3292 resbound2
= gfc_conv_descriptor_ubound_get (desc
, bound
);
3293 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
3294 gfc_array_index_type
, cond
,
3295 resbound
, resbound2
);
3298 se
->expr
= resbound
;
3301 se
->expr
= resbound
;
3303 type
= gfc_typenode_for_spec (&expr
->ts
);
3304 se
->expr
= convert (type
, se
->expr
);
3309 conv_intrinsic_stride (gfc_se
* se
, gfc_expr
* expr
)
3311 gfc_actual_arglist
*array_arg
;
3312 gfc_actual_arglist
*dim_arg
;
3316 array_arg
= expr
->value
.function
.actual
;
3317 dim_arg
= array_arg
->next
;
3319 gcc_assert (array_arg
->expr
->expr_type
== EXPR_VARIABLE
);
3321 gfc_init_se (&argse
, NULL
);
3322 gfc_conv_expr_descriptor (&argse
, array_arg
->expr
);
3323 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3324 gfc_add_block_to_block (&se
->post
, &argse
.post
);
3327 gcc_assert (dim_arg
->expr
);
3328 gfc_init_se (&argse
, NULL
);
3329 gfc_conv_expr_type (&argse
, dim_arg
->expr
, gfc_array_index_type
);
3330 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3331 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
3332 argse
.expr
, gfc_index_one_node
);
3333 se
->expr
= gfc_conv_descriptor_stride_get (desc
, tmp
);
3337 gfc_conv_intrinsic_abs (gfc_se
* se
, gfc_expr
* expr
)
3341 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
3343 switch (expr
->value
.function
.actual
->expr
->ts
.type
)
3347 se
->expr
= fold_build1_loc (input_location
, ABS_EXPR
, TREE_TYPE (arg
),
3352 cabs
= gfc_builtin_decl_for_float_kind (BUILT_IN_CABS
, expr
->ts
.kind
);
3353 se
->expr
= build_call_expr_loc (input_location
, cabs
, 1, arg
);
3362 /* Create a complex value from one or two real components. */
3365 gfc_conv_intrinsic_cmplx (gfc_se
* se
, gfc_expr
* expr
, int both
)
3371 unsigned int num_args
;
3373 num_args
= gfc_intrinsic_argument_list_length (expr
);
3374 args
= XALLOCAVEC (tree
, num_args
);
3376 type
= gfc_typenode_for_spec (&expr
->ts
);
3377 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
3378 real
= convert (TREE_TYPE (type
), args
[0]);
3380 imag
= convert (TREE_TYPE (type
), args
[1]);
3381 else if (TREE_CODE (TREE_TYPE (args
[0])) == COMPLEX_TYPE
)
3383 imag
= fold_build1_loc (input_location
, IMAGPART_EXPR
,
3384 TREE_TYPE (TREE_TYPE (args
[0])), args
[0]);
3385 imag
= convert (TREE_TYPE (type
), imag
);
3388 imag
= build_real_from_int_cst (TREE_TYPE (type
), integer_zero_node
);
3390 se
->expr
= fold_build2_loc (input_location
, COMPLEX_EXPR
, type
, real
, imag
);
3394 /* Remainder function MOD(A, P) = A - INT(A / P) * P
3395 MODULO(A, P) = A - FLOOR (A / P) * P
3397 The obvious algorithms above are numerically instable for large
3398 arguments, hence these intrinsics are instead implemented via calls
3399 to the fmod family of functions. It is the responsibility of the
3400 user to ensure that the second argument is non-zero. */
3403 gfc_conv_intrinsic_mod (gfc_se
* se
, gfc_expr
* expr
, int modulo
)
3413 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
3415 switch (expr
->ts
.type
)
3418 /* Integer case is easy, we've got a builtin op. */
3419 type
= TREE_TYPE (args
[0]);
3422 se
->expr
= fold_build2_loc (input_location
, FLOOR_MOD_EXPR
, type
,
3425 se
->expr
= fold_build2_loc (input_location
, TRUNC_MOD_EXPR
, type
,
3430 /* Even easier, we only need one. */
3431 type
= TREE_TYPE (args
[0]);
3432 se
->expr
= fold_build2_loc (input_location
, TRUNC_MOD_EXPR
, type
,
3438 /* Check if we have a builtin fmod. */
3439 fmod
= gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD
, expr
->ts
.kind
);
3441 /* The builtin should always be available. */
3442 gcc_assert (fmod
!= NULL_TREE
);
3444 tmp
= build_addr (fmod
);
3445 se
->expr
= build_call_array_loc (input_location
,
3446 TREE_TYPE (TREE_TYPE (fmod
)),
3451 type
= TREE_TYPE (args
[0]);
3453 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
3454 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
3457 modulo = arg - floor (arg/arg2) * arg2
3459 In order to calculate the result accurately, we use the fmod
3460 function as follows.
3462 res = fmod (arg, arg2);
3465 if ((arg < 0) xor (arg2 < 0))
3469 res = copysign (0., arg2);
3471 => As two nested ternary exprs:
3473 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3474 : copysign (0., arg2);
3478 zero
= gfc_build_const (type
, integer_zero_node
);
3479 tmp
= gfc_evaluate_now (se
->expr
, &se
->pre
);
3480 if (!flag_signed_zeros
)
3482 test
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3484 test2
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3486 test2
= fold_build2_loc (input_location
, TRUTH_XOR_EXPR
,
3487 logical_type_node
, test
, test2
);
3488 test
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
3490 test
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
3491 logical_type_node
, test
, test2
);
3492 test
= gfc_evaluate_now (test
, &se
->pre
);
3493 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, test
,
3494 fold_build2_loc (input_location
,
3496 type
, tmp
, args
[1]),
3501 tree expr1
, copysign
, cscall
;
3502 copysign
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
,
3504 test
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3506 test2
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3508 test2
= fold_build2_loc (input_location
, TRUTH_XOR_EXPR
,
3509 logical_type_node
, test
, test2
);
3510 expr1
= fold_build3_loc (input_location
, COND_EXPR
, type
, test2
,
3511 fold_build2_loc (input_location
,
3513 type
, tmp
, args
[1]),
3515 test
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
3517 cscall
= build_call_expr_loc (input_location
, copysign
, 2, zero
,
3519 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, test
,
3529 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3530 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3531 where the right shifts are logical (i.e. 0's are shifted in).
3532 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3533 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3535 DSHIFTL(I,J,BITSIZE) = J
3537 DSHIFTR(I,J,BITSIZE) = I. */
3540 gfc_conv_intrinsic_dshift (gfc_se
* se
, gfc_expr
* expr
, bool dshiftl
)
3542 tree type
, utype
, stype
, arg1
, arg2
, shift
, res
, left
, right
;
3543 tree args
[3], cond
, tmp
;
3546 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
3548 gcc_assert (TREE_TYPE (args
[0]) == TREE_TYPE (args
[1]));
3549 type
= TREE_TYPE (args
[0]);
3550 bitsize
= TYPE_PRECISION (type
);
3551 utype
= unsigned_type_for (type
);
3552 stype
= TREE_TYPE (args
[2]);
3554 arg1
= gfc_evaluate_now (args
[0], &se
->pre
);
3555 arg2
= gfc_evaluate_now (args
[1], &se
->pre
);
3556 shift
= gfc_evaluate_now (args
[2], &se
->pre
);
3558 /* The generic case. */
3559 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, stype
,
3560 build_int_cst (stype
, bitsize
), shift
);
3561 left
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
3562 arg1
, dshiftl
? shift
: tmp
);
3564 right
= fold_build2_loc (input_location
, RSHIFT_EXPR
, utype
,
3565 fold_convert (utype
, arg2
), dshiftl
? tmp
: shift
);
3566 right
= fold_convert (type
, right
);
3568 res
= fold_build2_loc (input_location
, BIT_IOR_EXPR
, type
, left
, right
);
3570 /* Special cases. */
3571 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, shift
,
3572 build_int_cst (stype
, 0));
3573 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
3574 dshiftl
? arg1
: arg2
, res
);
3576 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, shift
,
3577 build_int_cst (stype
, bitsize
));
3578 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
3579 dshiftl
? arg2
: arg1
, res
);
3585 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3588 gfc_conv_intrinsic_dim (gfc_se
* se
, gfc_expr
* expr
)
3596 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
3597 type
= TREE_TYPE (args
[0]);
3599 val
= fold_build2_loc (input_location
, MINUS_EXPR
, type
, args
[0], args
[1]);
3600 val
= gfc_evaluate_now (val
, &se
->pre
);
3602 zero
= gfc_build_const (type
, integer_zero_node
);
3603 tmp
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
, val
, zero
);
3604 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, zero
, val
);
3608 /* SIGN(A, B) is absolute value of A times sign of B.
3609 The real value versions use library functions to ensure the correct
3610 handling of negative zero. Integer case implemented as:
3611 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3615 gfc_conv_intrinsic_sign (gfc_se
* se
, gfc_expr
* expr
)
3621 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
3622 if (expr
->ts
.type
== BT_REAL
)
3626 tmp
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
, expr
->ts
.kind
);
3627 abs
= gfc_builtin_decl_for_float_kind (BUILT_IN_FABS
, expr
->ts
.kind
);
3629 /* We explicitly have to ignore the minus sign. We do so by using
3630 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3632 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args
[1]))))
3635 zero
= build_real_from_int_cst (TREE_TYPE (args
[1]), integer_zero_node
);
3636 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
3638 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
3639 TREE_TYPE (args
[0]), cond
,
3640 build_call_expr_loc (input_location
, abs
, 1,
3642 build_call_expr_loc (input_location
, tmp
, 2,
3646 se
->expr
= build_call_expr_loc (input_location
, tmp
, 2,
3651 /* Having excluded floating point types, we know we are now dealing
3652 with signed integer types. */
3653 type
= TREE_TYPE (args
[0]);
3655 /* Args[0] is used multiple times below. */
3656 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
3658 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3659 the signs of A and B are the same, and of all ones if they differ. */
3660 tmp
= fold_build2_loc (input_location
, BIT_XOR_EXPR
, type
, args
[0], args
[1]);
3661 tmp
= fold_build2_loc (input_location
, RSHIFT_EXPR
, type
, tmp
,
3662 build_int_cst (type
, TYPE_PRECISION (type
) - 1));
3663 tmp
= gfc_evaluate_now (tmp
, &se
->pre
);
3665 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3666 is all ones (i.e. -1). */
3667 se
->expr
= fold_build2_loc (input_location
, BIT_XOR_EXPR
, type
,
3668 fold_build2_loc (input_location
, PLUS_EXPR
,
3669 type
, args
[0], tmp
), tmp
);
3673 /* Test for the presence of an optional argument. */
3676 gfc_conv_intrinsic_present (gfc_se
* se
, gfc_expr
* expr
)
3680 arg
= expr
->value
.function
.actual
->expr
;
3681 gcc_assert (arg
->expr_type
== EXPR_VARIABLE
);
3682 se
->expr
= gfc_conv_expr_present (arg
->symtree
->n
.sym
);
3683 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
3687 /* Calculate the double precision product of two single precision values. */
3690 gfc_conv_intrinsic_dprod (gfc_se
* se
, gfc_expr
* expr
)
3695 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
3697 /* Convert the args to double precision before multiplying. */
3698 type
= gfc_typenode_for_spec (&expr
->ts
);
3699 args
[0] = convert (type
, args
[0]);
3700 args
[1] = convert (type
, args
[1]);
3701 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, type
, args
[0],
3706 /* Return a length one character string containing an ascii character. */
3709 gfc_conv_intrinsic_char (gfc_se
* se
, gfc_expr
* expr
)
3714 unsigned int num_args
;
3716 num_args
= gfc_intrinsic_argument_list_length (expr
);
3717 gfc_conv_intrinsic_function_args (se
, expr
, arg
, num_args
);
3719 type
= gfc_get_char_type (expr
->ts
.kind
);
3720 var
= gfc_create_var (type
, "char");
3722 arg
[0] = fold_build1_loc (input_location
, NOP_EXPR
, type
, arg
[0]);
3723 gfc_add_modify (&se
->pre
, var
, arg
[0]);
3724 se
->expr
= gfc_build_addr_expr (build_pointer_type (type
), var
);
3725 se
->string_length
= build_int_cst (gfc_charlen_type_node
, 1);
3730 gfc_conv_intrinsic_ctime (gfc_se
* se
, gfc_expr
* expr
)
3738 unsigned int num_args
;
3740 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
3741 args
= XALLOCAVEC (tree
, num_args
);
3743 var
= gfc_create_var (pchar_type_node
, "pstr");
3744 len
= gfc_create_var (gfc_charlen_type_node
, "len");
3746 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
3747 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
3748 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
3750 fndecl
= build_addr (gfor_fndecl_ctime
);
3751 tmp
= build_call_array_loc (input_location
,
3752 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime
)),
3753 fndecl
, num_args
, args
);
3754 gfc_add_expr_to_block (&se
->pre
, tmp
);
3756 /* Free the temporary afterwards, if necessary. */
3757 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3758 len
, build_int_cst (TREE_TYPE (len
), 0));
3759 tmp
= gfc_call_free (var
);
3760 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
3761 gfc_add_expr_to_block (&se
->post
, tmp
);
3764 se
->string_length
= len
;
3769 gfc_conv_intrinsic_fdate (gfc_se
* se
, gfc_expr
* expr
)
3777 unsigned int num_args
;
3779 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
3780 args
= XALLOCAVEC (tree
, num_args
);
3782 var
= gfc_create_var (pchar_type_node
, "pstr");
3783 len
= gfc_create_var (gfc_charlen_type_node
, "len");
3785 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
3786 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
3787 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
3789 fndecl
= build_addr (gfor_fndecl_fdate
);
3790 tmp
= build_call_array_loc (input_location
,
3791 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate
)),
3792 fndecl
, num_args
, args
);
3793 gfc_add_expr_to_block (&se
->pre
, tmp
);
3795 /* Free the temporary afterwards, if necessary. */
3796 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3797 len
, build_int_cst (TREE_TYPE (len
), 0));
3798 tmp
= gfc_call_free (var
);
3799 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
3800 gfc_add_expr_to_block (&se
->post
, tmp
);
3803 se
->string_length
= len
;
3807 /* Generate a direct call to free() for the FREE subroutine. */
3810 conv_intrinsic_free (gfc_code
*code
)
3816 gfc_init_se (&argse
, NULL
);
3817 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
3818 arg
= fold_convert (ptr_type_node
, argse
.expr
);
3820 gfc_init_block (&block
);
3821 call
= build_call_expr_loc (input_location
,
3822 builtin_decl_explicit (BUILT_IN_FREE
), 1, arg
);
3823 gfc_add_expr_to_block (&block
, call
);
3824 return gfc_finish_block (&block
);
3828 /* Call the RANDOM_INIT library subroutine with a hidden argument for
3829 handling seeding on coarray images. */
3832 conv_intrinsic_random_init (gfc_code
*code
)
3836 tree arg1
, arg2
, tmp
;
3837 /* On none coarray == lib compiles use LOGICAL(4) else regular LOGICAL. */
3838 tree used_bool_type_node
= flag_coarray
== GFC_FCOARRAY_LIB
3840 : gfc_get_logical_type (4);
3842 /* Make the function call. */
3843 gfc_init_block (&block
);
3844 gfc_init_se (&se
, NULL
);
3846 /* Convert REPEATABLE to the desired LOGICAL entity. */
3847 gfc_conv_expr (&se
, code
->ext
.actual
->expr
);
3848 gfc_add_block_to_block (&block
, &se
.pre
);
3849 arg1
= fold_convert (used_bool_type_node
, gfc_evaluate_now (se
.expr
, &block
));
3850 gfc_add_block_to_block (&block
, &se
.post
);
3852 /* Convert IMAGE_DISTINCT to the desired LOGICAL entity. */
3853 gfc_conv_expr (&se
, code
->ext
.actual
->next
->expr
);
3854 gfc_add_block_to_block (&block
, &se
.pre
);
3855 arg2
= fold_convert (used_bool_type_node
, gfc_evaluate_now (se
.expr
, &block
));
3856 gfc_add_block_to_block (&block
, &se
.post
);
3858 if (flag_coarray
== GFC_FCOARRAY_LIB
)
3860 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_random_init
,
3865 /* The ABI for libgfortran needs to be maintained, so a hidden
3866 argument must be include if code is compiled with -fcoarray=single
3867 or without the option. Set to 0. */
3868 tree arg3
= build_int_cst (gfc_get_int_type (4), 0);
3869 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_random_init
,
3870 3, arg1
, arg2
, arg3
);
3873 gfc_add_expr_to_block (&block
, tmp
);
3875 return gfc_finish_block (&block
);
3879 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3883 conv_intrinsic_system_clock (gfc_code
*code
)
3886 gfc_se count_se
, count_rate_se
, count_max_se
;
3887 tree arg1
= NULL_TREE
, arg2
= NULL_TREE
, arg3
= NULL_TREE
;
3891 gfc_expr
*count
= code
->ext
.actual
->expr
;
3892 gfc_expr
*count_rate
= code
->ext
.actual
->next
->expr
;
3893 gfc_expr
*count_max
= code
->ext
.actual
->next
->next
->expr
;
3895 /* Evaluate our arguments. */
3898 gfc_init_se (&count_se
, NULL
);
3899 gfc_conv_expr (&count_se
, count
);
3904 gfc_init_se (&count_rate_se
, NULL
);
3905 gfc_conv_expr (&count_rate_se
, count_rate
);
3910 gfc_init_se (&count_max_se
, NULL
);
3911 gfc_conv_expr (&count_max_se
, count_max
);
3914 /* Find the smallest kind found of the arguments. */
3916 least
= (count
&& count
->ts
.kind
< least
) ? count
->ts
.kind
: least
;
3917 least
= (count_rate
&& count_rate
->ts
.kind
< least
) ? count_rate
->ts
.kind
3919 least
= (count_max
&& count_max
->ts
.kind
< least
) ? count_max
->ts
.kind
3922 /* Prepare temporary variables. */
3927 arg1
= gfc_create_var (gfc_get_int_type (8), "count");
3928 else if (least
== 4)
3929 arg1
= gfc_create_var (gfc_get_int_type (4), "count");
3930 else if (count
->ts
.kind
== 1)
3931 arg1
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[0].pedantic_min_int
,
3934 arg1
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[1].pedantic_min_int
,
3941 arg2
= gfc_create_var (gfc_get_int_type (8), "count_rate");
3942 else if (least
== 4)
3943 arg2
= gfc_create_var (gfc_get_int_type (4), "count_rate");
3945 arg2
= integer_zero_node
;
3951 arg3
= gfc_create_var (gfc_get_int_type (8), "count_max");
3952 else if (least
== 4)
3953 arg3
= gfc_create_var (gfc_get_int_type (4), "count_max");
3955 arg3
= integer_zero_node
;
3958 /* Make the function call. */
3959 gfc_init_block (&block
);
3965 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
3966 : null_pointer_node
;
3967 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
3968 : null_pointer_node
;
3969 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
3970 : null_pointer_node
;
3975 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
3976 : null_pointer_node
;
3977 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
3978 : null_pointer_node
;
3979 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
3980 : null_pointer_node
;
3987 tmp
= build_call_expr_loc (input_location
,
3988 gfor_fndecl_system_clock4
, 3,
3989 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
3990 : null_pointer_node
,
3991 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
3992 : null_pointer_node
,
3993 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
3994 : null_pointer_node
);
3995 gfc_add_expr_to_block (&block
, tmp
);
3997 /* Handle kind>=8, 10, or 16 arguments */
4000 tmp
= build_call_expr_loc (input_location
,
4001 gfor_fndecl_system_clock8
, 3,
4002 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
4003 : null_pointer_node
,
4004 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
4005 : null_pointer_node
,
4006 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
4007 : null_pointer_node
);
4008 gfc_add_expr_to_block (&block
, tmp
);
4012 /* And store values back if needed. */
4013 if (arg1
&& arg1
!= count_se
.expr
)
4014 gfc_add_modify (&block
, count_se
.expr
,
4015 fold_convert (TREE_TYPE (count_se
.expr
), arg1
));
4016 if (arg2
&& arg2
!= count_rate_se
.expr
)
4017 gfc_add_modify (&block
, count_rate_se
.expr
,
4018 fold_convert (TREE_TYPE (count_rate_se
.expr
), arg2
));
4019 if (arg3
&& arg3
!= count_max_se
.expr
)
4020 gfc_add_modify (&block
, count_max_se
.expr
,
4021 fold_convert (TREE_TYPE (count_max_se
.expr
), arg3
));
4023 return gfc_finish_block (&block
);
4027 /* Return a character string containing the tty name. */
4030 gfc_conv_intrinsic_ttynam (gfc_se
* se
, gfc_expr
* expr
)
4038 unsigned int num_args
;
4040 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
4041 args
= XALLOCAVEC (tree
, num_args
);
4043 var
= gfc_create_var (pchar_type_node
, "pstr");
4044 len
= gfc_create_var (gfc_charlen_type_node
, "len");
4046 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
4047 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
4048 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
4050 fndecl
= build_addr (gfor_fndecl_ttynam
);
4051 tmp
= build_call_array_loc (input_location
,
4052 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam
)),
4053 fndecl
, num_args
, args
);
4054 gfc_add_expr_to_block (&se
->pre
, tmp
);
4056 /* Free the temporary afterwards, if necessary. */
4057 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
4058 len
, build_int_cst (TREE_TYPE (len
), 0));
4059 tmp
= gfc_call_free (var
);
4060 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
4061 gfc_add_expr_to_block (&se
->post
, tmp
);
4064 se
->string_length
= len
;
4068 /* Get the minimum/maximum value of all the parameters.
4069 minmax (a1, a2, a3, ...)
4072 mvar = COMP (mvar, a2)
4073 mvar = COMP (mvar, a3)
4077 Where COMP is MIN/MAX_EXPR for integral types or when we don't
4078 care about NaNs, or IFN_FMIN/MAX when the target has support for
4079 fast NaN-honouring min/max. When neither holds expand a sequence
4080 of explicit comparisons. */
4082 /* TODO: Mismatching types can occur when specific names are used.
4083 These should be handled during resolution. */
4085 gfc_conv_intrinsic_minmax (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
4093 gfc_actual_arglist
*argexpr
;
4094 unsigned int i
, nargs
;
4096 nargs
= gfc_intrinsic_argument_list_length (expr
);
4097 args
= XALLOCAVEC (tree
, nargs
);
4099 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
4100 type
= gfc_typenode_for_spec (&expr
->ts
);
4102 /* Only evaluate the argument once. */
4103 if (!VAR_P (args
[0]) && !TREE_CONSTANT (args
[0]))
4104 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
4106 /* Determine suitable type of temporary, as a GNU extension allows
4107 different argument kinds. */
4108 argtype
= TREE_TYPE (args
[0]);
4109 argexpr
= expr
->value
.function
.actual
;
4110 for (i
= 1, argexpr
= argexpr
->next
; i
< nargs
; i
++, argexpr
= argexpr
->next
)
4112 tree tmptype
= TREE_TYPE (args
[i
]);
4113 if (TYPE_PRECISION (tmptype
) > TYPE_PRECISION (argtype
))
4116 mvar
= gfc_create_var (argtype
, "M");
4117 gfc_add_modify (&se
->pre
, mvar
, convert (argtype
, args
[0]));
4119 argexpr
= expr
->value
.function
.actual
;
4120 for (i
= 1, argexpr
= argexpr
->next
; i
< nargs
; i
++, argexpr
= argexpr
->next
)
4122 tree cond
= NULL_TREE
;
4125 /* Handle absent optional arguments by ignoring the comparison. */
4126 if (argexpr
->expr
->expr_type
== EXPR_VARIABLE
4127 && argexpr
->expr
->symtree
->n
.sym
->attr
.optional
4128 && INDIRECT_REF_P (val
))
4130 cond
= fold_build2_loc (input_location
,
4131 NE_EXPR
, logical_type_node
,
4132 TREE_OPERAND (val
, 0),
4133 build_int_cst (TREE_TYPE (TREE_OPERAND (val
, 0)), 0));
4135 else if (!VAR_P (val
) && !TREE_CONSTANT (val
))
4136 /* Only evaluate the argument once. */
4137 val
= gfc_evaluate_now (val
, &se
->pre
);
4140 /* For floating point types, the question is what MAX(a, NaN) or
4141 MIN(a, NaN) should return (where "a" is a normal number).
4142 There are valid use case for returning either one, but the
4143 Fortran standard doesn't specify which one should be chosen.
4144 Also, there is no consensus among other tested compilers. In
4145 short, it's a mess. So lets just do whatever is fastest. */
4146 tree_code code
= op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
;
4147 calc
= fold_build2_loc (input_location
, code
, argtype
,
4148 convert (argtype
, val
), mvar
);
4149 tmp
= build2_v (MODIFY_EXPR
, mvar
, calc
);
4151 if (cond
!= NULL_TREE
)
4152 tmp
= build3_v (COND_EXPR
, cond
, tmp
,
4153 build_empty_stmt (input_location
));
4154 gfc_add_expr_to_block (&se
->pre
, tmp
);
4156 se
->expr
= convert (type
, mvar
);
4160 /* Generate library calls for MIN and MAX intrinsics for character
4163 gfc_conv_intrinsic_minmax_char (gfc_se
* se
, gfc_expr
* expr
, int op
)
4166 tree var
, len
, fndecl
, tmp
, cond
, function
;
4169 nargs
= gfc_intrinsic_argument_list_length (expr
);
4170 args
= XALLOCAVEC (tree
, nargs
+ 4);
4171 gfc_conv_intrinsic_function_args (se
, expr
, &args
[4], nargs
);
4173 /* Create the result variables. */
4174 len
= gfc_create_var (gfc_charlen_type_node
, "len");
4175 args
[0] = gfc_build_addr_expr (NULL_TREE
, len
);
4176 var
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
), "pstr");
4177 args
[1] = gfc_build_addr_expr (ppvoid_type_node
, var
);
4178 args
[2] = build_int_cst (integer_type_node
, op
);
4179 args
[3] = build_int_cst (integer_type_node
, nargs
/ 2);
4181 if (expr
->ts
.kind
== 1)
4182 function
= gfor_fndecl_string_minmax
;
4183 else if (expr
->ts
.kind
== 4)
4184 function
= gfor_fndecl_string_minmax_char4
;
4188 /* Make the function call. */
4189 fndecl
= build_addr (function
);
4190 tmp
= build_call_array_loc (input_location
,
4191 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
4193 gfc_add_expr_to_block (&se
->pre
, tmp
);
4195 /* Free the temporary afterwards, if necessary. */
4196 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
4197 len
, build_int_cst (TREE_TYPE (len
), 0));
4198 tmp
= gfc_call_free (var
);
4199 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
4200 gfc_add_expr_to_block (&se
->post
, tmp
);
4203 se
->string_length
= len
;
4207 /* Create a symbol node for this intrinsic. The symbol from the frontend
4208 has the generic name. */
4211 gfc_get_symbol_for_expr (gfc_expr
* expr
, bool ignore_optional
)
4215 /* TODO: Add symbols for intrinsic function to the global namespace. */
4216 gcc_assert (strlen (expr
->value
.function
.name
) <= GFC_MAX_SYMBOL_LEN
- 5);
4217 sym
= gfc_new_symbol (expr
->value
.function
.name
, NULL
);
4220 sym
->attr
.external
= 1;
4221 sym
->attr
.function
= 1;
4222 sym
->attr
.always_explicit
= 1;
4223 sym
->attr
.proc
= PROC_INTRINSIC
;
4224 sym
->attr
.flavor
= FL_PROCEDURE
;
4228 sym
->attr
.dimension
= 1;
4229 sym
->as
= gfc_get_array_spec ();
4230 sym
->as
->type
= AS_ASSUMED_SHAPE
;
4231 sym
->as
->rank
= expr
->rank
;
4234 gfc_copy_formal_args_intr (sym
, expr
->value
.function
.isym
,
4235 ignore_optional
? expr
->value
.function
.actual
4241 /* Remove empty actual arguments. */
4244 remove_empty_actual_arguments (gfc_actual_arglist
**ap
)
4248 if ((*ap
)->expr
== NULL
)
4250 gfc_actual_arglist
*r
= *ap
;
4253 gfc_free_actual_arglist (r
);
4256 ap
= &((*ap
)->next
);
4260 #define MAX_SPEC_ARG 12
4262 /* Make up an fn spec that's right for intrinsic functions that we
4266 intrinsic_fnspec (gfc_expr
*expr
)
4268 static char fnspec_buf
[MAX_SPEC_ARG
*2+1];
4273 #define ADD_CHAR(c) do { *fp++ = c; *fp++ = ' '; } while(0)
4275 /* Set the fndecl. */
4277 /* Function return value. FIXME: Check if the second letter could
4278 be something other than a space, for further optimization. */
4280 if (expr
->rank
== 0)
4282 if (expr
->ts
.type
== BT_CHARACTER
)
4284 ADD_CHAR ('w'); /* Address of character. */
4285 ADD_CHAR ('.'); /* Length of character. */
4289 ADD_CHAR ('w'); /* Return value is a descriptor. */
4292 for (gfc_actual_arglist
*a
= expr
->value
.function
.actual
; a
; a
= a
->next
)
4294 if (a
->expr
== NULL
)
4297 if (a
->name
&& strcmp (a
->name
,"%VAL") == 0)
4301 if (a
->expr
->rank
> 0)
4306 num_char_args
+= a
->expr
->ts
.type
== BT_CHARACTER
;
4307 gcc_assert (fp
- fnspec_buf
+ num_char_args
<= MAX_SPEC_ARG
*2);
4310 for (i
= 0; i
< num_char_args
; i
++)
4320 /* Generate the right symbol for the specific intrinsic function and
4321 modify the expr accordingly. This assumes that absent optional
4322 arguments should be removed. */
4325 specific_intrinsic_symbol (gfc_expr
*expr
)
4329 sym
= gfc_find_intrinsic_symbol (expr
);
4332 sym
= gfc_get_intrinsic_function_symbol (expr
);
4334 if (sym
->ts
.type
== BT_CHARACTER
&& sym
->ts
.u
.cl
)
4335 sym
->ts
.u
.cl
= gfc_new_charlen (sym
->ns
, NULL
);
4337 gfc_copy_formal_args_intr (sym
, expr
->value
.function
.isym
,
4338 expr
->value
.function
.actual
, true);
4340 = gfc_get_extern_function_decl (sym
, expr
->value
.function
.actual
,
4341 intrinsic_fnspec (expr
));
4344 remove_empty_actual_arguments (&(expr
->value
.function
.actual
));
4349 /* Generate a call to an external intrinsic function. FIXME: So far,
4350 this only works for functions which are called with well-defined
4351 types; CSHIFT and friends will come later. */
4354 gfc_conv_intrinsic_funcall (gfc_se
* se
, gfc_expr
* expr
)
4357 vec
<tree
, va_gc
> *append_args
;
4358 bool specific_symbol
;
4360 gcc_assert (!se
->ss
|| se
->ss
->info
->expr
== expr
);
4363 gcc_assert (expr
->rank
> 0);
4365 gcc_assert (expr
->rank
== 0);
4367 switch (expr
->value
.function
.isym
->id
)
4371 case GFC_ISYM_FINDLOC
:
4372 case GFC_ISYM_MAXLOC
:
4373 case GFC_ISYM_MINLOC
:
4374 case GFC_ISYM_MAXVAL
:
4375 case GFC_ISYM_MINVAL
:
4376 case GFC_ISYM_NORM2
:
4377 case GFC_ISYM_PRODUCT
:
4379 specific_symbol
= true;
4382 specific_symbol
= false;
4385 if (specific_symbol
)
4387 /* Need to copy here because specific_intrinsic_symbol modifies
4388 expr to omit the absent optional arguments. */
4389 expr
= gfc_copy_expr (expr
);
4390 sym
= specific_intrinsic_symbol (expr
);
4393 sym
= gfc_get_symbol_for_expr (expr
, se
->ignore_optional
);
4395 /* Calls to libgfortran_matmul need to be appended special arguments,
4396 to be able to call the BLAS ?gemm functions if required and possible. */
4398 if (expr
->value
.function
.isym
->id
== GFC_ISYM_MATMUL
4399 && !expr
->external_blas
4400 && sym
->ts
.type
!= BT_LOGICAL
)
4402 tree cint
= gfc_get_int_type (gfc_c_int_kind
);
4404 if (flag_external_blas
4405 && (sym
->ts
.type
== BT_REAL
|| sym
->ts
.type
== BT_COMPLEX
)
4406 && (sym
->ts
.kind
== 4 || sym
->ts
.kind
== 8))
4410 if (sym
->ts
.type
== BT_REAL
)
4412 if (sym
->ts
.kind
== 4)
4413 gemm_fndecl
= gfor_fndecl_sgemm
;
4415 gemm_fndecl
= gfor_fndecl_dgemm
;
4419 if (sym
->ts
.kind
== 4)
4420 gemm_fndecl
= gfor_fndecl_cgemm
;
4422 gemm_fndecl
= gfor_fndecl_zgemm
;
4425 vec_alloc (append_args
, 3);
4426 append_args
->quick_push (build_int_cst (cint
, 1));
4427 append_args
->quick_push (build_int_cst (cint
,
4428 flag_blas_matmul_limit
));
4429 append_args
->quick_push (gfc_build_addr_expr (NULL_TREE
,
4434 vec_alloc (append_args
, 3);
4435 append_args
->quick_push (build_int_cst (cint
, 0));
4436 append_args
->quick_push (build_int_cst (cint
, 0));
4437 append_args
->quick_push (null_pointer_node
);
4441 gfc_conv_procedure_call (se
, sym
, expr
->value
.function
.actual
, expr
,
4444 if (specific_symbol
)
4445 gfc_free_expr (expr
);
4447 gfc_free_symbol (sym
);
4450 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4470 gfc_conv_intrinsic_anyall (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
4479 gfc_actual_arglist
*actual
;
4486 gfc_conv_intrinsic_funcall (se
, expr
);
4490 actual
= expr
->value
.function
.actual
;
4491 type
= gfc_typenode_for_spec (&expr
->ts
);
4492 /* Initialize the result. */
4493 resvar
= gfc_create_var (type
, "test");
4495 tmp
= convert (type
, boolean_true_node
);
4497 tmp
= convert (type
, boolean_false_node
);
4498 gfc_add_modify (&se
->pre
, resvar
, tmp
);
4500 /* Walk the arguments. */
4501 arrayss
= gfc_walk_expr (actual
->expr
);
4502 gcc_assert (arrayss
!= gfc_ss_terminator
);
4504 /* Initialize the scalarizer. */
4505 gfc_init_loopinfo (&loop
);
4506 exit_label
= gfc_build_label_decl (NULL_TREE
);
4507 TREE_USED (exit_label
) = 1;
4508 gfc_add_ss_to_loop (&loop
, arrayss
);
4510 /* Initialize the loop. */
4511 gfc_conv_ss_startstride (&loop
);
4512 gfc_conv_loop_setup (&loop
, &expr
->where
);
4514 gfc_mark_ss_chain_used (arrayss
, 1);
4515 /* Generate the loop body. */
4516 gfc_start_scalarized_body (&loop
, &body
);
4518 /* If the condition matches then set the return value. */
4519 gfc_start_block (&block
);
4521 tmp
= convert (type
, boolean_false_node
);
4523 tmp
= convert (type
, boolean_true_node
);
4524 gfc_add_modify (&block
, resvar
, tmp
);
4526 /* And break out of the loop. */
4527 tmp
= build1_v (GOTO_EXPR
, exit_label
);
4528 gfc_add_expr_to_block (&block
, tmp
);
4530 found
= gfc_finish_block (&block
);
4532 /* Check this element. */
4533 gfc_init_se (&arrayse
, NULL
);
4534 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
4535 arrayse
.ss
= arrayss
;
4536 gfc_conv_expr_val (&arrayse
, actual
->expr
);
4538 gfc_add_block_to_block (&body
, &arrayse
.pre
);
4539 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
, arrayse
.expr
,
4540 build_int_cst (TREE_TYPE (arrayse
.expr
), 0));
4541 tmp
= build3_v (COND_EXPR
, tmp
, found
, build_empty_stmt (input_location
));
4542 gfc_add_expr_to_block (&body
, tmp
);
4543 gfc_add_block_to_block (&body
, &arrayse
.post
);
4545 gfc_trans_scalarizing_loops (&loop
, &body
);
4547 /* Add the exit label. */
4548 tmp
= build1_v (LABEL_EXPR
, exit_label
);
4549 gfc_add_expr_to_block (&loop
.pre
, tmp
);
4551 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
4552 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
4553 gfc_cleanup_loop (&loop
);
4559 /* Generate the constant 180 / pi, which is used in the conversion
4560 of acosd(), asind(), atand(), atan2d(). */
4568 gfc_set_model_kind (kind
);
4571 mpfr_set_si (t0
, 180, GFC_RND_MODE
);
4572 mpfr_const_pi (pi
, GFC_RND_MODE
);
4573 mpfr_div (t0
, t0
, pi
, GFC_RND_MODE
);
4574 retval
= gfc_conv_mpfr_to_tree (t0
, kind
, 0);
4581 static gfc_intrinsic_map_t
*
4582 gfc_lookup_intrinsic (gfc_isym_id id
)
4584 gfc_intrinsic_map_t
*m
= gfc_intrinsic_map
;
4585 for (; m
->id
!= GFC_ISYM_NONE
|| m
->double_built_in
!= END_BUILTINS
; m
++)
4588 gcc_assert (id
== m
->id
);
4593 /* ACOSD(x) is translated into ACOS(x) * 180 / pi.
4594 ASIND(x) is translated into ASIN(x) * 180 / pi.
4595 ATAND(x) is translated into ATAN(x) * 180 / pi. */
4598 gfc_conv_intrinsic_atrigd (gfc_se
* se
, gfc_expr
* expr
, gfc_isym_id id
)
4603 gfc_intrinsic_map_t
*m
;
4605 type
= gfc_typenode_for_spec (&expr
->ts
);
4607 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
4611 case GFC_ISYM_ACOSD
:
4612 m
= gfc_lookup_intrinsic (GFC_ISYM_ACOS
);
4614 case GFC_ISYM_ASIND
:
4615 m
= gfc_lookup_intrinsic (GFC_ISYM_ASIN
);
4617 case GFC_ISYM_ATAND
:
4618 m
= gfc_lookup_intrinsic (GFC_ISYM_ATAN
);
4623 atrigd
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
4624 atrigd
= build_call_expr_loc (input_location
, atrigd
, 1, arg
);
4626 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, type
, atrigd
,
4627 fold_convert (type
, rad2deg (expr
->ts
.kind
)));
4631 /* COTAN(X) is translated into -TAN(X+PI/2) for REAL argument and
4632 COS(X) / SIN(X) for COMPLEX argument. */
4635 gfc_conv_intrinsic_cotan (gfc_se
*se
, gfc_expr
*expr
)
4637 gfc_intrinsic_map_t
*m
;
4641 type
= gfc_typenode_for_spec (&expr
->ts
);
4642 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
4644 if (expr
->ts
.type
== BT_REAL
)
4651 gfc_set_model_kind (expr
->ts
.kind
);
4653 mpfr_const_pi (pio2
, GFC_RND_MODE
);
4654 mpfr_div_ui (pio2
, pio2
, 2, GFC_RND_MODE
);
4655 tmp
= gfc_conv_mpfr_to_tree (pio2
, expr
->ts
.kind
, 0);
4658 /* Find tan builtin function. */
4659 m
= gfc_lookup_intrinsic (GFC_ISYM_TAN
);
4660 tan
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
4661 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, arg
, tmp
);
4662 tan
= build_call_expr_loc (input_location
, tan
, 1, tmp
);
4663 se
->expr
= fold_build1_loc (input_location
, NEGATE_EXPR
, type
, tan
);
4670 /* Find cos builtin function. */
4671 m
= gfc_lookup_intrinsic (GFC_ISYM_COS
);
4672 cos
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
4673 cos
= build_call_expr_loc (input_location
, cos
, 1, arg
);
4675 /* Find sin builtin function. */
4676 m
= gfc_lookup_intrinsic (GFC_ISYM_SIN
);
4677 sin
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
4678 sin
= build_call_expr_loc (input_location
, sin
, 1, arg
);
4680 /* Divide cos by sin. */
4681 se
->expr
= fold_build2_loc (input_location
, RDIV_EXPR
, type
, cos
, sin
);
4686 /* COTAND(X) is translated into -TAND(X+90) for REAL argument. */
4689 gfc_conv_intrinsic_cotand (gfc_se
*se
, gfc_expr
*expr
)
4696 type
= gfc_typenode_for_spec (&expr
->ts
);
4697 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
4699 gfc_set_model_kind (expr
->ts
.kind
);
4701 /* Build the tree for x + 90. */
4702 mpfr_init_set_ui (ninety
, 90, GFC_RND_MODE
);
4703 ninety_tree
= gfc_conv_mpfr_to_tree (ninety
, expr
->ts
.kind
, 0);
4704 arg
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, arg
, ninety_tree
);
4705 mpfr_clear (ninety
);
4708 gfc_intrinsic_map_t
*m
= gfc_lookup_intrinsic (GFC_ISYM_TAND
);
4709 tree tand
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
4710 tand
= build_call_expr_loc (input_location
, tand
, 1, arg
);
4712 se
->expr
= fold_build1_loc (input_location
, NEGATE_EXPR
, type
, tand
);
4716 /* ATAN2D(Y,X) is translated into ATAN2(Y,X) * 180 / PI. */
4719 gfc_conv_intrinsic_atan2d (gfc_se
*se
, gfc_expr
*expr
)
4725 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
4726 type
= TREE_TYPE (args
[0]);
4728 gfc_intrinsic_map_t
*m
= gfc_lookup_intrinsic (GFC_ISYM_ATAN2
);
4729 atan2d
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
4730 atan2d
= build_call_expr_loc (input_location
, atan2d
, 2, args
[0], args
[1]);
4732 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, type
, atan2d
,
4733 rad2deg (expr
->ts
.kind
));
4737 /* COUNT(A) = Number of true elements in A. */
4739 gfc_conv_intrinsic_count (gfc_se
* se
, gfc_expr
* expr
)
4746 gfc_actual_arglist
*actual
;
4752 gfc_conv_intrinsic_funcall (se
, expr
);
4756 actual
= expr
->value
.function
.actual
;
4758 type
= gfc_typenode_for_spec (&expr
->ts
);
4759 /* Initialize the result. */
4760 resvar
= gfc_create_var (type
, "count");
4761 gfc_add_modify (&se
->pre
, resvar
, build_int_cst (type
, 0));
4763 /* Walk the arguments. */
4764 arrayss
= gfc_walk_expr (actual
->expr
);
4765 gcc_assert (arrayss
!= gfc_ss_terminator
);
4767 /* Initialize the scalarizer. */
4768 gfc_init_loopinfo (&loop
);
4769 gfc_add_ss_to_loop (&loop
, arrayss
);
4771 /* Initialize the loop. */
4772 gfc_conv_ss_startstride (&loop
);
4773 gfc_conv_loop_setup (&loop
, &expr
->where
);
4775 gfc_mark_ss_chain_used (arrayss
, 1);
4776 /* Generate the loop body. */
4777 gfc_start_scalarized_body (&loop
, &body
);
4779 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (resvar
),
4780 resvar
, build_int_cst (TREE_TYPE (resvar
), 1));
4781 tmp
= build2_v (MODIFY_EXPR
, resvar
, tmp
);
4783 gfc_init_se (&arrayse
, NULL
);
4784 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
4785 arrayse
.ss
= arrayss
;
4786 gfc_conv_expr_val (&arrayse
, actual
->expr
);
4787 tmp
= build3_v (COND_EXPR
, arrayse
.expr
, tmp
,
4788 build_empty_stmt (input_location
));
4790 gfc_add_block_to_block (&body
, &arrayse
.pre
);
4791 gfc_add_expr_to_block (&body
, tmp
);
4792 gfc_add_block_to_block (&body
, &arrayse
.post
);
4794 gfc_trans_scalarizing_loops (&loop
, &body
);
4796 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
4797 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
4798 gfc_cleanup_loop (&loop
);
4804 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4805 struct and return the corresponding loopinfo. */
4807 static gfc_loopinfo
*
4808 enter_nested_loop (gfc_se
*se
)
4810 se
->ss
= se
->ss
->nested_ss
;
4811 gcc_assert (se
->ss
== se
->ss
->loop
->ss
);
4813 return se
->ss
->loop
;
4816 /* Build the condition for a mask, which may be optional. */
4819 conv_mask_condition (gfc_se
*maskse
, gfc_expr
*maskexpr
,
4827 type
= TREE_TYPE (maskse
->expr
);
4828 present
= gfc_conv_expr_present (maskexpr
->symtree
->n
.sym
);
4829 present
= convert (type
, present
);
4830 present
= fold_build1_loc (input_location
, TRUTH_NOT_EXPR
, type
,
4832 return fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
4833 type
, present
, maskse
->expr
);
4836 return maskse
->expr
;
4839 /* Inline implementation of the sum and product intrinsics. */
4841 gfc_conv_intrinsic_arith (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
,
4845 tree scale
= NULL_TREE
;
4850 gfc_loopinfo loop
, *ploop
;
4851 gfc_actual_arglist
*arg_array
, *arg_mask
;
4852 gfc_ss
*arrayss
= NULL
;
4853 gfc_ss
*maskss
= NULL
;
4857 gfc_expr
*arrayexpr
;
4863 gcc_assert (gfc_inline_intrinsic_function_p (expr
));
4869 type
= gfc_typenode_for_spec (&expr
->ts
);
4870 /* Initialize the result. */
4871 resvar
= gfc_create_var (type
, "val");
4876 scale
= gfc_create_var (type
, "scale");
4877 gfc_add_modify (&se
->pre
, scale
,
4878 gfc_build_const (type
, integer_one_node
));
4879 tmp
= gfc_build_const (type
, integer_zero_node
);
4881 else if (op
== PLUS_EXPR
|| op
== BIT_IOR_EXPR
|| op
== BIT_XOR_EXPR
)
4882 tmp
= gfc_build_const (type
, integer_zero_node
);
4883 else if (op
== NE_EXPR
)
4885 tmp
= convert (type
, boolean_false_node
);
4886 else if (op
== BIT_AND_EXPR
)
4887 tmp
= gfc_build_const (type
, fold_build1_loc (input_location
, NEGATE_EXPR
,
4888 type
, integer_one_node
));
4890 tmp
= gfc_build_const (type
, integer_one_node
);
4892 gfc_add_modify (&se
->pre
, resvar
, tmp
);
4894 arg_array
= expr
->value
.function
.actual
;
4896 arrayexpr
= arg_array
->expr
;
4898 if (op
== NE_EXPR
|| norm2
)
4900 /* PARITY and NORM2. */
4902 optional_mask
= false;
4906 arg_mask
= arg_array
->next
->next
;
4907 gcc_assert (arg_mask
!= NULL
);
4908 maskexpr
= arg_mask
->expr
;
4909 optional_mask
= maskexpr
&& maskexpr
->expr_type
== EXPR_VARIABLE
4910 && maskexpr
->symtree
->n
.sym
->attr
.dummy
4911 && maskexpr
->symtree
->n
.sym
->attr
.optional
;
4914 if (expr
->rank
== 0)
4916 /* Walk the arguments. */
4917 arrayss
= gfc_walk_expr (arrayexpr
);
4918 gcc_assert (arrayss
!= gfc_ss_terminator
);
4920 if (maskexpr
&& maskexpr
->rank
> 0)
4922 maskss
= gfc_walk_expr (maskexpr
);
4923 gcc_assert (maskss
!= gfc_ss_terminator
);
4928 /* Initialize the scalarizer. */
4929 gfc_init_loopinfo (&loop
);
4931 /* We add the mask first because the number of iterations is
4932 taken from the last ss, and this breaks if an absent
4933 optional argument is used for mask. */
4935 if (maskexpr
&& maskexpr
->rank
> 0)
4936 gfc_add_ss_to_loop (&loop
, maskss
);
4937 gfc_add_ss_to_loop (&loop
, arrayss
);
4939 /* Initialize the loop. */
4940 gfc_conv_ss_startstride (&loop
);
4941 gfc_conv_loop_setup (&loop
, &expr
->where
);
4943 if (maskexpr
&& maskexpr
->rank
> 0)
4944 gfc_mark_ss_chain_used (maskss
, 1);
4945 gfc_mark_ss_chain_used (arrayss
, 1);
4950 /* All the work has been done in the parent loops. */
4951 ploop
= enter_nested_loop (se
);
4955 /* Generate the loop body. */
4956 gfc_start_scalarized_body (ploop
, &body
);
4958 /* If we have a mask, only add this element if the mask is set. */
4959 if (maskexpr
&& maskexpr
->rank
> 0)
4961 gfc_init_se (&maskse
, parent_se
);
4962 gfc_copy_loopinfo_to_se (&maskse
, ploop
);
4963 if (expr
->rank
== 0)
4965 gfc_conv_expr_val (&maskse
, maskexpr
);
4966 gfc_add_block_to_block (&body
, &maskse
.pre
);
4968 gfc_start_block (&block
);
4971 gfc_init_block (&block
);
4973 /* Do the actual summation/product. */
4974 gfc_init_se (&arrayse
, parent_se
);
4975 gfc_copy_loopinfo_to_se (&arrayse
, ploop
);
4976 if (expr
->rank
== 0)
4977 arrayse
.ss
= arrayss
;
4978 gfc_conv_expr_val (&arrayse
, arrayexpr
);
4979 gfc_add_block_to_block (&block
, &arrayse
.pre
);
4983 /* if (x (i) != 0.0)
4989 result = 1.0 + result * val * val;
4995 result += val * val;
4998 tree res1
, res2
, cond
, absX
, val
;
4999 stmtblock_t ifblock1
, ifblock2
, ifblock3
;
5001 gfc_init_block (&ifblock1
);
5003 absX
= gfc_create_var (type
, "absX");
5004 gfc_add_modify (&ifblock1
, absX
,
5005 fold_build1_loc (input_location
, ABS_EXPR
, type
,
5007 val
= gfc_create_var (type
, "val");
5008 gfc_add_expr_to_block (&ifblock1
, val
);
5010 gfc_init_block (&ifblock2
);
5011 gfc_add_modify (&ifblock2
, val
,
5012 fold_build2_loc (input_location
, RDIV_EXPR
, type
, scale
,
5014 res1
= fold_build2_loc (input_location
, MULT_EXPR
, type
, val
, val
);
5015 res1
= fold_build2_loc (input_location
, MULT_EXPR
, type
, resvar
, res1
);
5016 res1
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, res1
,
5017 gfc_build_const (type
, integer_one_node
));
5018 gfc_add_modify (&ifblock2
, resvar
, res1
);
5019 gfc_add_modify (&ifblock2
, scale
, absX
);
5020 res1
= gfc_finish_block (&ifblock2
);
5022 gfc_init_block (&ifblock3
);
5023 gfc_add_modify (&ifblock3
, val
,
5024 fold_build2_loc (input_location
, RDIV_EXPR
, type
, absX
,
5026 res2
= fold_build2_loc (input_location
, MULT_EXPR
, type
, val
, val
);
5027 res2
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, resvar
, res2
);
5028 gfc_add_modify (&ifblock3
, resvar
, res2
);
5029 res2
= gfc_finish_block (&ifblock3
);
5031 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
5033 tmp
= build3_v (COND_EXPR
, cond
, res1
, res2
);
5034 gfc_add_expr_to_block (&ifblock1
, tmp
);
5035 tmp
= gfc_finish_block (&ifblock1
);
5037 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
5039 gfc_build_const (type
, integer_zero_node
));
5041 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
5042 gfc_add_expr_to_block (&block
, tmp
);
5046 tmp
= fold_build2_loc (input_location
, op
, type
, resvar
, arrayse
.expr
);
5047 gfc_add_modify (&block
, resvar
, tmp
);
5050 gfc_add_block_to_block (&block
, &arrayse
.post
);
5052 if (maskexpr
&& maskexpr
->rank
> 0)
5054 /* We enclose the above in if (mask) {...} . If the mask is an
5055 optional argument, generate
5056 IF (.NOT. PRESENT(MASK) .OR. MASK(I)). */
5058 tmp
= gfc_finish_block (&block
);
5059 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
5060 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
5061 build_empty_stmt (input_location
));
5064 tmp
= gfc_finish_block (&block
);
5065 gfc_add_expr_to_block (&body
, tmp
);
5067 gfc_trans_scalarizing_loops (ploop
, &body
);
5069 /* For a scalar mask, enclose the loop in an if statement. */
5070 if (maskexpr
&& maskexpr
->rank
== 0)
5072 gfc_init_block (&block
);
5073 gfc_add_block_to_block (&block
, &ploop
->pre
);
5074 gfc_add_block_to_block (&block
, &ploop
->post
);
5075 tmp
= gfc_finish_block (&block
);
5079 tmp
= build3_v (COND_EXPR
, se
->ss
->info
->data
.scalar
.value
, tmp
,
5080 build_empty_stmt (input_location
));
5081 gfc_advance_se_ss_chain (se
);
5087 gcc_assert (expr
->rank
== 0);
5088 gfc_init_se (&maskse
, NULL
);
5089 gfc_conv_expr_val (&maskse
, maskexpr
);
5090 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
5091 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
5092 build_empty_stmt (input_location
));
5095 gfc_add_expr_to_block (&block
, tmp
);
5096 gfc_add_block_to_block (&se
->pre
, &block
);
5097 gcc_assert (se
->post
.head
== NULL
);
5101 gfc_add_block_to_block (&se
->pre
, &ploop
->pre
);
5102 gfc_add_block_to_block (&se
->pre
, &ploop
->post
);
5105 if (expr
->rank
== 0)
5106 gfc_cleanup_loop (ploop
);
5110 /* result = scale * sqrt(result). */
5112 sqrt
= gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT
, expr
->ts
.kind
);
5113 resvar
= build_call_expr_loc (input_location
,
5115 resvar
= fold_build2_loc (input_location
, MULT_EXPR
, type
, scale
, resvar
);
5122 /* Inline implementation of the dot_product intrinsic. This function
5123 is based on gfc_conv_intrinsic_arith (the previous function). */
5125 gfc_conv_intrinsic_dot_product (gfc_se
* se
, gfc_expr
* expr
)
5133 gfc_actual_arglist
*actual
;
5134 gfc_ss
*arrayss1
, *arrayss2
;
5135 gfc_se arrayse1
, arrayse2
;
5136 gfc_expr
*arrayexpr1
, *arrayexpr2
;
5138 type
= gfc_typenode_for_spec (&expr
->ts
);
5140 /* Initialize the result. */
5141 resvar
= gfc_create_var (type
, "val");
5142 if (expr
->ts
.type
== BT_LOGICAL
)
5143 tmp
= build_int_cst (type
, 0);
5145 tmp
= gfc_build_const (type
, integer_zero_node
);
5147 gfc_add_modify (&se
->pre
, resvar
, tmp
);
5149 /* Walk argument #1. */
5150 actual
= expr
->value
.function
.actual
;
5151 arrayexpr1
= actual
->expr
;
5152 arrayss1
= gfc_walk_expr (arrayexpr1
);
5153 gcc_assert (arrayss1
!= gfc_ss_terminator
);
5155 /* Walk argument #2. */
5156 actual
= actual
->next
;
5157 arrayexpr2
= actual
->expr
;
5158 arrayss2
= gfc_walk_expr (arrayexpr2
);
5159 gcc_assert (arrayss2
!= gfc_ss_terminator
);
5161 /* Initialize the scalarizer. */
5162 gfc_init_loopinfo (&loop
);
5163 gfc_add_ss_to_loop (&loop
, arrayss1
);
5164 gfc_add_ss_to_loop (&loop
, arrayss2
);
5166 /* Initialize the loop. */
5167 gfc_conv_ss_startstride (&loop
);
5168 gfc_conv_loop_setup (&loop
, &expr
->where
);
5170 gfc_mark_ss_chain_used (arrayss1
, 1);
5171 gfc_mark_ss_chain_used (arrayss2
, 1);
5173 /* Generate the loop body. */
5174 gfc_start_scalarized_body (&loop
, &body
);
5175 gfc_init_block (&block
);
5177 /* Make the tree expression for [conjg(]array1[)]. */
5178 gfc_init_se (&arrayse1
, NULL
);
5179 gfc_copy_loopinfo_to_se (&arrayse1
, &loop
);
5180 arrayse1
.ss
= arrayss1
;
5181 gfc_conv_expr_val (&arrayse1
, arrayexpr1
);
5182 if (expr
->ts
.type
== BT_COMPLEX
)
5183 arrayse1
.expr
= fold_build1_loc (input_location
, CONJ_EXPR
, type
,
5185 gfc_add_block_to_block (&block
, &arrayse1
.pre
);
5187 /* Make the tree expression for array2. */
5188 gfc_init_se (&arrayse2
, NULL
);
5189 gfc_copy_loopinfo_to_se (&arrayse2
, &loop
);
5190 arrayse2
.ss
= arrayss2
;
5191 gfc_conv_expr_val (&arrayse2
, arrayexpr2
);
5192 gfc_add_block_to_block (&block
, &arrayse2
.pre
);
5194 /* Do the actual product and sum. */
5195 if (expr
->ts
.type
== BT_LOGICAL
)
5197 tmp
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
, type
,
5198 arrayse1
.expr
, arrayse2
.expr
);
5199 tmp
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
, type
, resvar
, tmp
);
5203 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, type
, arrayse1
.expr
,
5205 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, resvar
, tmp
);
5207 gfc_add_modify (&block
, resvar
, tmp
);
5209 /* Finish up the loop block and the loop. */
5210 tmp
= gfc_finish_block (&block
);
5211 gfc_add_expr_to_block (&body
, tmp
);
5213 gfc_trans_scalarizing_loops (&loop
, &body
);
5214 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
5215 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
5216 gfc_cleanup_loop (&loop
);
5222 /* Tells whether the expression E is a reference to an optional variable whose
5223 presence is not known at compile time. Those are variable references without
5224 subreference; if there is a subreference, we can assume the variable is
5225 present. We have to special case full arrays, which we represent with a fake
5226 "full" reference, and class descriptors for which a reference to data is not
5227 really a subreference. */
5230 maybe_absent_optional_variable (gfc_expr
*e
)
5232 if (!(e
&& e
->expr_type
== EXPR_VARIABLE
))
5235 gfc_symbol
*sym
= e
->symtree
->n
.sym
;
5236 if (!sym
->attr
.optional
)
5239 gfc_ref
*ref
= e
->ref
;
5243 if (ref
->type
== REF_ARRAY
5244 && ref
->u
.ar
.type
== AR_FULL
5245 && ref
->next
== nullptr)
5248 if (!(sym
->ts
.type
== BT_CLASS
5249 && ref
->type
== REF_COMPONENT
5250 && ref
->u
.c
.component
== CLASS_DATA (sym
)))
5253 gfc_ref
*next_ref
= ref
->next
;
5254 if (next_ref
== nullptr)
5257 if (next_ref
->type
== REF_ARRAY
5258 && next_ref
->u
.ar
.type
== AR_FULL
5259 && next_ref
->next
== nullptr)
5266 /* Remove unneeded kind= argument from actual argument list when the
5267 result conversion is dealt with in a different place. */
5270 strip_kind_from_actual (gfc_actual_arglist
* actual
)
5272 for (gfc_actual_arglist
*a
= actual
; a
; a
= a
->next
)
5274 if (a
&& a
->name
&& strcmp (a
->name
, "kind") == 0)
5276 gfc_free_expr (a
->expr
);
5282 /* Emit code for minloc or maxloc intrinsic. There are many different cases
5283 we need to handle. For performance reasons we sometimes create two
5284 loops instead of one, where the second one is much simpler.
5285 Examples for minloc intrinsic:
5286 A: Result is scalar.
5287 1) Array mask is used and NaNs need to be supported:
5293 if (pos == 0) pos = S + (1 - from);
5294 if (a[S] <= limit) {
5296 pos = S + (1 - from);
5308 pos = S + (1 - from);
5313 2) NaNs need to be supported, but it is known at compile time or cheaply
5314 at runtime whether array is nonempty or not:
5319 if (a[S] <= limit) {
5321 pos = S + (1 - from);
5326 if (from <= to) pos = 1;
5332 pos = S + (1 - from);
5337 3) NaNs aren't supported, array mask is used:
5338 limit = infinities_supported ? Infinity : huge (limit);
5344 pos = S + (1 - from);
5355 pos = S + (1 - from);
5360 4) Same without array mask:
5361 limit = infinities_supported ? Infinity : huge (limit);
5362 pos = (from <= to) ? 1 : 0;
5367 pos = S + (1 - from);
5371 B: Array result, non-CHARACTER type, DIM absent
5372 Generate similar code as in the scalar case, using a collection of
5373 variables (one per dimension) instead of a single variable as result.
5374 Picking only cases 1) and 4) with ARRAY of rank 2, the generated code
5376 1) Array mask is used and NaNs need to be supported:
5381 second_loop_entry = false;
5387 pos0 = S0 + (1 - from0);
5388 pos1 = S1 + (1 - from1);
5390 if (a[S1][S0] <= limit) {
5392 pos0 = S0 + (1 - from0);
5393 pos1 = S1 + (1 - from1);
5394 second_loop_entry = true;
5404 S1 = second_loop_entry ? S1 : from1;
5406 S0 = second_loop_entry ? S0 : from0;
5409 if (a[S1][S0] < limit) {
5411 pos0 = S + (1 - from0);
5412 pos1 = S + (1 - from1);
5414 second_loop_entry = false;
5420 result = { pos0, pos1 };
5422 4) NANs aren't supported, no array mask.
5423 limit = infinities_supported ? Infinity : huge (limit);
5424 pos0 = (from0 <= to0 && from1 <= to1) ? 1 : 0;
5425 pos1 = (from0 <= to0 && from1 <= to1) ? 1 : 0;
5430 if (a[S1][S0] < limit) {
5432 pos0 = S + (1 - from0);
5433 pos1 = S + (1 - from1);
5439 result = { pos0, pos1 };
5440 C: Otherwise, a call is generated.
5441 For 2) and 4), if mask is scalar, this all goes into a conditional,
5442 setting pos = 0; in the else branch.
5444 Since we now also support the BACK argument, instead of using
5445 if (a[S] < limit), we now use
5448 cond = a[S] <= limit;
5450 cond = a[S] < limit;
5454 The optimizer is smart enough to move the condition out of the loop.
5455 They are now marked as unlikely too for further speedup. */
5458 gfc_conv_intrinsic_minmaxloc (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
5462 stmtblock_t ifblock
;
5463 stmtblock_t elseblock
;
5470 tree offset
[GFC_MAX_DIMENSIONS
];
5476 gfc_actual_arglist
*actual
;
5481 gfc_expr
*arrayexpr
;
5485 tree pos
[GFC_MAX_DIMENSIONS
];
5486 tree idx
[GFC_MAX_DIMENSIONS
];
5487 tree result_var
= NULL_TREE
;
5491 actual
= expr
->value
.function
.actual
;
5493 /* The last argument, BACK, is passed by value. Ensure that
5494 by setting its name to %VAL. */
5495 for (gfc_actual_arglist
*a
= actual
; a
; a
= a
->next
)
5497 if (a
->next
== NULL
)
5503 if (se
->ss
->info
->useflags
)
5505 /* The inline implementation of MINLOC/MAXLOC has been generated
5506 before, out of the scalarization loop; now we can just use the
5508 gfc_conv_tmp_array_ref (se
);
5511 else if (!gfc_inline_intrinsic_function_p (expr
))
5513 gfc_conv_intrinsic_funcall (se
, expr
);
5518 arrayexpr
= actual
->expr
;
5520 /* Special case for character maxloc. Remove unneeded actual
5521 arguments, then call a library function. */
5523 if (arrayexpr
->ts
.type
== BT_CHARACTER
)
5525 gfc_actual_arglist
*a
;
5527 strip_kind_from_actual (a
);
5530 if (a
->name
&& strcmp (a
->name
, "dim") == 0)
5532 gfc_free_expr (a
->expr
);
5537 gfc_conv_intrinsic_funcall (se
, expr
);
5541 type
= gfc_typenode_for_spec (&expr
->ts
);
5546 memset (&as
, 0, sizeof (as
));
5549 as
.lower
[0] = gfc_get_int_expr (gfc_index_integer_kind
,
5552 as
.upper
[0] = gfc_get_int_expr (gfc_index_integer_kind
,
5556 tree array
= gfc_get_nodesc_array_type (type
, &as
, PACKED_STATIC
, true);
5558 result_var
= gfc_create_var (array
, "loc_result");
5561 /* Initialize the result. */
5562 for (int i
= 0; i
< arrayexpr
->rank
; i
++)
5564 pos
[i
] = gfc_create_var (gfc_array_index_type
,
5565 gfc_get_string ("pos%d", i
));
5566 offset
[i
] = gfc_create_var (gfc_array_index_type
,
5567 gfc_get_string ("offset%d", i
));
5568 idx
[i
] = gfc_create_var (gfc_array_index_type
,
5569 gfc_get_string ("idx%d", i
));
5572 /* Walk the arguments. */
5573 arrayss
= gfc_walk_expr (arrayexpr
);
5574 gcc_assert (arrayss
!= gfc_ss_terminator
);
5576 actual
= actual
->next
->next
;
5577 gcc_assert (actual
);
5578 maskexpr
= actual
->expr
;
5579 optional_mask
= maskexpr
&& maskexpr
->expr_type
== EXPR_VARIABLE
5580 && maskexpr
->symtree
->n
.sym
->attr
.dummy
5581 && maskexpr
->symtree
->n
.sym
->attr
.optional
;
5582 backexpr
= actual
->next
->next
->expr
;
5584 gfc_init_se (&backse
, NULL
);
5585 if (backexpr
== nullptr)
5586 back
= logical_false_node
;
5587 else if (maybe_absent_optional_variable (backexpr
))
5589 /* This should have been checked already by
5590 maybe_absent_optional_variable. */
5591 gcc_checking_assert (backexpr
->expr_type
== EXPR_VARIABLE
);
5593 gfc_conv_expr (&backse
, backexpr
);
5594 tree present
= gfc_conv_expr_present (backexpr
->symtree
->n
.sym
, false);
5595 back
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
5596 logical_type_node
, present
, backse
.expr
);
5600 gfc_conv_expr (&backse
, backexpr
);
5603 gfc_add_block_to_block (&se
->pre
, &backse
.pre
);
5604 back
= gfc_evaluate_now_loc (input_location
, back
, &se
->pre
);
5605 gfc_add_block_to_block (&se
->pre
, &backse
.post
);
5608 if (maskexpr
&& maskexpr
->rank
!= 0)
5610 maskss
= gfc_walk_expr (maskexpr
);
5611 gcc_assert (maskss
!= gfc_ss_terminator
);
5616 if (gfc_array_size (arrayexpr
, &asize
))
5618 nonempty
= gfc_conv_mpz_to_tree (asize
, gfc_index_integer_kind
);
5620 nonempty
= fold_build2_loc (input_location
, GT_EXPR
,
5621 logical_type_node
, nonempty
,
5622 gfc_index_zero_node
);
5627 limit
= gfc_create_var (gfc_typenode_for_spec (&arrayexpr
->ts
), "limit");
5628 switch (arrayexpr
->ts
.type
)
5631 tmp
= gfc_build_inf_or_huge (TREE_TYPE (limit
), arrayexpr
->ts
.kind
);
5635 n
= gfc_validate_kind (arrayexpr
->ts
.type
, arrayexpr
->ts
.kind
, false);
5636 tmp
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
,
5637 arrayexpr
->ts
.kind
);
5641 /* For MAXVAL, the minimum is zero, for MINVAL it is HUGE(). */
5644 tmp
= gfc_get_unsigned_type (arrayexpr
->ts
.kind
);
5645 tmp
= build_int_cst (tmp
, 0);
5649 n
= gfc_validate_kind (arrayexpr
->ts
.type
, arrayexpr
->ts
.kind
, false);
5650 tmp
= gfc_conv_mpz_unsigned_to_tree (gfc_unsigned_kinds
[n
].huge
,
5659 /* We start with the most negative possible value for MAXLOC, and the most
5660 positive possible value for MINLOC. The most negative possible value is
5661 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5662 possible value is HUGE in both cases. BT_UNSIGNED has already been dealt
5664 if (op
== GT_EXPR
&& expr
->ts
.type
!= BT_UNSIGNED
)
5665 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (tmp
), tmp
);
5666 if (op
== GT_EXPR
&& arrayexpr
->ts
.type
== BT_INTEGER
)
5667 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (tmp
), tmp
,
5668 build_int_cst (TREE_TYPE (tmp
), 1));
5670 gfc_add_modify (&se
->pre
, limit
, tmp
);
5672 /* If we are in a case where we generate two sets of loops, the second one
5673 should continue where the first stopped instead of restarting from the
5674 beginning. So nested loops in the second set should have a partial range
5675 on the first iteration, but they should start from the beginning and span
5676 their full range on the following iterations. So we use conditionals in
5677 the loops lower bounds, and use the following variable in those
5678 conditionals to decide whether to use the original loop bound or to use
5679 the index at which the loop from the first set stopped. */
5680 tree second_loop_entry
= gfc_create_var (logical_type_node
,
5681 "second_loop_entry");
5682 gfc_add_modify (&se
->pre
, second_loop_entry
, logical_false_node
);
5684 /* Initialize the scalarizer. */
5685 gfc_init_loopinfo (&loop
);
5687 /* We add the mask first because the number of iterations is taken
5688 from the last ss, and this breaks if an absent optional argument
5689 is used for mask. */
5692 gfc_add_ss_to_loop (&loop
, maskss
);
5694 gfc_add_ss_to_loop (&loop
, arrayss
);
5696 /* Initialize the loop. */
5697 gfc_conv_ss_startstride (&loop
);
5699 /* The code generated can have more than one loop in sequence (see the
5700 comment at the function header). This doesn't work well with the
5701 scalarizer, which changes arrays' offset when the scalarization loops
5702 are generated (see gfc_trans_preloop_setup). Fortunately, we can use
5703 the scalarizer temporary code to handle multiple loops. Thus, we set
5704 temp_dim here, we call gfc_mark_ss_chain_used with flag=3 later, and
5705 we use gfc_trans_scalarized_loop_boundary even later to restore
5707 loop
.temp_dim
= loop
.dimen
;
5708 gfc_conv_loop_setup (&loop
, &expr
->where
);
5710 if (nonempty
== NULL
&& maskss
== NULL
)
5712 nonempty
= logical_true_node
;
5714 for (int i
= 0; i
< loop
.dimen
; i
++)
5716 if (!(loop
.from
[i
] && loop
.to
[i
]))
5722 tree tmp
= fold_build2_loc (input_location
, LE_EXPR
,
5723 logical_type_node
, loop
.from
[i
],
5726 nonempty
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
5727 logical_type_node
, nonempty
, tmp
);
5733 /* Initialize the position to zero, following Fortran 2003. We are free
5734 to do this because Fortran 95 allows the result of an entirely false
5735 mask to be processor dependent. If we know at compile time the array
5736 is non-empty and no MASK is used, we can initialize to 1 to simplify
5738 if (nonempty
!= NULL
&& !HONOR_NANS (DECL_MODE (limit
)))
5740 tree init
= fold_build3_loc (input_location
, COND_EXPR
,
5741 gfc_array_index_type
, nonempty
,
5743 gfc_index_zero_node
);
5744 for (int i
= 0; i
< loop
.dimen
; i
++)
5745 gfc_add_modify (&loop
.pre
, pos
[i
], init
);
5749 for (int i
= 0; i
< loop
.dimen
; i
++)
5750 gfc_add_modify (&loop
.pre
, pos
[i
], gfc_index_zero_node
);
5751 lab1
= gfc_build_label_decl (NULL_TREE
);
5752 TREE_USED (lab1
) = 1;
5753 lab2
= gfc_build_label_decl (NULL_TREE
);
5754 TREE_USED (lab2
) = 1;
5757 /* An offset must be added to the loop
5758 counter to obtain the required position. */
5759 for (int i
= 0; i
< loop
.dimen
; i
++)
5761 gcc_assert (loop
.from
[i
]);
5763 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
5764 gfc_index_one_node
, loop
.from
[i
]);
5765 gfc_add_modify (&loop
.pre
, offset
[i
], tmp
);
5768 gfc_mark_ss_chain_used (arrayss
, lab1
? 3 : 1);
5770 gfc_mark_ss_chain_used (maskss
, lab1
? 3 : 1);
5771 /* Generate the loop body. */
5772 gfc_start_scalarized_body (&loop
, &body
);
5774 /* If we have a mask, only check this element if the mask is set. */
5777 gfc_init_se (&maskse
, NULL
);
5778 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
5780 gfc_conv_expr_val (&maskse
, maskexpr
);
5781 gfc_add_block_to_block (&body
, &maskse
.pre
);
5783 gfc_start_block (&block
);
5786 gfc_init_block (&block
);
5788 /* Compare with the current limit. */
5789 gfc_init_se (&arrayse
, NULL
);
5790 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
5791 arrayse
.ss
= arrayss
;
5792 gfc_conv_expr_val (&arrayse
, arrayexpr
);
5793 gfc_add_block_to_block (&block
, &arrayse
.pre
);
5795 /* We do the following if this is a more extreme value. */
5796 gfc_start_block (&ifblock
);
5798 /* Assign the value to the limit... */
5799 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
5801 if (nonempty
== NULL
&& HONOR_NANS (DECL_MODE (limit
)))
5803 stmtblock_t ifblock2
;
5806 gfc_start_block (&ifblock2
);
5807 for (int i
= 0; i
< loop
.dimen
; i
++)
5809 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
[i
]),
5810 loop
.loopvar
[i
], offset
[i
]);
5811 gfc_add_modify (&ifblock2
, pos
[i
], tmp
);
5813 ifbody2
= gfc_finish_block (&ifblock2
);
5815 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
5816 pos
[0], gfc_index_zero_node
);
5817 tmp
= build3_v (COND_EXPR
, cond
, ifbody2
,
5818 build_empty_stmt (input_location
));
5819 gfc_add_expr_to_block (&block
, tmp
);
5822 for (int i
= 0; i
< loop
.dimen
; i
++)
5824 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
[i
]),
5825 loop
.loopvar
[i
], offset
[i
]);
5826 gfc_add_modify (&ifblock
, pos
[i
], tmp
);
5827 gfc_add_modify (&ifblock
, idx
[i
], loop
.loopvar
[i
]);
5830 gfc_add_modify (&ifblock
, second_loop_entry
, logical_true_node
);
5833 gfc_add_expr_to_block (&ifblock
, build1_v (GOTO_EXPR
, lab1
));
5835 ifbody
= gfc_finish_block (&ifblock
);
5837 if (!lab1
|| HONOR_NANS (DECL_MODE (limit
)))
5840 cond
= fold_build2_loc (input_location
,
5841 op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
5842 logical_type_node
, arrayse
.expr
, limit
);
5845 tree ifbody2
, elsebody2
;
5847 /* We switch to > or >= depending on the value of the BACK argument. */
5848 cond
= gfc_create_var (logical_type_node
, "cond");
5850 gfc_start_block (&ifblock
);
5851 b_if
= fold_build2_loc (input_location
, op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
5852 logical_type_node
, arrayse
.expr
, limit
);
5854 gfc_add_modify (&ifblock
, cond
, b_if
);
5855 ifbody2
= gfc_finish_block (&ifblock
);
5857 gfc_start_block (&elseblock
);
5858 b_else
= fold_build2_loc (input_location
, op
, logical_type_node
,
5859 arrayse
.expr
, limit
);
5861 gfc_add_modify (&elseblock
, cond
, b_else
);
5862 elsebody2
= gfc_finish_block (&elseblock
);
5864 tmp
= fold_build3_loc (input_location
, COND_EXPR
, logical_type_node
,
5865 back
, ifbody2
, elsebody2
);
5867 gfc_add_expr_to_block (&block
, tmp
);
5870 cond
= gfc_unlikely (cond
, PRED_BUILTIN_EXPECT
);
5871 ifbody
= build3_v (COND_EXPR
, cond
, ifbody
,
5872 build_empty_stmt (input_location
));
5874 gfc_add_expr_to_block (&block
, ifbody
);
5878 /* We enclose the above in if (mask) {...}. If the mask is an
5879 optional argument, generate IF (.NOT. PRESENT(MASK)
5883 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
5884 tmp
= gfc_finish_block (&block
);
5885 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
5886 build_empty_stmt (input_location
));
5889 tmp
= gfc_finish_block (&block
);
5890 gfc_add_expr_to_block (&body
, tmp
);
5894 for (int i
= 0; i
< loop
.dimen
; i
++)
5895 loop
.from
[i
] = fold_build3_loc (input_location
, COND_EXPR
,
5896 TREE_TYPE (loop
.from
[i
]),
5897 second_loop_entry
, idx
[i
],
5900 gfc_trans_scalarized_loop_boundary (&loop
, &body
);
5902 stmtblock_t
* const outer_block
= &loop
.code
[loop
.dimen
- 1];
5904 if (HONOR_NANS (DECL_MODE (limit
)))
5906 if (nonempty
!= NULL
)
5908 stmtblock_t init_block
;
5909 gfc_init_block (&init_block
);
5911 for (int i
= 0; i
< loop
.dimen
; i
++)
5912 gfc_add_modify (&init_block
, pos
[i
], gfc_index_one_node
);
5914 tree ifbody
= gfc_finish_block (&init_block
);
5915 tmp
= build3_v (COND_EXPR
, nonempty
, ifbody
,
5916 build_empty_stmt (input_location
));
5917 gfc_add_expr_to_block (outer_block
, tmp
);
5921 gfc_add_expr_to_block (outer_block
, build1_v (GOTO_EXPR
, lab2
));
5922 gfc_add_expr_to_block (outer_block
, build1_v (LABEL_EXPR
, lab1
));
5924 /* If we have a mask, only check this element if the mask is set. */
5927 gfc_init_se (&maskse
, NULL
);
5928 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
5930 gfc_conv_expr_val (&maskse
, maskexpr
);
5931 gfc_add_block_to_block (&body
, &maskse
.pre
);
5933 gfc_start_block (&block
);
5936 gfc_init_block (&block
);
5938 /* Compare with the current limit. */
5939 gfc_init_se (&arrayse
, NULL
);
5940 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
5941 arrayse
.ss
= arrayss
;
5942 gfc_conv_expr_val (&arrayse
, arrayexpr
);
5943 gfc_add_block_to_block (&block
, &arrayse
.pre
);
5945 /* We do the following if this is a more extreme value. */
5946 gfc_start_block (&ifblock
);
5948 /* Assign the value to the limit... */
5949 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
5951 for (int i
= 0; i
< loop
.dimen
; i
++)
5953 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
[i
]),
5954 loop
.loopvar
[i
], offset
[i
]);
5955 gfc_add_modify (&ifblock
, pos
[i
], tmp
);
5958 ifbody
= gfc_finish_block (&ifblock
);
5960 /* We switch to > or >= depending on the value of the BACK argument. */
5962 tree ifbody2
, elsebody2
;
5964 cond
= gfc_create_var (logical_type_node
, "cond");
5966 gfc_start_block (&ifblock
);
5967 b_if
= fold_build2_loc (input_location
, op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
5968 logical_type_node
, arrayse
.expr
, limit
);
5970 gfc_add_modify (&ifblock
, cond
, b_if
);
5971 ifbody2
= gfc_finish_block (&ifblock
);
5973 gfc_start_block (&elseblock
);
5974 b_else
= fold_build2_loc (input_location
, op
, logical_type_node
,
5975 arrayse
.expr
, limit
);
5977 gfc_add_modify (&elseblock
, cond
, b_else
);
5978 elsebody2
= gfc_finish_block (&elseblock
);
5980 tmp
= fold_build3_loc (input_location
, COND_EXPR
, logical_type_node
,
5981 back
, ifbody2
, elsebody2
);
5984 gfc_add_expr_to_block (&block
, tmp
);
5985 cond
= gfc_unlikely (cond
, PRED_BUILTIN_EXPECT
);
5986 tmp
= build3_v (COND_EXPR
, cond
, ifbody
,
5987 build_empty_stmt (input_location
));
5989 gfc_add_expr_to_block (&block
, tmp
);
5993 /* We enclose the above in if (mask) {...}. If the mask is
5994 an optional argument, generate IF (.NOT. PRESENT(MASK)
5998 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
5999 tmp
= gfc_finish_block (&block
);
6000 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
6001 build_empty_stmt (input_location
));
6004 tmp
= gfc_finish_block (&block
);
6006 gfc_add_expr_to_block (&body
, tmp
);
6007 gfc_add_modify (&body
, second_loop_entry
, logical_false_node
);
6010 gfc_trans_scalarizing_loops (&loop
, &body
);
6013 gfc_add_expr_to_block (&loop
.pre
, build1_v (LABEL_EXPR
, lab2
));
6015 /* For a scalar mask, enclose the loop in an if statement. */
6016 if (maskexpr
&& maskss
== NULL
)
6020 gfc_init_se (&maskse
, NULL
);
6021 gfc_conv_expr_val (&maskse
, maskexpr
);
6022 gfc_add_block_to_block (&se
->pre
, &maskse
.pre
);
6023 gfc_init_block (&block
);
6024 gfc_add_block_to_block (&block
, &loop
.pre
);
6025 gfc_add_block_to_block (&block
, &loop
.post
);
6026 tmp
= gfc_finish_block (&block
);
6028 /* For the else part of the scalar mask, just initialize
6029 the pos variable the same way as above. */
6031 gfc_init_block (&elseblock
);
6032 for (int i
= 0; i
< loop
.dimen
; i
++)
6033 gfc_add_modify (&elseblock
, pos
[i
], gfc_index_zero_node
);
6034 elsetmp
= gfc_finish_block (&elseblock
);
6035 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6036 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
, elsetmp
);
6037 gfc_add_expr_to_block (&block
, tmp
);
6038 gfc_add_block_to_block (&se
->pre
, &block
);
6042 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
6043 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
6045 gfc_cleanup_loop (&loop
);
6049 for (int i
= 0; i
< arrayexpr
->rank
; i
++)
6051 tree res_idx
= build_int_cst (gfc_array_index_type
, i
);
6052 tree res_arr_ref
= gfc_build_array_ref (result_var
, res_idx
,
6055 tree value
= convert (type
, pos
[i
]);
6056 gfc_add_modify (&se
->pre
, res_arr_ref
, value
);
6059 se
->expr
= result_var
;
6062 se
->expr
= convert (type
, pos
[0]);
6065 /* Emit code for findloc. */
6068 gfc_conv_intrinsic_findloc (gfc_se
*se
, gfc_expr
*expr
)
6070 gfc_actual_arglist
*array_arg
, *value_arg
, *dim_arg
, *mask_arg
,
6071 *kind_arg
, *back_arg
;
6072 gfc_expr
*value_expr
;
6077 stmtblock_t loopblock
;
6081 tree forward_branch
= NULL_TREE
;
6096 array_arg
= expr
->value
.function
.actual
;
6097 value_arg
= array_arg
->next
;
6098 dim_arg
= value_arg
->next
;
6099 mask_arg
= dim_arg
->next
;
6100 kind_arg
= mask_arg
->next
;
6101 back_arg
= kind_arg
->next
;
6103 /* Remove kind and set ikind. */
6106 ikind
= mpz_get_si (kind_arg
->expr
->value
.integer
);
6107 gfc_free_expr (kind_arg
->expr
);
6108 kind_arg
->expr
= NULL
;
6111 ikind
= gfc_default_integer_kind
;
6113 value_expr
= value_arg
->expr
;
6115 /* Unless it's a string, pass VALUE by value. */
6116 if (value_expr
->ts
.type
!= BT_CHARACTER
)
6117 value_arg
->name
= "%VAL";
6119 /* Pass BACK argument by value. */
6120 back_arg
->name
= "%VAL";
6122 /* Call the library if we have a character function or if
6124 if (se
->ss
|| array_arg
->expr
->ts
.type
== BT_CHARACTER
)
6126 se
->ignore_optional
= 1;
6127 if (expr
->rank
== 0)
6129 /* Remove dim argument. */
6130 gfc_free_expr (dim_arg
->expr
);
6131 dim_arg
->expr
= NULL
;
6133 gfc_conv_intrinsic_funcall (se
, expr
);
6137 type
= gfc_get_int_type (ikind
);
6139 /* Initialize the result. */
6140 resvar
= gfc_create_var (gfc_array_index_type
, "pos");
6141 gfc_add_modify (&se
->pre
, resvar
, build_int_cst (gfc_array_index_type
, 0));
6142 offset
= gfc_create_var (gfc_array_index_type
, "offset");
6144 maskexpr
= mask_arg
->expr
;
6145 optional_mask
= maskexpr
&& maskexpr
->expr_type
== EXPR_VARIABLE
6146 && maskexpr
->symtree
->n
.sym
->attr
.dummy
6147 && maskexpr
->symtree
->n
.sym
->attr
.optional
;
6149 /* Generate two loops, one for BACK=.true. and one for BACK=.false. */
6151 for (i
= 0 ; i
< 2; i
++)
6153 /* Walk the arguments. */
6154 arrayss
= gfc_walk_expr (array_arg
->expr
);
6155 gcc_assert (arrayss
!= gfc_ss_terminator
);
6157 if (maskexpr
&& maskexpr
->rank
!= 0)
6159 maskss
= gfc_walk_expr (maskexpr
);
6160 gcc_assert (maskss
!= gfc_ss_terminator
);
6165 /* Initialize the scalarizer. */
6166 gfc_init_loopinfo (&loop
);
6167 exit_label
= gfc_build_label_decl (NULL_TREE
);
6168 TREE_USED (exit_label
) = 1;
6170 /* We add the mask first because the number of iterations is
6171 taken from the last ss, and this breaks if an absent
6172 optional argument is used for mask. */
6175 gfc_add_ss_to_loop (&loop
, maskss
);
6176 gfc_add_ss_to_loop (&loop
, arrayss
);
6178 /* Initialize the loop. */
6179 gfc_conv_ss_startstride (&loop
);
6180 gfc_conv_loop_setup (&loop
, &expr
->where
);
6182 /* Calculate the offset. */
6183 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
6184 gfc_index_one_node
, loop
.from
[0]);
6185 gfc_add_modify (&loop
.pre
, offset
, tmp
);
6187 gfc_mark_ss_chain_used (arrayss
, 1);
6189 gfc_mark_ss_chain_used (maskss
, 1);
6191 /* The first loop is for BACK=.true. */
6193 loop
.reverse
[0] = GFC_REVERSE_SET
;
6195 /* Generate the loop body. */
6196 gfc_start_scalarized_body (&loop
, &body
);
6198 /* If we have an array mask, only add the element if it is
6202 gfc_init_se (&maskse
, NULL
);
6203 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
6205 gfc_conv_expr_val (&maskse
, maskexpr
);
6206 gfc_add_block_to_block (&body
, &maskse
.pre
);
6209 /* If the condition matches then set the return value. */
6210 gfc_start_block (&block
);
6212 /* Add the offset. */
6213 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
6215 loop
.loopvar
[0], offset
);
6216 gfc_add_modify (&block
, resvar
, tmp
);
6217 /* And break out of the loop. */
6218 tmp
= build1_v (GOTO_EXPR
, exit_label
);
6219 gfc_add_expr_to_block (&block
, tmp
);
6221 found
= gfc_finish_block (&block
);
6223 /* Check this element. */
6224 gfc_init_se (&arrayse
, NULL
);
6225 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
6226 arrayse
.ss
= arrayss
;
6227 gfc_conv_expr_val (&arrayse
, array_arg
->expr
);
6228 gfc_add_block_to_block (&body
, &arrayse
.pre
);
6230 gfc_init_se (&valuese
, NULL
);
6231 gfc_conv_expr_val (&valuese
, value_arg
->expr
);
6232 gfc_add_block_to_block (&body
, &valuese
.pre
);
6234 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
6235 arrayse
.expr
, valuese
.expr
);
6237 tmp
= build3_v (COND_EXPR
, tmp
, found
, build_empty_stmt (input_location
));
6240 /* We enclose the above in if (mask) {...}. If the mask is
6241 an optional argument, generate IF (.NOT. PRESENT(MASK)
6245 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6246 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
6247 build_empty_stmt (input_location
));
6250 gfc_add_expr_to_block (&body
, tmp
);
6251 gfc_add_block_to_block (&body
, &arrayse
.post
);
6253 gfc_trans_scalarizing_loops (&loop
, &body
);
6255 /* Add the exit label. */
6256 tmp
= build1_v (LABEL_EXPR
, exit_label
);
6257 gfc_add_expr_to_block (&loop
.pre
, tmp
);
6258 gfc_start_block (&loopblock
);
6259 gfc_add_block_to_block (&loopblock
, &loop
.pre
);
6260 gfc_add_block_to_block (&loopblock
, &loop
.post
);
6262 forward_branch
= gfc_finish_block (&loopblock
);
6264 back_branch
= gfc_finish_block (&loopblock
);
6266 gfc_cleanup_loop (&loop
);
6269 /* Enclose the two loops in an IF statement. */
6271 gfc_init_se (&backse
, NULL
);
6272 gfc_conv_expr_val (&backse
, back_arg
->expr
);
6273 gfc_add_block_to_block (&se
->pre
, &backse
.pre
);
6274 tmp
= build3_v (COND_EXPR
, backse
.expr
, forward_branch
, back_branch
);
6276 /* For a scalar mask, enclose the loop in an if statement. */
6277 if (maskexpr
&& maskss
== NULL
)
6282 gfc_init_se (&maskse
, NULL
);
6283 gfc_conv_expr_val (&maskse
, maskexpr
);
6284 gfc_init_block (&block
);
6285 gfc_add_expr_to_block (&block
, maskse
.expr
);
6286 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6287 if_stmt
= build3_v (COND_EXPR
, ifmask
, tmp
,
6288 build_empty_stmt (input_location
));
6289 gfc_add_expr_to_block (&block
, if_stmt
);
6290 tmp
= gfc_finish_block (&block
);
6293 gfc_add_expr_to_block (&se
->pre
, tmp
);
6294 se
->expr
= convert (type
, resvar
);
6298 /* Emit code for minval or maxval intrinsic. There are many different cases
6299 we need to handle. For performance reasons we sometimes create two
6300 loops instead of one, where the second one is much simpler.
6301 Examples for minval intrinsic:
6302 1) Result is an array, a call is generated
6303 2) Array mask is used and NaNs need to be supported, rank 1:
6308 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
6311 limit = nonempty ? NaN : huge (limit);
6313 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
6314 3) NaNs need to be supported, but it is known at compile time or cheaply
6315 at runtime whether array is nonempty or not, rank 1:
6318 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
6319 limit = (from <= to) ? NaN : huge (limit);
6321 while (S <= to) { limit = min (a[S], limit); S++; }
6322 4) Array mask is used and NaNs need to be supported, rank > 1:
6331 if (fast) limit = min (a[S1][S2], limit);
6334 if (a[S1][S2] <= limit) {
6345 limit = nonempty ? NaN : huge (limit);
6346 5) NaNs need to be supported, but it is known at compile time or cheaply
6347 at runtime whether array is nonempty or not, rank > 1:
6354 if (fast) limit = min (a[S1][S2], limit);
6356 if (a[S1][S2] <= limit) {
6366 limit = (nonempty_array) ? NaN : huge (limit);
6367 6) NaNs aren't supported, but infinities are. Array mask is used:
6372 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
6375 limit = nonempty ? limit : huge (limit);
6376 7) Same without array mask:
6379 while (S <= to) { limit = min (a[S], limit); S++; }
6380 limit = (from <= to) ? limit : huge (limit);
6381 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
6382 limit = huge (limit);
6384 while (S <= to) { limit = min (a[S], limit); S++); }
6386 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
6387 with array mask instead).
6388 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
6389 setting limit = huge (limit); in the else branch. */
6392 gfc_conv_intrinsic_minmaxval (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
6402 tree huge_cst
= NULL
, nan_cst
= NULL
;
6404 stmtblock_t block
, block2
;
6406 gfc_actual_arglist
*actual
;
6411 gfc_expr
*arrayexpr
;
6418 gfc_conv_intrinsic_funcall (se
, expr
);
6422 actual
= expr
->value
.function
.actual
;
6423 arrayexpr
= actual
->expr
;
6425 if (arrayexpr
->ts
.type
== BT_CHARACTER
)
6427 gfc_actual_arglist
*dim
= actual
->next
;
6428 if (expr
->rank
== 0 && dim
->expr
!= 0)
6430 gfc_free_expr (dim
->expr
);
6433 gfc_conv_intrinsic_funcall (se
, expr
);
6437 type
= gfc_typenode_for_spec (&expr
->ts
);
6438 /* Initialize the result. */
6439 limit
= gfc_create_var (type
, "limit");
6440 n
= gfc_validate_kind (expr
->ts
.type
, expr
->ts
.kind
, false);
6441 switch (expr
->ts
.type
)
6444 huge_cst
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[n
].huge
,
6446 if (HONOR_INFINITIES (DECL_MODE (limit
)))
6448 REAL_VALUE_TYPE real
;
6450 tmp
= build_real (type
, real
);
6454 if (HONOR_NANS (DECL_MODE (limit
)))
6455 nan_cst
= gfc_build_nan (type
, "");
6459 tmp
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
, expr
->ts
.kind
);
6463 /* For MAXVAL, the minimum is zero, for MINVAL it is HUGE(). */
6465 tmp
= build_int_cst (type
, 0);
6467 tmp
= gfc_conv_mpz_unsigned_to_tree (gfc_unsigned_kinds
[n
].huge
,
6475 /* We start with the most negative possible value for MAXVAL, and the most
6476 positive possible value for MINVAL. The most negative possible value is
6477 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
6478 possible value is HUGE in both cases. BT_UNSIGNED has already been dealt
6480 if (op
== GT_EXPR
&& expr
->ts
.type
!= BT_UNSIGNED
)
6482 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (tmp
), tmp
);
6484 huge_cst
= fold_build1_loc (input_location
, NEGATE_EXPR
,
6485 TREE_TYPE (huge_cst
), huge_cst
);
6488 if (op
== GT_EXPR
&& expr
->ts
.type
== BT_INTEGER
)
6489 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (tmp
),
6490 tmp
, build_int_cst (type
, 1));
6492 gfc_add_modify (&se
->pre
, limit
, tmp
);
6494 /* Walk the arguments. */
6495 arrayss
= gfc_walk_expr (arrayexpr
);
6496 gcc_assert (arrayss
!= gfc_ss_terminator
);
6498 actual
= actual
->next
->next
;
6499 gcc_assert (actual
);
6500 maskexpr
= actual
->expr
;
6501 optional_mask
= maskexpr
&& maskexpr
->expr_type
== EXPR_VARIABLE
6502 && maskexpr
->symtree
->n
.sym
->attr
.dummy
6503 && maskexpr
->symtree
->n
.sym
->attr
.optional
;
6505 if (maskexpr
&& maskexpr
->rank
!= 0)
6507 maskss
= gfc_walk_expr (maskexpr
);
6508 gcc_assert (maskss
!= gfc_ss_terminator
);
6513 if (gfc_array_size (arrayexpr
, &asize
))
6515 nonempty
= gfc_conv_mpz_to_tree (asize
, gfc_index_integer_kind
);
6517 nonempty
= fold_build2_loc (input_location
, GT_EXPR
,
6518 logical_type_node
, nonempty
,
6519 gfc_index_zero_node
);
6524 /* Initialize the scalarizer. */
6525 gfc_init_loopinfo (&loop
);
6527 /* We add the mask first because the number of iterations is taken
6528 from the last ss, and this breaks if an absent optional argument
6529 is used for mask. */
6532 gfc_add_ss_to_loop (&loop
, maskss
);
6533 gfc_add_ss_to_loop (&loop
, arrayss
);
6535 /* Initialize the loop. */
6536 gfc_conv_ss_startstride (&loop
);
6538 /* The code generated can have more than one loop in sequence (see the
6539 comment at the function header). This doesn't work well with the
6540 scalarizer, which changes arrays' offset when the scalarization loops
6541 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
6542 are currently inlined in the scalar case only. As there is no dependency
6543 to care about in that case, there is no temporary, so that we can use the
6544 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
6545 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
6546 gfc_trans_scalarized_loop_boundary even later to restore offset.
6547 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
6548 should eventually go away. We could either create two loops properly,
6549 or find another way to save/restore the array offsets between the two
6550 loops (without conflicting with temporary management), or use a single
6551 loop minmaxval implementation. See PR 31067. */
6552 loop
.temp_dim
= loop
.dimen
;
6553 gfc_conv_loop_setup (&loop
, &expr
->where
);
6555 if (nonempty
== NULL
&& maskss
== NULL
6556 && loop
.dimen
== 1 && loop
.from
[0] && loop
.to
[0])
6557 nonempty
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
,
6558 loop
.from
[0], loop
.to
[0]);
6559 nonempty_var
= NULL
;
6560 if (nonempty
== NULL
6561 && (HONOR_INFINITIES (DECL_MODE (limit
))
6562 || HONOR_NANS (DECL_MODE (limit
))))
6564 nonempty_var
= gfc_create_var (logical_type_node
, "nonempty");
6565 gfc_add_modify (&se
->pre
, nonempty_var
, logical_false_node
);
6566 nonempty
= nonempty_var
;
6570 if (HONOR_NANS (DECL_MODE (limit
)))
6572 if (loop
.dimen
== 1)
6574 lab
= gfc_build_label_decl (NULL_TREE
);
6575 TREE_USED (lab
) = 1;
6579 fast
= gfc_create_var (logical_type_node
, "fast");
6580 gfc_add_modify (&se
->pre
, fast
, logical_false_node
);
6584 gfc_mark_ss_chain_used (arrayss
, lab
? 3 : 1);
6586 gfc_mark_ss_chain_used (maskss
, lab
? 3 : 1);
6587 /* Generate the loop body. */
6588 gfc_start_scalarized_body (&loop
, &body
);
6590 /* If we have a mask, only add this element if the mask is set. */
6593 gfc_init_se (&maskse
, NULL
);
6594 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
6596 gfc_conv_expr_val (&maskse
, maskexpr
);
6597 gfc_add_block_to_block (&body
, &maskse
.pre
);
6599 gfc_start_block (&block
);
6602 gfc_init_block (&block
);
6604 /* Compare with the current limit. */
6605 gfc_init_se (&arrayse
, NULL
);
6606 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
6607 arrayse
.ss
= arrayss
;
6608 gfc_conv_expr_val (&arrayse
, arrayexpr
);
6609 gfc_add_block_to_block (&block
, &arrayse
.pre
);
6611 gfc_init_block (&block2
);
6614 gfc_add_modify (&block2
, nonempty_var
, logical_true_node
);
6616 if (HONOR_NANS (DECL_MODE (limit
)))
6618 tmp
= fold_build2_loc (input_location
, op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
6619 logical_type_node
, arrayse
.expr
, limit
);
6621 ifbody
= build1_v (GOTO_EXPR
, lab
);
6624 stmtblock_t ifblock
;
6626 gfc_init_block (&ifblock
);
6627 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
6628 gfc_add_modify (&ifblock
, fast
, logical_true_node
);
6629 ifbody
= gfc_finish_block (&ifblock
);
6631 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
6632 build_empty_stmt (input_location
));
6633 gfc_add_expr_to_block (&block2
, tmp
);
6637 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6639 tmp
= fold_build2_loc (input_location
,
6640 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
6641 type
, arrayse
.expr
, limit
);
6642 gfc_add_modify (&block2
, limit
, tmp
);
6647 tree elsebody
= gfc_finish_block (&block2
);
6649 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6651 if (HONOR_NANS (DECL_MODE (limit
)))
6653 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
,
6654 arrayse
.expr
, limit
);
6655 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
6656 ifbody
= build3_v (COND_EXPR
, tmp
, ifbody
,
6657 build_empty_stmt (input_location
));
6661 tmp
= fold_build2_loc (input_location
,
6662 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
6663 type
, arrayse
.expr
, limit
);
6664 ifbody
= build2_v (MODIFY_EXPR
, limit
, tmp
);
6666 tmp
= build3_v (COND_EXPR
, fast
, ifbody
, elsebody
);
6667 gfc_add_expr_to_block (&block
, tmp
);
6670 gfc_add_block_to_block (&block
, &block2
);
6672 gfc_add_block_to_block (&block
, &arrayse
.post
);
6674 tmp
= gfc_finish_block (&block
);
6677 /* We enclose the above in if (mask) {...}. If the mask is an
6678 optional argument, generate IF (.NOT. PRESENT(MASK)
6681 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6682 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
6683 build_empty_stmt (input_location
));
6685 gfc_add_expr_to_block (&body
, tmp
);
6689 gfc_trans_scalarized_loop_boundary (&loop
, &body
);
6691 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
,
6693 gfc_add_modify (&loop
.code
[0], limit
, tmp
);
6694 gfc_add_expr_to_block (&loop
.code
[0], build1_v (LABEL_EXPR
, lab
));
6696 /* If we have a mask, only add this element if the mask is set. */
6699 gfc_init_se (&maskse
, NULL
);
6700 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
6702 gfc_conv_expr_val (&maskse
, maskexpr
);
6703 gfc_add_block_to_block (&body
, &maskse
.pre
);
6705 gfc_start_block (&block
);
6708 gfc_init_block (&block
);
6710 /* Compare with the current limit. */
6711 gfc_init_se (&arrayse
, NULL
);
6712 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
6713 arrayse
.ss
= arrayss
;
6714 gfc_conv_expr_val (&arrayse
, arrayexpr
);
6715 gfc_add_block_to_block (&block
, &arrayse
.pre
);
6717 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
6719 if (HONOR_NANS (DECL_MODE (limit
)))
6721 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
,
6722 arrayse
.expr
, limit
);
6723 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
6724 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
6725 build_empty_stmt (input_location
));
6726 gfc_add_expr_to_block (&block
, tmp
);
6730 tmp
= fold_build2_loc (input_location
,
6731 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
6732 type
, arrayse
.expr
, limit
);
6733 gfc_add_modify (&block
, limit
, tmp
);
6736 gfc_add_block_to_block (&block
, &arrayse
.post
);
6738 tmp
= gfc_finish_block (&block
);
6740 /* We enclose the above in if (mask) {...}. */
6743 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6744 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
,
6745 build_empty_stmt (input_location
));
6748 gfc_add_expr_to_block (&body
, tmp
);
6749 /* Avoid initializing loopvar[0] again, it should be left where
6750 it finished by the first loop. */
6751 loop
.from
[0] = loop
.loopvar
[0];
6753 gfc_trans_scalarizing_loops (&loop
, &body
);
6757 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
,
6759 ifbody
= build2_v (MODIFY_EXPR
, limit
, tmp
);
6760 tmp
= build3_v (COND_EXPR
, fast
, build_empty_stmt (input_location
),
6762 gfc_add_expr_to_block (&loop
.pre
, tmp
);
6764 else if (HONOR_INFINITIES (DECL_MODE (limit
)) && !lab
)
6766 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
, limit
,
6768 gfc_add_modify (&loop
.pre
, limit
, tmp
);
6771 /* For a scalar mask, enclose the loop in an if statement. */
6772 if (maskexpr
&& maskss
== NULL
)
6777 gfc_init_se (&maskse
, NULL
);
6778 gfc_conv_expr_val (&maskse
, maskexpr
);
6779 gfc_init_block (&block
);
6780 gfc_add_block_to_block (&block
, &loop
.pre
);
6781 gfc_add_block_to_block (&block
, &loop
.post
);
6782 tmp
= gfc_finish_block (&block
);
6784 if (HONOR_INFINITIES (DECL_MODE (limit
)))
6785 else_stmt
= build2_v (MODIFY_EXPR
, limit
, huge_cst
);
6787 else_stmt
= build_empty_stmt (input_location
);
6789 ifmask
= conv_mask_condition (&maskse
, maskexpr
, optional_mask
);
6790 tmp
= build3_v (COND_EXPR
, ifmask
, tmp
, else_stmt
);
6791 gfc_add_expr_to_block (&block
, tmp
);
6792 gfc_add_block_to_block (&se
->pre
, &block
);
6796 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
6797 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
6800 gfc_cleanup_loop (&loop
);
6805 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
6807 gfc_conv_intrinsic_btest (gfc_se
* se
, gfc_expr
* expr
)
6813 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6814 type
= TREE_TYPE (args
[0]);
6816 /* Optionally generate code for runtime argument check. */
6817 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
6819 tree below
= fold_build2_loc (input_location
, LT_EXPR
,
6820 logical_type_node
, args
[1],
6821 build_int_cst (TREE_TYPE (args
[1]), 0));
6822 tree nbits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
6823 tree above
= fold_build2_loc (input_location
, GE_EXPR
,
6824 logical_type_node
, args
[1], nbits
);
6825 tree scond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
6826 logical_type_node
, below
, above
);
6827 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
6828 "POS argument (%ld) out of range 0:%ld "
6829 "in intrinsic BTEST",
6830 fold_convert (long_integer_type_node
, args
[1]),
6831 fold_convert (long_integer_type_node
, nbits
));
6834 tmp
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
6835 build_int_cst (type
, 1), args
[1]);
6836 tmp
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[0], tmp
);
6837 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, tmp
,
6838 build_int_cst (type
, 0));
6839 type
= gfc_typenode_for_spec (&expr
->ts
);
6840 se
->expr
= convert (type
, tmp
);
6844 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
6846 gfc_conv_intrinsic_bitcomp (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
6850 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6852 /* Convert both arguments to the unsigned type of the same size. */
6853 args
[0] = fold_convert (unsigned_type_for (TREE_TYPE (args
[0])), args
[0]);
6854 args
[1] = fold_convert (unsigned_type_for (TREE_TYPE (args
[1])), args
[1]);
6856 /* If they have unequal type size, convert to the larger one. */
6857 if (TYPE_PRECISION (TREE_TYPE (args
[0]))
6858 > TYPE_PRECISION (TREE_TYPE (args
[1])))
6859 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
6860 else if (TYPE_PRECISION (TREE_TYPE (args
[1]))
6861 > TYPE_PRECISION (TREE_TYPE (args
[0])))
6862 args
[0] = fold_convert (TREE_TYPE (args
[1]), args
[0]);
6864 /* Now, we compare them. */
6865 se
->expr
= fold_build2_loc (input_location
, op
, logical_type_node
,
6870 /* Generate code to perform the specified operation. */
6872 gfc_conv_intrinsic_bitop (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
6876 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6877 se
->expr
= fold_build2_loc (input_location
, op
, TREE_TYPE (args
[0]),
6883 gfc_conv_intrinsic_not (gfc_se
* se
, gfc_expr
* expr
)
6887 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6888 se
->expr
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
6889 TREE_TYPE (arg
), arg
);
6892 /* Set or clear a single bit. */
6894 gfc_conv_intrinsic_singlebitop (gfc_se
* se
, gfc_expr
* expr
, int set
)
6901 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6902 type
= TREE_TYPE (args
[0]);
6904 /* Optionally generate code for runtime argument check. */
6905 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
6907 tree below
= fold_build2_loc (input_location
, LT_EXPR
,
6908 logical_type_node
, args
[1],
6909 build_int_cst (TREE_TYPE (args
[1]), 0));
6910 tree nbits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
6911 tree above
= fold_build2_loc (input_location
, GE_EXPR
,
6912 logical_type_node
, args
[1], nbits
);
6913 tree scond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
6914 logical_type_node
, below
, above
);
6915 size_t len_name
= strlen (expr
->value
.function
.isym
->name
);
6916 char *name
= XALLOCAVEC (char, len_name
+ 1);
6917 for (size_t i
= 0; i
< len_name
; i
++)
6918 name
[i
] = TOUPPER (expr
->value
.function
.isym
->name
[i
]);
6919 name
[len_name
] = '\0';
6920 tree iname
= gfc_build_addr_expr (pchar_type_node
,
6921 gfc_build_cstring_const (name
));
6922 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
6923 "POS argument (%ld) out of range 0:%ld "
6925 fold_convert (long_integer_type_node
, args
[1]),
6926 fold_convert (long_integer_type_node
, nbits
),
6930 tmp
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
6931 build_int_cst (type
, 1), args
[1]);
6937 tmp
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, type
, tmp
);
6939 se
->expr
= fold_build2_loc (input_location
, op
, type
, args
[0], tmp
);
6942 /* Extract a sequence of bits.
6943 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
6945 gfc_conv_intrinsic_ibits (gfc_se
* se
, gfc_expr
* expr
)
6951 tree num_bits
, cond
;
6953 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
6954 type
= TREE_TYPE (args
[0]);
6956 /* Optionally generate code for runtime argument check. */
6957 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
6959 tree tmp1
= fold_convert (long_integer_type_node
, args
[1]);
6960 tree tmp2
= fold_convert (long_integer_type_node
, args
[2]);
6961 tree nbits
= build_int_cst (long_integer_type_node
,
6962 TYPE_PRECISION (type
));
6963 tree below
= fold_build2_loc (input_location
, LT_EXPR
,
6964 logical_type_node
, args
[1],
6965 build_int_cst (TREE_TYPE (args
[1]), 0));
6966 tree above
= fold_build2_loc (input_location
, GT_EXPR
,
6967 logical_type_node
, tmp1
, nbits
);
6968 tree scond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
6969 logical_type_node
, below
, above
);
6970 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
6971 "POS argument (%ld) out of range 0:%ld "
6972 "in intrinsic IBITS", tmp1
, nbits
);
6973 below
= fold_build2_loc (input_location
, LT_EXPR
,
6974 logical_type_node
, args
[2],
6975 build_int_cst (TREE_TYPE (args
[2]), 0));
6976 above
= fold_build2_loc (input_location
, GT_EXPR
,
6977 logical_type_node
, tmp2
, nbits
);
6978 scond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
6979 logical_type_node
, below
, above
);
6980 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
6981 "LEN argument (%ld) out of range 0:%ld "
6982 "in intrinsic IBITS", tmp2
, nbits
);
6983 above
= fold_build2_loc (input_location
, PLUS_EXPR
,
6984 long_integer_type_node
, tmp1
, tmp2
);
6985 scond
= fold_build2_loc (input_location
, GT_EXPR
,
6986 logical_type_node
, above
, nbits
);
6987 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
6988 "POS(%ld)+LEN(%ld)>BIT_SIZE(%ld) "
6989 "in intrinsic IBITS", tmp1
, tmp2
, nbits
);
6992 /* The Fortran standard allows (shift width) LEN <= BIT_SIZE(I), whereas
6993 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
6994 special case. See also gfc_conv_intrinsic_ishft (). */
6995 num_bits
= build_int_cst (TREE_TYPE (args
[2]), TYPE_PRECISION (type
));
6997 mask
= build_int_cst (type
, -1);
6998 mask
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
, mask
, args
[2]);
6999 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, args
[2],
7001 mask
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
7002 build_int_cst (type
, 0), mask
);
7003 mask
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, type
, mask
);
7005 tmp
= fold_build2_loc (input_location
, RSHIFT_EXPR
, type
, args
[0], args
[1]);
7007 se
->expr
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, tmp
, mask
);
7011 gfc_conv_intrinsic_shift (gfc_se
* se
, gfc_expr
* expr
, bool right_shift
,
7014 tree args
[2], type
, num_bits
, cond
;
7016 bool do_convert
= false;
7018 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
7020 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
7021 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
7022 type
= TREE_TYPE (args
[0]);
7026 args
[0] = fold_convert (unsigned_type_for (type
), args
[0]);
7030 gcc_assert (right_shift
);
7032 if (flag_unsigned
&& arithmetic
&& expr
->ts
.type
== BT_UNSIGNED
)
7035 args
[0] = fold_convert (signed_type_for (type
), args
[0]);
7038 se
->expr
= fold_build2_loc (input_location
,
7039 right_shift
? RSHIFT_EXPR
: LSHIFT_EXPR
,
7040 TREE_TYPE (args
[0]), args
[0], args
[1]);
7043 se
->expr
= fold_convert (type
, se
->expr
);
7046 bigshift
= build_int_cst (type
, 0);
7049 tree nonneg
= fold_build2_loc (input_location
, GE_EXPR
,
7050 logical_type_node
, args
[0],
7051 build_int_cst (TREE_TYPE (args
[0]), 0));
7052 bigshift
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonneg
,
7053 build_int_cst (type
, 0),
7054 build_int_cst (type
, -1));
7057 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
7058 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
7060 num_bits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
7062 /* Optionally generate code for runtime argument check. */
7063 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
7065 tree below
= fold_build2_loc (input_location
, LT_EXPR
,
7066 logical_type_node
, args
[1],
7067 build_int_cst (TREE_TYPE (args
[1]), 0));
7068 tree above
= fold_build2_loc (input_location
, GT_EXPR
,
7069 logical_type_node
, args
[1], num_bits
);
7070 tree scond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
7071 logical_type_node
, below
, above
);
7072 size_t len_name
= strlen (expr
->value
.function
.isym
->name
);
7073 char *name
= XALLOCAVEC (char, len_name
+ 1);
7074 for (size_t i
= 0; i
< len_name
; i
++)
7075 name
[i
] = TOUPPER (expr
->value
.function
.isym
->name
[i
]);
7076 name
[len_name
] = '\0';
7077 tree iname
= gfc_build_addr_expr (pchar_type_node
,
7078 gfc_build_cstring_const (name
));
7079 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
7080 "SHIFT argument (%ld) out of range 0:%ld "
7082 fold_convert (long_integer_type_node
, args
[1]),
7083 fold_convert (long_integer_type_node
, num_bits
),
7087 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
7090 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
7091 bigshift
, se
->expr
);
7094 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
7096 : ((shift >= 0) ? i << shift : i >> -shift)
7097 where all shifts are logical shifts. */
7099 gfc_conv_intrinsic_ishft (gfc_se
* se
, gfc_expr
* expr
)
7111 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
7113 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
7114 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
7116 type
= TREE_TYPE (args
[0]);
7117 utype
= unsigned_type_for (type
);
7119 width
= fold_build1_loc (input_location
, ABS_EXPR
, TREE_TYPE (args
[1]),
7122 /* Left shift if positive. */
7123 lshift
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
, args
[0], width
);
7125 /* Right shift if negative.
7126 We convert to an unsigned type because we want a logical shift.
7127 The standard doesn't define the case of shifting negative
7128 numbers, and we try to be compatible with other compilers, most
7129 notably g77, here. */
7130 rshift
= fold_convert (type
, fold_build2_loc (input_location
, RSHIFT_EXPR
,
7131 utype
, convert (utype
, args
[0]), width
));
7133 tmp
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, args
[1],
7134 build_int_cst (TREE_TYPE (args
[1]), 0));
7135 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, lshift
, rshift
);
7137 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
7138 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
7140 num_bits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
7142 /* Optionally generate code for runtime argument check. */
7143 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
7145 tree outside
= fold_build2_loc (input_location
, GT_EXPR
,
7146 logical_type_node
, width
, num_bits
);
7147 gfc_trans_runtime_check (true, false, outside
, &se
->pre
, &expr
->where
,
7148 "SHIFT argument (%ld) out of range -%ld:%ld "
7149 "in intrinsic ISHFT",
7150 fold_convert (long_integer_type_node
, args
[1]),
7151 fold_convert (long_integer_type_node
, num_bits
),
7152 fold_convert (long_integer_type_node
, num_bits
));
7155 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, width
,
7157 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
7158 build_int_cst (type
, 0), tmp
);
7162 /* Circular shift. AKA rotate or barrel shift. */
7165 gfc_conv_intrinsic_ishftc (gfc_se
* se
, gfc_expr
* expr
)
7174 unsigned int num_args
;
7176 num_args
= gfc_intrinsic_argument_list_length (expr
);
7177 args
= XALLOCAVEC (tree
, num_args
);
7179 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
7181 type
= TREE_TYPE (args
[0]);
7182 nbits
= build_int_cst (long_integer_type_node
, TYPE_PRECISION (type
));
7186 gfc_expr
*size
= expr
->value
.function
.actual
->next
->next
->expr
;
7188 /* Use a library function for the 3 parameter version. */
7189 tree int4type
= gfc_get_int_type (4);
7191 /* Treat optional SIZE argument when it is passed as an optional
7192 dummy. If SIZE is absent, the default value is BIT_SIZE(I). */
7193 if (size
->expr_type
== EXPR_VARIABLE
7194 && size
->symtree
->n
.sym
->attr
.dummy
7195 && size
->symtree
->n
.sym
->attr
.optional
)
7197 tree type_of_size
= TREE_TYPE (args
[2]);
7198 args
[2] = build3_loc (input_location
, COND_EXPR
, type_of_size
,
7199 gfc_conv_expr_present (size
->symtree
->n
.sym
),
7200 args
[2], fold_convert (type_of_size
, nbits
));
7203 /* We convert the first argument to at least 4 bytes, and
7204 convert back afterwards. This removes the need for library
7205 functions for all argument sizes, and function will be
7206 aligned to at least 32 bits, so there's no loss. */
7207 if (expr
->ts
.kind
< 4)
7208 args
[0] = convert (int4type
, args
[0]);
7210 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
7211 need loads of library functions. They cannot have values >
7212 BIT_SIZE (I) so the conversion is safe. */
7213 args
[1] = convert (int4type
, args
[1]);
7214 args
[2] = convert (int4type
, args
[2]);
7216 /* Optionally generate code for runtime argument check. */
7217 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
7219 tree size
= fold_convert (long_integer_type_node
, args
[2]);
7220 tree below
= fold_build2_loc (input_location
, LE_EXPR
,
7221 logical_type_node
, size
,
7222 build_int_cst (TREE_TYPE (args
[1]), 0));
7223 tree above
= fold_build2_loc (input_location
, GT_EXPR
,
7224 logical_type_node
, size
, nbits
);
7225 tree scond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
7226 logical_type_node
, below
, above
);
7227 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
7228 "SIZE argument (%ld) out of range 1:%ld "
7229 "in intrinsic ISHFTC", size
, nbits
);
7230 tree width
= fold_convert (long_integer_type_node
, args
[1]);
7231 width
= fold_build1_loc (input_location
, ABS_EXPR
,
7232 long_integer_type_node
, width
);
7233 scond
= fold_build2_loc (input_location
, GT_EXPR
,
7234 logical_type_node
, width
, size
);
7235 gfc_trans_runtime_check (true, false, scond
, &se
->pre
, &expr
->where
,
7236 "SHIFT argument (%ld) out of range -%ld:%ld "
7237 "in intrinsic ISHFTC",
7238 fold_convert (long_integer_type_node
, args
[1]),
7242 switch (expr
->ts
.kind
)
7247 tmp
= gfor_fndecl_math_ishftc4
;
7250 tmp
= gfor_fndecl_math_ishftc8
;
7253 tmp
= gfor_fndecl_math_ishftc16
;
7258 se
->expr
= build_call_expr_loc (input_location
,
7259 tmp
, 3, args
[0], args
[1], args
[2]);
7260 /* Convert the result back to the original type, if we extended
7261 the first argument's width above. */
7262 if (expr
->ts
.kind
< 4)
7263 se
->expr
= convert (type
, se
->expr
);
7268 /* Evaluate arguments only once. */
7269 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
7270 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
7272 /* Optionally generate code for runtime argument check. */
7273 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
7275 tree width
= fold_convert (long_integer_type_node
, args
[1]);
7276 width
= fold_build1_loc (input_location
, ABS_EXPR
,
7277 long_integer_type_node
, width
);
7278 tree outside
= fold_build2_loc (input_location
, GT_EXPR
,
7279 logical_type_node
, width
, nbits
);
7280 gfc_trans_runtime_check (true, false, outside
, &se
->pre
, &expr
->where
,
7281 "SHIFT argument (%ld) out of range -%ld:%ld "
7282 "in intrinsic ISHFTC",
7283 fold_convert (long_integer_type_node
, args
[1]),
7287 /* Rotate left if positive. */
7288 lrot
= fold_build2_loc (input_location
, LROTATE_EXPR
, type
, args
[0], args
[1]);
7290 /* Rotate right if negative. */
7291 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (args
[1]),
7293 rrot
= fold_build2_loc (input_location
,RROTATE_EXPR
, type
, args
[0], tmp
);
7295 zero
= build_int_cst (TREE_TYPE (args
[1]), 0);
7296 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
, args
[1],
7298 rrot
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, lrot
, rrot
);
7300 /* Do nothing if shift == 0. */
7301 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, args
[1],
7303 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, args
[0],
7308 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
7309 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
7311 The conditional expression is necessary because the result of LEADZ(0)
7312 is defined, but the result of __builtin_clz(0) is undefined for most
7315 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
7316 difference in bit size between the argument of LEADZ and the C int. */
7319 gfc_conv_intrinsic_leadz (gfc_se
* se
, gfc_expr
* expr
)
7331 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
7332 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
7334 /* Which variant of __builtin_clz* should we call? */
7335 if (argsize
<= INT_TYPE_SIZE
)
7337 arg_type
= unsigned_type_node
;
7338 func
= builtin_decl_explicit (BUILT_IN_CLZ
);
7340 else if (argsize
<= LONG_TYPE_SIZE
)
7342 arg_type
= long_unsigned_type_node
;
7343 func
= builtin_decl_explicit (BUILT_IN_CLZL
);
7345 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
7347 arg_type
= long_long_unsigned_type_node
;
7348 func
= builtin_decl_explicit (BUILT_IN_CLZLL
);
7352 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
7353 arg_type
= gfc_build_uint_type (argsize
);
7357 /* Convert the actual argument twice: first, to the unsigned type of the
7358 same size; then, to the proper argument type for the built-in
7359 function. But the return type is of the default INTEGER kind. */
7360 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
7361 arg
= fold_convert (arg_type
, arg
);
7362 arg
= gfc_evaluate_now (arg
, &se
->pre
);
7363 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
7365 /* Compute LEADZ for the case i .ne. 0. */
7368 s
= TYPE_PRECISION (arg_type
) - argsize
;
7369 tmp
= fold_convert (result_type
,
7370 build_call_expr_loc (input_location
, func
,
7372 leadz
= fold_build2_loc (input_location
, MINUS_EXPR
, result_type
,
7373 tmp
, build_int_cst (result_type
, s
));
7377 /* We end up here if the argument type is larger than 'long long'.
7378 We generate this code:
7380 if (x & (ULL_MAX << ULL_SIZE) != 0)
7381 return clzll ((unsigned long long) (x >> ULLSIZE));
7383 return ULL_SIZE + clzll ((unsigned long long) x);
7384 where ULL_MAX is the largest value that a ULL_MAX can hold
7385 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
7386 is the bit-size of the long long type (64 in this example). */
7387 tree ullsize
, ullmax
, tmp1
, tmp2
, btmp
;
7389 ullsize
= build_int_cst (result_type
, LONG_LONG_TYPE_SIZE
);
7390 ullmax
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
7391 long_long_unsigned_type_node
,
7392 build_int_cst (long_long_unsigned_type_node
,
7395 cond
= fold_build2_loc (input_location
, LSHIFT_EXPR
, arg_type
,
7396 fold_convert (arg_type
, ullmax
), ullsize
);
7397 cond
= fold_build2_loc (input_location
, BIT_AND_EXPR
, arg_type
,
7399 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
7400 cond
, build_int_cst (arg_type
, 0));
7402 tmp1
= fold_build2_loc (input_location
, RSHIFT_EXPR
, arg_type
,
7404 tmp1
= fold_convert (long_long_unsigned_type_node
, tmp1
);
7405 btmp
= builtin_decl_explicit (BUILT_IN_CLZLL
);
7406 tmp1
= fold_convert (result_type
,
7407 build_call_expr_loc (input_location
, btmp
, 1, tmp1
));
7409 tmp2
= fold_convert (long_long_unsigned_type_node
, arg
);
7410 btmp
= builtin_decl_explicit (BUILT_IN_CLZLL
);
7411 tmp2
= fold_convert (result_type
,
7412 build_call_expr_loc (input_location
, btmp
, 1, tmp2
));
7413 tmp2
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
7416 leadz
= fold_build3_loc (input_location
, COND_EXPR
, result_type
,
7420 /* Build BIT_SIZE. */
7421 bit_size
= build_int_cst (result_type
, argsize
);
7423 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
7424 arg
, build_int_cst (arg_type
, 0));
7425 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, result_type
, cond
,
7430 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
7432 The conditional expression is necessary because the result of TRAILZ(0)
7433 is defined, but the result of __builtin_ctz(0) is undefined for most
7437 gfc_conv_intrinsic_trailz (gfc_se
* se
, gfc_expr
*expr
)
7448 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
7449 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
7451 /* Which variant of __builtin_ctz* should we call? */
7452 if (argsize
<= INT_TYPE_SIZE
)
7454 arg_type
= unsigned_type_node
;
7455 func
= builtin_decl_explicit (BUILT_IN_CTZ
);
7457 else if (argsize
<= LONG_TYPE_SIZE
)
7459 arg_type
= long_unsigned_type_node
;
7460 func
= builtin_decl_explicit (BUILT_IN_CTZL
);
7462 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
7464 arg_type
= long_long_unsigned_type_node
;
7465 func
= builtin_decl_explicit (BUILT_IN_CTZLL
);
7469 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
7470 arg_type
= gfc_build_uint_type (argsize
);
7474 /* Convert the actual argument twice: first, to the unsigned type of the
7475 same size; then, to the proper argument type for the built-in
7476 function. But the return type is of the default INTEGER kind. */
7477 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
7478 arg
= fold_convert (arg_type
, arg
);
7479 arg
= gfc_evaluate_now (arg
, &se
->pre
);
7480 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
7482 /* Compute TRAILZ for the case i .ne. 0. */
7484 trailz
= fold_convert (result_type
, build_call_expr_loc (input_location
,
7488 /* We end up here if the argument type is larger than 'long long'.
7489 We generate this code:
7491 if ((x & ULL_MAX) == 0)
7492 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
7494 return ctzll ((unsigned long long) x);
7496 where ULL_MAX is the largest value that a ULL_MAX can hold
7497 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
7498 is the bit-size of the long long type (64 in this example). */
7499 tree ullsize
, ullmax
, tmp1
, tmp2
, btmp
;
7501 ullsize
= build_int_cst (result_type
, LONG_LONG_TYPE_SIZE
);
7502 ullmax
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
7503 long_long_unsigned_type_node
,
7504 build_int_cst (long_long_unsigned_type_node
, 0));
7506 cond
= fold_build2_loc (input_location
, BIT_AND_EXPR
, arg_type
, arg
,
7507 fold_convert (arg_type
, ullmax
));
7508 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, cond
,
7509 build_int_cst (arg_type
, 0));
7511 tmp1
= fold_build2_loc (input_location
, RSHIFT_EXPR
, arg_type
,
7513 tmp1
= fold_convert (long_long_unsigned_type_node
, tmp1
);
7514 btmp
= builtin_decl_explicit (BUILT_IN_CTZLL
);
7515 tmp1
= fold_convert (result_type
,
7516 build_call_expr_loc (input_location
, btmp
, 1, tmp1
));
7517 tmp1
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
7520 tmp2
= fold_convert (long_long_unsigned_type_node
, arg
);
7521 btmp
= builtin_decl_explicit (BUILT_IN_CTZLL
);
7522 tmp2
= fold_convert (result_type
,
7523 build_call_expr_loc (input_location
, btmp
, 1, tmp2
));
7525 trailz
= fold_build3_loc (input_location
, COND_EXPR
, result_type
,
7529 /* Build BIT_SIZE. */
7530 bit_size
= build_int_cst (result_type
, argsize
);
7532 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
7533 arg
, build_int_cst (arg_type
, 0));
7534 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, result_type
, cond
,
7538 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
7539 for types larger than "long long", we call the long long built-in for
7540 the lower and higher bits and combine the result. */
7543 gfc_conv_intrinsic_popcnt_poppar (gfc_se
* se
, gfc_expr
*expr
, int parity
)
7551 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
7552 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
7553 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
7555 /* Which variant of the builtin should we call? */
7556 if (argsize
<= INT_TYPE_SIZE
)
7558 arg_type
= unsigned_type_node
;
7559 func
= builtin_decl_explicit (parity
7561 : BUILT_IN_POPCOUNT
);
7563 else if (argsize
<= LONG_TYPE_SIZE
)
7565 arg_type
= long_unsigned_type_node
;
7566 func
= builtin_decl_explicit (parity
7568 : BUILT_IN_POPCOUNTL
);
7570 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
7572 arg_type
= long_long_unsigned_type_node
;
7573 func
= builtin_decl_explicit (parity
7575 : BUILT_IN_POPCOUNTLL
);
7579 /* Our argument type is larger than 'long long', which mean none
7580 of the POPCOUNT builtins covers it. We thus call the 'long long'
7581 variant multiple times, and add the results. */
7582 tree utype
, arg2
, call1
, call2
;
7584 /* For now, we only cover the case where argsize is twice as large
7586 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
7588 func
= builtin_decl_explicit (parity
7590 : BUILT_IN_POPCOUNTLL
);
7592 /* Convert it to an integer, and store into a variable. */
7593 utype
= gfc_build_uint_type (argsize
);
7594 arg
= fold_convert (utype
, arg
);
7595 arg
= gfc_evaluate_now (arg
, &se
->pre
);
7597 /* Call the builtin twice. */
7598 call1
= build_call_expr_loc (input_location
, func
, 1,
7599 fold_convert (long_long_unsigned_type_node
,
7602 arg2
= fold_build2_loc (input_location
, RSHIFT_EXPR
, utype
, arg
,
7603 build_int_cst (utype
, LONG_LONG_TYPE_SIZE
));
7604 call2
= build_call_expr_loc (input_location
, func
, 1,
7605 fold_convert (long_long_unsigned_type_node
,
7608 /* Combine the results. */
7610 se
->expr
= fold_build2_loc (input_location
, BIT_XOR_EXPR
,
7611 integer_type_node
, call1
, call2
);
7613 se
->expr
= fold_build2_loc (input_location
, PLUS_EXPR
,
7614 integer_type_node
, call1
, call2
);
7616 se
->expr
= convert (result_type
, se
->expr
);
7620 /* Convert the actual argument twice: first, to the unsigned type of the
7621 same size; then, to the proper argument type for the built-in
7623 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
7624 arg
= fold_convert (arg_type
, arg
);
7626 se
->expr
= fold_convert (result_type
,
7627 build_call_expr_loc (input_location
, func
, 1, arg
));
7631 /* Process an intrinsic with unspecified argument-types that has an optional
7632 argument (which could be of type character), e.g. EOSHIFT. For those, we
7633 need to append the string length of the optional argument if it is not
7634 present and the type is really character.
7635 primary specifies the position (starting at 1) of the non-optional argument
7636 specifying the type and optional gives the position of the optional
7637 argument in the arglist. */
7640 conv_generic_with_optional_char_arg (gfc_se
* se
, gfc_expr
* expr
,
7641 unsigned primary
, unsigned optional
)
7643 gfc_actual_arglist
* prim_arg
;
7644 gfc_actual_arglist
* opt_arg
;
7646 gfc_actual_arglist
* arg
;
7648 vec
<tree
, va_gc
> *append_args
;
7650 /* Find the two arguments given as position. */
7654 for (arg
= expr
->value
.function
.actual
; arg
; arg
= arg
->next
)
7658 if (cur_pos
== primary
)
7660 if (cur_pos
== optional
)
7663 if (cur_pos
>= primary
&& cur_pos
>= optional
)
7666 gcc_assert (prim_arg
);
7667 gcc_assert (prim_arg
->expr
);
7668 gcc_assert (opt_arg
);
7670 /* If we do have type CHARACTER and the optional argument is really absent,
7671 append a dummy 0 as string length. */
7673 if (prim_arg
->expr
->ts
.type
== BT_CHARACTER
&& !opt_arg
->expr
)
7677 dummy
= build_int_cst (gfc_charlen_type_node
, 0);
7678 vec_alloc (append_args
, 1);
7679 append_args
->quick_push (dummy
);
7682 /* Build the call itself. */
7683 gcc_assert (!se
->ignore_optional
);
7684 sym
= gfc_get_symbol_for_expr (expr
, false);
7685 gfc_conv_procedure_call (se
, sym
, expr
->value
.function
.actual
, expr
,
7687 gfc_free_symbol (sym
);
7690 /* The length of a character string. */
7692 gfc_conv_intrinsic_len (gfc_se
* se
, gfc_expr
* expr
)
7701 gcc_assert (!se
->ss
);
7703 arg
= expr
->value
.function
.actual
->expr
;
7705 type
= gfc_typenode_for_spec (&expr
->ts
);
7706 switch (arg
->expr_type
)
7709 len
= build_int_cst (gfc_charlen_type_node
, arg
->value
.character
.length
);
7713 /* Obtain the string length from the function used by
7714 trans-array.cc(gfc_trans_array_constructor). */
7716 get_array_ctor_strlen (&se
->pre
, arg
->value
.constructor
, &len
);
7720 if (arg
->ref
== NULL
7721 || (arg
->ref
->next
== NULL
&& arg
->ref
->type
== REF_ARRAY
))
7723 /* This doesn't catch all cases.
7724 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
7725 and the surrounding thread. */
7726 sym
= arg
->symtree
->n
.sym
;
7727 decl
= gfc_get_symbol_decl (sym
);
7728 if (decl
== current_function_decl
&& sym
->attr
.function
7729 && (sym
->result
== sym
))
7730 decl
= gfc_get_fake_result_decl (sym
, 0);
7732 len
= sym
->ts
.u
.cl
->backend_decl
;
7740 gfc_init_se (&argse
, se
);
7742 gfc_conv_expr (&argse
, arg
);
7744 gfc_conv_expr_descriptor (&argse
, arg
);
7745 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7746 gfc_add_block_to_block (&se
->post
, &argse
.post
);
7747 len
= argse
.string_length
;
7750 se
->expr
= convert (type
, len
);
7753 /* The length of a character string not including trailing blanks. */
7755 gfc_conv_intrinsic_len_trim (gfc_se
* se
, gfc_expr
* expr
)
7757 int kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
7758 tree args
[2], type
, fndecl
;
7760 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
7761 type
= gfc_typenode_for_spec (&expr
->ts
);
7764 fndecl
= gfor_fndecl_string_len_trim
;
7766 fndecl
= gfor_fndecl_string_len_trim_char4
;
7770 se
->expr
= build_call_expr_loc (input_location
,
7771 fndecl
, 2, args
[0], args
[1]);
7772 se
->expr
= convert (type
, se
->expr
);
7776 /* Returns the starting position of a substring within a string. */
7779 gfc_conv_intrinsic_index_scan_verify (gfc_se
* se
, gfc_expr
* expr
,
7782 tree logical4_type_node
= gfc_get_logical_type (4);
7786 unsigned int num_args
;
7788 args
= XALLOCAVEC (tree
, 5);
7790 /* Get number of arguments; characters count double due to the
7791 string length argument. Kind= is not passed to the library
7792 and thus ignored. */
7793 if (expr
->value
.function
.actual
->next
->next
->expr
== NULL
)
7798 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
7799 type
= gfc_typenode_for_spec (&expr
->ts
);
7802 args
[4] = build_int_cst (logical4_type_node
, 0);
7804 args
[4] = convert (logical4_type_node
, args
[4]);
7806 fndecl
= build_addr (function
);
7807 se
->expr
= build_call_array_loc (input_location
,
7808 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
7810 se
->expr
= convert (type
, se
->expr
);
7814 /* The ascii value for a single character. */
7816 gfc_conv_intrinsic_ichar (gfc_se
* se
, gfc_expr
* expr
)
7818 tree args
[3], type
, pchartype
;
7821 nargs
= gfc_intrinsic_argument_list_length (expr
);
7822 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
7823 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args
[1])));
7824 pchartype
= gfc_get_pchar_type (expr
->value
.function
.actual
->expr
->ts
.kind
);
7825 args
[1] = fold_build1_loc (input_location
, NOP_EXPR
, pchartype
, args
[1]);
7826 type
= gfc_typenode_for_spec (&expr
->ts
);
7828 se
->expr
= build_fold_indirect_ref_loc (input_location
,
7830 se
->expr
= convert (type
, se
->expr
);
7834 /* Intrinsic ISNAN calls __builtin_isnan. */
7837 gfc_conv_intrinsic_isnan (gfc_se
* se
, gfc_expr
* expr
)
7841 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
7842 se
->expr
= build_call_expr_loc (input_location
,
7843 builtin_decl_explicit (BUILT_IN_ISNAN
),
7845 STRIP_TYPE_NOPS (se
->expr
);
7846 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
7850 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
7851 their argument against a constant integer value. */
7854 gfc_conv_has_intvalue (gfc_se
* se
, gfc_expr
* expr
, const int value
)
7858 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
7859 se
->expr
= fold_build2_loc (input_location
, EQ_EXPR
,
7860 gfc_typenode_for_spec (&expr
->ts
),
7861 arg
, build_int_cst (TREE_TYPE (arg
), value
));
7866 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
7869 gfc_conv_intrinsic_merge (gfc_se
* se
, gfc_expr
* expr
)
7877 unsigned int num_args
;
7879 num_args
= gfc_intrinsic_argument_list_length (expr
);
7880 args
= XALLOCAVEC (tree
, num_args
);
7882 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
7883 if (expr
->ts
.type
!= BT_CHARACTER
)
7891 /* We do the same as in the non-character case, but the argument
7892 list is different because of the string length arguments. We
7893 also have to set the string length for the result. */
7900 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr
->where
, len
, len2
,
7902 se
->string_length
= len
;
7904 tsource
= gfc_evaluate_now (tsource
, &se
->pre
);
7905 fsource
= gfc_evaluate_now (fsource
, &se
->pre
);
7906 mask
= gfc_evaluate_now (mask
, &se
->pre
);
7907 type
= TREE_TYPE (tsource
);
7908 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, mask
, tsource
,
7909 fold_convert (type
, fsource
));
7913 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
7916 gfc_conv_intrinsic_merge_bits (gfc_se
* se
, gfc_expr
* expr
)
7918 tree args
[3], mask
, type
;
7920 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
7921 mask
= gfc_evaluate_now (args
[2], &se
->pre
);
7923 type
= TREE_TYPE (args
[0]);
7924 gcc_assert (TREE_TYPE (args
[1]) == type
);
7925 gcc_assert (TREE_TYPE (mask
) == type
);
7927 args
[0] = fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[0], mask
);
7928 args
[1] = fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[1],
7929 fold_build1_loc (input_location
, BIT_NOT_EXPR
,
7931 se
->expr
= fold_build2_loc (input_location
, BIT_IOR_EXPR
, type
,
7936 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
7937 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
7940 gfc_conv_intrinsic_mask (gfc_se
* se
, gfc_expr
* expr
, int left
)
7942 tree arg
, allones
, type
, utype
, res
, cond
, bitsize
;
7945 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
7946 arg
= gfc_evaluate_now (arg
, &se
->pre
);
7948 type
= gfc_get_int_type (expr
->ts
.kind
);
7949 utype
= unsigned_type_for (type
);
7951 i
= gfc_validate_kind (BT_INTEGER
, expr
->ts
.kind
, false);
7952 bitsize
= build_int_cst (TREE_TYPE (arg
), gfc_integer_kinds
[i
].bit_size
);
7954 allones
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, utype
,
7955 build_int_cst (utype
, 0));
7959 /* Left-justified mask. */
7960 res
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (arg
),
7962 res
= fold_build2_loc (input_location
, LSHIFT_EXPR
, utype
, allones
,
7963 fold_convert (utype
, res
));
7965 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
7966 smaller than type width. */
7967 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, arg
,
7968 build_int_cst (TREE_TYPE (arg
), 0));
7969 res
= fold_build3_loc (input_location
, COND_EXPR
, utype
, cond
,
7970 build_int_cst (utype
, 0), res
);
7974 /* Right-justified mask. */
7975 res
= fold_build2_loc (input_location
, LSHIFT_EXPR
, utype
, allones
,
7976 fold_convert (utype
, arg
));
7977 res
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, utype
, res
);
7979 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
7980 strictly smaller than type width. */
7981 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
7983 res
= fold_build3_loc (input_location
, COND_EXPR
, utype
,
7984 cond
, allones
, res
);
7987 se
->expr
= fold_convert (type
, res
);
7991 /* FRACTION (s) is translated into:
7992 isfinite (s) ? frexp (s, &dummy_int) : NaN */
7994 gfc_conv_intrinsic_fraction (gfc_se
* se
, gfc_expr
* expr
)
7996 tree arg
, type
, tmp
, res
, frexp
, cond
;
7998 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
8000 type
= gfc_typenode_for_spec (&expr
->ts
);
8001 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
8002 arg
= gfc_evaluate_now (arg
, &se
->pre
);
8004 cond
= build_call_expr_loc (input_location
,
8005 builtin_decl_explicit (BUILT_IN_ISFINITE
),
8008 tmp
= gfc_create_var (integer_type_node
, NULL
);
8009 res
= build_call_expr_loc (input_location
, frexp
, 2,
8010 fold_convert (type
, arg
),
8011 gfc_build_addr_expr (NULL_TREE
, tmp
));
8012 res
= fold_convert (type
, res
);
8014 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
,
8015 cond
, res
, gfc_build_nan (type
, ""));
8019 /* NEAREST (s, dir) is translated into
8020 tmp = copysign (HUGE_VAL, dir);
8021 return nextafter (s, tmp);
8024 gfc_conv_intrinsic_nearest (gfc_se
* se
, gfc_expr
* expr
)
8026 tree args
[2], type
, tmp
, nextafter
, copysign
, huge_val
;
8028 nextafter
= gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER
, expr
->ts
.kind
);
8029 copysign
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
, expr
->ts
.kind
);
8031 type
= gfc_typenode_for_spec (&expr
->ts
);
8032 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
8034 huge_val
= gfc_build_inf_or_huge (type
, expr
->ts
.kind
);
8035 tmp
= build_call_expr_loc (input_location
, copysign
, 2, huge_val
,
8036 fold_convert (type
, args
[1]));
8037 se
->expr
= build_call_expr_loc (input_location
, nextafter
, 2,
8038 fold_convert (type
, args
[0]), tmp
);
8039 se
->expr
= fold_convert (type
, se
->expr
);
8043 /* SPACING (s) is translated into
8053 e = MAX_EXPR (e, emin);
8054 res = scalbn (1., e);
8058 where prec is the precision of s, gfc_real_kinds[k].digits,
8059 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
8060 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
8063 gfc_conv_intrinsic_spacing (gfc_se
* se
, gfc_expr
* expr
)
8065 tree arg
, type
, prec
, emin
, tiny
, res
, e
;
8066 tree cond
, nan
, tmp
, frexp
, scalbn
;
8070 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
8071 prec
= build_int_cst (integer_type_node
, gfc_real_kinds
[k
].digits
);
8072 emin
= build_int_cst (integer_type_node
, gfc_real_kinds
[k
].min_exponent
- 1);
8073 tiny
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[k
].tiny
, expr
->ts
.kind
, 0);
8075 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
8076 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
8078 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
8079 arg
= gfc_evaluate_now (arg
, &se
->pre
);
8081 type
= gfc_typenode_for_spec (&expr
->ts
);
8082 e
= gfc_create_var (integer_type_node
, NULL
);
8083 res
= gfc_create_var (type
, NULL
);
8086 /* Build the block for s /= 0. */
8087 gfc_start_block (&block
);
8088 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
8089 gfc_build_addr_expr (NULL_TREE
, e
));
8090 gfc_add_expr_to_block (&block
, tmp
);
8092 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, integer_type_node
, e
,
8094 gfc_add_modify (&block
, e
, fold_build2_loc (input_location
, MAX_EXPR
,
8095 integer_type_node
, tmp
, emin
));
8097 tmp
= build_call_expr_loc (input_location
, scalbn
, 2,
8098 build_real_from_int_cst (type
, integer_one_node
), e
);
8099 gfc_add_modify (&block
, res
, tmp
);
8101 /* Finish by building the IF statement for value zero. */
8102 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, arg
,
8103 build_real_from_int_cst (type
, integer_zero_node
));
8104 tmp
= build3_v (COND_EXPR
, cond
, build2_v (MODIFY_EXPR
, res
, tiny
),
8105 gfc_finish_block (&block
));
8107 /* And deal with infinities and NaNs. */
8108 cond
= build_call_expr_loc (input_location
,
8109 builtin_decl_explicit (BUILT_IN_ISFINITE
),
8111 nan
= gfc_build_nan (type
, "");
8112 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build2_v (MODIFY_EXPR
, res
, nan
));
8114 gfc_add_expr_to_block (&se
->pre
, tmp
);
8119 /* RRSPACING (s) is translated into
8128 x = scalbn (x, precision - e);
8135 where precision is gfc_real_kinds[k].digits. */
8138 gfc_conv_intrinsic_rrspacing (gfc_se
* se
, gfc_expr
* expr
)
8140 tree arg
, type
, e
, x
, cond
, nan
, stmt
, tmp
, frexp
, scalbn
, fabs
;
8144 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
8145 prec
= gfc_real_kinds
[k
].digits
;
8147 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
8148 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
8149 fabs
= gfc_builtin_decl_for_float_kind (BUILT_IN_FABS
, expr
->ts
.kind
);
8151 type
= gfc_typenode_for_spec (&expr
->ts
);
8152 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
8153 arg
= gfc_evaluate_now (arg
, &se
->pre
);
8155 e
= gfc_create_var (integer_type_node
, NULL
);
8156 x
= gfc_create_var (type
, NULL
);
8157 gfc_add_modify (&se
->pre
, x
,
8158 build_call_expr_loc (input_location
, fabs
, 1, arg
));
8161 gfc_start_block (&block
);
8162 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
8163 gfc_build_addr_expr (NULL_TREE
, e
));
8164 gfc_add_expr_to_block (&block
, tmp
);
8166 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, integer_type_node
,
8167 build_int_cst (integer_type_node
, prec
), e
);
8168 tmp
= build_call_expr_loc (input_location
, scalbn
, 2, x
, tmp
);
8169 gfc_add_modify (&block
, x
, tmp
);
8170 stmt
= gfc_finish_block (&block
);
8173 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, x
,
8174 build_real_from_int_cst (type
, integer_zero_node
));
8175 tmp
= build3_v (COND_EXPR
, cond
, stmt
, build_empty_stmt (input_location
));
8177 /* And deal with infinities and NaNs. */
8178 cond
= build_call_expr_loc (input_location
,
8179 builtin_decl_explicit (BUILT_IN_ISFINITE
),
8181 nan
= gfc_build_nan (type
, "");
8182 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build2_v (MODIFY_EXPR
, x
, nan
));
8184 gfc_add_expr_to_block (&se
->pre
, tmp
);
8185 se
->expr
= fold_convert (type
, x
);
8189 /* SCALE (s, i) is translated into scalbn (s, i). */
8191 gfc_conv_intrinsic_scale (gfc_se
* se
, gfc_expr
* expr
)
8193 tree args
[2], type
, scalbn
;
8195 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
8197 type
= gfc_typenode_for_spec (&expr
->ts
);
8198 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
8199 se
->expr
= build_call_expr_loc (input_location
, scalbn
, 2,
8200 fold_convert (type
, args
[0]),
8201 fold_convert (integer_type_node
, args
[1]));
8202 se
->expr
= fold_convert (type
, se
->expr
);
8206 /* SET_EXPONENT (s, i) is translated into
8207 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
8209 gfc_conv_intrinsic_set_exponent (gfc_se
* se
, gfc_expr
* expr
)
8211 tree args
[2], type
, tmp
, frexp
, scalbn
, cond
, nan
, res
;
8213 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
8214 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
8216 type
= gfc_typenode_for_spec (&expr
->ts
);
8217 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
8218 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
8220 tmp
= gfc_create_var (integer_type_node
, NULL
);
8221 tmp
= build_call_expr_loc (input_location
, frexp
, 2,
8222 fold_convert (type
, args
[0]),
8223 gfc_build_addr_expr (NULL_TREE
, tmp
));
8224 res
= build_call_expr_loc (input_location
, scalbn
, 2, tmp
,
8225 fold_convert (integer_type_node
, args
[1]));
8226 res
= fold_convert (type
, res
);
8228 /* Call to isfinite */
8229 cond
= build_call_expr_loc (input_location
,
8230 builtin_decl_explicit (BUILT_IN_ISFINITE
),
8232 nan
= gfc_build_nan (type
, "");
8234 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
8240 gfc_conv_intrinsic_size (gfc_se
* se
, gfc_expr
* expr
)
8242 gfc_actual_arglist
*actual
;
8248 gfc_symbol
*sym
= NULL
;
8250 gfc_init_se (&argse
, NULL
);
8251 actual
= expr
->value
.function
.actual
;
8253 if (actual
->expr
->ts
.type
== BT_CLASS
)
8254 gfc_add_class_array_ref (actual
->expr
);
8258 /* These are emerging from the interface mapping, when a class valued
8259 function appears as the rhs in a realloc on assign statement, where
8260 the size of the result is that of one of the actual arguments. */
8261 if (e
->expr_type
== EXPR_VARIABLE
8262 && e
->symtree
->n
.sym
->ns
== NULL
/* This is distinctive! */
8263 && e
->symtree
->n
.sym
->ts
.type
== BT_CLASS
8264 && e
->ref
&& e
->ref
->type
== REF_COMPONENT
8265 && strcmp (e
->ref
->u
.c
.component
->name
, "_data") == 0)
8266 sym
= e
->symtree
->n
.sym
;
8268 if ((gfc_option
.rtcheck
& GFC_RTCHECK_POINTER
)
8270 && (e
->expr_type
== EXPR_VARIABLE
|| e
->expr_type
== EXPR_FUNCTION
))
8272 symbol_attribute attr
;
8277 if (e
->symtree
->n
.sym
&& IS_CLASS_ARRAY (e
->symtree
->n
.sym
))
8279 attr
= CLASS_DATA (e
->symtree
->n
.sym
)->attr
;
8280 attr
.pointer
= attr
.class_pointer
;
8283 attr
= gfc_expr_attr (e
);
8285 if (attr
.allocatable
)
8286 msg
= xasprintf ("Allocatable argument '%s' is not allocated",
8287 e
->symtree
->n
.sym
->name
);
8288 else if (attr
.pointer
)
8289 msg
= xasprintf ("Pointer argument '%s' is not associated",
8290 e
->symtree
->n
.sym
->name
);
8296 temp
= gfc_class_data_get (sym
->backend_decl
);
8297 temp
= gfc_conv_descriptor_data_get (temp
);
8301 argse
.descriptor_only
= 1;
8302 gfc_conv_expr_descriptor (&argse
, actual
->expr
);
8303 temp
= gfc_conv_descriptor_data_get (argse
.expr
);
8306 cond
= fold_build2_loc (input_location
, EQ_EXPR
,
8307 logical_type_node
, temp
,
8308 fold_convert (TREE_TYPE (temp
),
8309 null_pointer_node
));
8310 gfc_trans_runtime_check (true, false, cond
, &argse
.pre
, &e
->where
, msg
);
8316 argse
.data_not_needed
= 1;
8317 if (gfc_is_class_array_function (e
))
8319 /* For functions that return a class array conv_expr_descriptor is not
8320 able to get the descriptor right. Therefore this special case. */
8321 gfc_conv_expr_reference (&argse
, e
);
8322 argse
.expr
= gfc_class_data_get (argse
.expr
);
8324 else if (sym
&& sym
->backend_decl
)
8326 gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (sym
->backend_decl
)));
8327 argse
.expr
= gfc_class_data_get (sym
->backend_decl
);
8330 gfc_conv_expr_descriptor (&argse
, actual
->expr
);
8331 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8332 gfc_add_block_to_block (&se
->post
, &argse
.post
);
8335 actual
= actual
->next
;
8339 gfc_init_block (&block
);
8340 gfc_init_se (&argse
, NULL
);
8341 gfc_conv_expr_type (&argse
, actual
->expr
,
8342 gfc_array_index_type
);
8343 gfc_add_block_to_block (&block
, &argse
.pre
);
8344 tree tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
8345 argse
.expr
, gfc_index_one_node
);
8346 size
= gfc_tree_array_size (&block
, arg1
, e
, tmp
);
8348 /* Unusually, for an intrinsic, size does not exclude
8349 an optional arg2, so we must test for it. */
8350 if (actual
->expr
->expr_type
== EXPR_VARIABLE
8351 && actual
->expr
->symtree
->n
.sym
->attr
.dummy
8352 && actual
->expr
->symtree
->n
.sym
->attr
.optional
)
8356 gfc_init_block (&block2
);
8357 gfc_init_se (&argse
, NULL
);
8358 argse
.want_pointer
= 1;
8359 argse
.data_not_needed
= 1;
8360 gfc_conv_expr (&argse
, actual
->expr
);
8361 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8362 /* 'block2' contains the arg2 absent case, 'block' the arg2 present
8363 case; size_var can be used in both blocks. */
8364 tree size_var
= gfc_create_var (TREE_TYPE (size
), "size");
8365 tmp
= fold_build2_loc (input_location
, MODIFY_EXPR
,
8366 TREE_TYPE (size_var
), size_var
, size
);
8367 gfc_add_expr_to_block (&block
, tmp
);
8368 size
= gfc_tree_array_size (&block2
, arg1
, e
, NULL_TREE
);
8369 tmp
= fold_build2_loc (input_location
, MODIFY_EXPR
,
8370 TREE_TYPE (size_var
), size_var
, size
);
8371 gfc_add_expr_to_block (&block2
, tmp
);
8372 cond
= gfc_conv_expr_present (actual
->expr
->symtree
->n
.sym
);
8373 tmp
= build3_v (COND_EXPR
, cond
, gfc_finish_block (&block
),
8374 gfc_finish_block (&block2
));
8375 gfc_add_expr_to_block (&se
->pre
, tmp
);
8379 gfc_add_block_to_block (&se
->pre
, &block
);
8382 size
= gfc_tree_array_size (&se
->pre
, arg1
, e
, NULL_TREE
);
8383 type
= gfc_typenode_for_spec (&expr
->ts
);
8384 se
->expr
= convert (type
, size
);
8388 /* Helper function to compute the size of a character variable,
8389 excluding the terminating null characters. The result has
8390 gfc_array_index_type type. */
8393 size_of_string_in_bytes (int kind
, tree string_length
)
8396 int i
= gfc_validate_kind (BT_CHARACTER
, kind
, false);
8398 bytesize
= build_int_cst (gfc_array_index_type
,
8399 gfc_character_kinds
[i
].bit_size
/ 8);
8401 return fold_build2_loc (input_location
, MULT_EXPR
, gfc_array_index_type
,
8403 fold_convert (gfc_array_index_type
, string_length
));
8408 gfc_conv_intrinsic_sizeof (gfc_se
*se
, gfc_expr
*expr
)
8420 gfc_init_se (&argse
, NULL
);
8421 arg
= expr
->value
.function
.actual
->expr
;
8423 if (arg
->rank
|| arg
->ts
.type
== BT_ASSUMED
)
8424 gfc_conv_expr_descriptor (&argse
, arg
);
8426 gfc_conv_expr_reference (&argse
, arg
);
8428 if (arg
->ts
.type
== BT_ASSUMED
)
8430 /* This only works if an array descriptor has been passed; thus, extract
8431 the size from the descriptor. */
8432 gcc_assert (TYPE_PRECISION (gfc_array_index_type
)
8433 == TYPE_PRECISION (size_type_node
));
8434 tmp
= arg
->symtree
->n
.sym
->backend_decl
;
8435 tmp
= DECL_LANG_SPECIFIC (tmp
)
8436 && GFC_DECL_SAVED_DESCRIPTOR (tmp
) != NULL_TREE
8437 ? GFC_DECL_SAVED_DESCRIPTOR (tmp
) : tmp
;
8438 if (POINTER_TYPE_P (TREE_TYPE (tmp
)))
8439 tmp
= build_fold_indirect_ref_loc (input_location
, tmp
);
8441 tmp
= gfc_conv_descriptor_dtype (tmp
);
8442 field
= gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
8443 GFC_DTYPE_ELEM_LEN
);
8444 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
8445 tmp
, field
, NULL_TREE
);
8447 byte_size
= fold_convert (gfc_array_index_type
, tmp
);
8449 else if (arg
->ts
.type
== BT_CLASS
)
8451 /* Conv_expr_descriptor returns a component_ref to _data component of the
8452 class object. The class object may be a non-pointer object, e.g.
8453 located on the stack, or a memory location pointed to, e.g. a
8454 parameter, i.e., an indirect_ref. */
8455 if (POINTER_TYPE_P (TREE_TYPE (argse
.expr
))
8456 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (argse
.expr
))))
8458 = gfc_class_vtab_size_get (build_fold_indirect_ref (argse
.expr
));
8459 else if (GFC_CLASS_TYPE_P (TREE_TYPE (argse
.expr
)))
8460 byte_size
= gfc_class_vtab_size_get (argse
.expr
);
8461 else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (argse
.expr
))
8462 && TREE_CODE (argse
.expr
) == COMPONENT_REF
)
8463 byte_size
= gfc_class_vtab_size_get (TREE_OPERAND (argse
.expr
, 0));
8464 else if (arg
->rank
> 0
8466 && arg
->ref
&& arg
->ref
->type
== REF_COMPONENT
))
8468 /* The scalarizer added an additional temp. To get the class' vptr
8469 one has to look at the original backend_decl. */
8470 if (argse
.class_container
)
8471 byte_size
= gfc_class_vtab_size_get (argse
.class_container
);
8472 else if (DECL_LANG_SPECIFIC (arg
->symtree
->n
.sym
->backend_decl
))
8473 byte_size
= gfc_class_vtab_size_get (
8474 GFC_DECL_SAVED_DESCRIPTOR (arg
->symtree
->n
.sym
->backend_decl
));
8483 if (arg
->ts
.type
== BT_CHARACTER
)
8484 byte_size
= size_of_string_in_bytes (arg
->ts
.kind
, argse
.string_length
);
8488 byte_size
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
8491 byte_size
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
8492 byte_size
= fold_convert (gfc_array_index_type
,
8493 size_in_bytes (byte_size
));
8498 se
->expr
= byte_size
;
8501 source_bytes
= gfc_create_var (gfc_array_index_type
, "bytes");
8502 gfc_add_modify (&argse
.pre
, source_bytes
, byte_size
);
8504 if (arg
->rank
== -1)
8506 tree cond
, loop_var
, exit_label
;
8509 tmp
= fold_convert (gfc_array_index_type
,
8510 gfc_conv_descriptor_rank (argse
.expr
));
8511 loop_var
= gfc_create_var (gfc_array_index_type
, "i");
8512 gfc_add_modify (&argse
.pre
, loop_var
, gfc_index_zero_node
);
8513 exit_label
= gfc_build_label_decl (NULL_TREE
);
8520 source_bytes = source_bytes * array.dim[i].extent;
8524 gfc_start_block (&body
);
8525 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
8527 tmp
= build1_v (GOTO_EXPR
, exit_label
);
8528 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
8529 cond
, tmp
, build_empty_stmt (input_location
));
8530 gfc_add_expr_to_block (&body
, tmp
);
8532 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, loop_var
);
8533 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, loop_var
);
8534 tmp
= gfc_conv_array_extent_dim (lower
, upper
, NULL
);
8535 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
8536 gfc_array_index_type
, tmp
, source_bytes
);
8537 gfc_add_modify (&body
, source_bytes
, tmp
);
8539 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
8540 gfc_array_index_type
, loop_var
,
8541 gfc_index_one_node
);
8542 gfc_add_modify_loc (input_location
, &body
, loop_var
, tmp
);
8544 tmp
= gfc_finish_block (&body
);
8546 tmp
= fold_build1_loc (input_location
, LOOP_EXPR
, void_type_node
,
8548 gfc_add_expr_to_block (&argse
.pre
, tmp
);
8550 tmp
= build1_v (LABEL_EXPR
, exit_label
);
8551 gfc_add_expr_to_block (&argse
.pre
, tmp
);
8555 /* Obtain the size of the array in bytes. */
8556 for (n
= 0; n
< arg
->rank
; n
++)
8559 idx
= gfc_rank_cst
[n
];
8560 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, idx
);
8561 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, idx
);
8562 tmp
= gfc_conv_array_extent_dim (lower
, upper
, NULL
);
8563 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
8564 gfc_array_index_type
, tmp
, source_bytes
);
8565 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
8568 se
->expr
= source_bytes
;
8571 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8576 gfc_conv_intrinsic_storage_size (gfc_se
*se
, gfc_expr
*expr
)
8580 tree type
, result_type
, tmp
, class_decl
= NULL
;
8582 bool unlimited
= false;
8584 arg
= expr
->value
.function
.actual
->expr
;
8586 gfc_init_se (&argse
, NULL
);
8587 result_type
= gfc_get_int_type (expr
->ts
.kind
);
8591 if (arg
->ts
.type
== BT_CLASS
)
8593 unlimited
= UNLIMITED_POLY (arg
);
8594 gfc_add_vptr_component (arg
);
8595 gfc_add_size_component (arg
);
8596 gfc_conv_expr (&argse
, arg
);
8597 tmp
= fold_convert (result_type
, argse
.expr
);
8598 class_decl
= gfc_get_class_from_expr (argse
.expr
);
8602 gfc_conv_expr_reference (&argse
, arg
);
8603 type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
8608 argse
.want_pointer
= 0;
8609 gfc_conv_expr_descriptor (&argse
, arg
);
8610 sym
= arg
->expr_type
== EXPR_VARIABLE
? arg
->symtree
->n
.sym
: NULL
;
8611 if (arg
->ts
.type
== BT_CLASS
)
8613 unlimited
= UNLIMITED_POLY (arg
);
8614 if (TREE_CODE (argse
.expr
) == COMPONENT_REF
)
8615 tmp
= gfc_class_vtab_size_get (TREE_OPERAND (argse
.expr
, 0));
8616 else if (arg
->rank
> 0 && sym
8617 && DECL_LANG_SPECIFIC (sym
->backend_decl
))
8618 tmp
= gfc_class_vtab_size_get (
8619 GFC_DECL_SAVED_DESCRIPTOR (sym
->backend_decl
));
8622 tmp
= fold_convert (result_type
, tmp
);
8623 class_decl
= gfc_get_class_from_expr (argse
.expr
);
8626 type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
8629 /* Obtain the argument's word length. */
8630 if (arg
->ts
.type
== BT_CHARACTER
)
8631 tmp
= size_of_string_in_bytes (arg
->ts
.kind
, argse
.string_length
);
8633 tmp
= size_in_bytes (type
);
8634 tmp
= fold_convert (result_type
, tmp
);
8637 if (unlimited
&& class_decl
)
8638 tmp
= gfc_resize_class_size_with_len (NULL
, class_decl
, tmp
);
8640 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, result_type
, tmp
,
8641 build_int_cst (result_type
, BITS_PER_UNIT
));
8642 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8646 /* Intrinsic string comparison functions. */
8649 gfc_conv_intrinsic_strcmp (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
8653 gfc_conv_intrinsic_function_args (se
, expr
, args
, 4);
8656 = gfc_build_compare_string (args
[0], args
[1], args
[2], args
[3],
8657 expr
->value
.function
.actual
->expr
->ts
.kind
,
8659 se
->expr
= fold_build2_loc (input_location
, op
,
8660 gfc_typenode_for_spec (&expr
->ts
), se
->expr
,
8661 build_int_cst (TREE_TYPE (se
->expr
), 0));
8664 /* Generate a call to the adjustl/adjustr library function. */
8666 gfc_conv_intrinsic_adjust (gfc_se
* se
, gfc_expr
* expr
, tree fndecl
)
8674 gfc_conv_intrinsic_function_args (se
, expr
, &args
[1], 2);
8677 type
= TREE_TYPE (args
[2]);
8678 var
= gfc_conv_string_tmp (se
, type
, len
);
8681 tmp
= build_call_expr_loc (input_location
,
8682 fndecl
, 3, args
[0], args
[1], args
[2]);
8683 gfc_add_expr_to_block (&se
->pre
, tmp
);
8685 se
->string_length
= len
;
8689 /* Generate code for the TRANSFER intrinsic:
8691 DEST = TRANSFER (SOURCE, MOLD)
8693 typeof<DEST> = typeof<MOLD>
8698 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
8700 typeof<DEST> = typeof<MOLD>
8702 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
8703 sizeof (DEST(0) * SIZE). */
8705 gfc_conv_intrinsic_transfer (gfc_se
* se
, gfc_expr
* expr
)
8721 tree class_ref
= NULL_TREE
;
8722 gfc_actual_arglist
*arg
;
8724 gfc_array_info
*info
;
8728 gfc_expr
*source_expr
, *mold_expr
, *class_expr
;
8732 info
= &se
->ss
->info
->data
.array
;
8734 /* Convert SOURCE. The output from this stage is:-
8735 source_bytes = length of the source in bytes
8736 source = pointer to the source data. */
8737 arg
= expr
->value
.function
.actual
;
8738 source_expr
= arg
->expr
;
8740 /* Ensure double transfer through LOGICAL preserves all
8742 if (arg
->expr
->expr_type
== EXPR_FUNCTION
8743 && arg
->expr
->value
.function
.esym
== NULL
8744 && arg
->expr
->value
.function
.isym
!= NULL
8745 && arg
->expr
->value
.function
.isym
->id
== GFC_ISYM_TRANSFER
8746 && arg
->expr
->ts
.type
== BT_LOGICAL
8747 && expr
->ts
.type
!= arg
->expr
->ts
.type
)
8748 arg
->expr
->value
.function
.name
= "__transfer_in_transfer";
8750 gfc_init_se (&argse
, NULL
);
8752 source_bytes
= gfc_create_var (gfc_array_index_type
, NULL
);
8754 /* Obtain the pointer to source and the length of source in bytes. */
8755 if (arg
->expr
->rank
== 0)
8757 gfc_conv_expr_reference (&argse
, arg
->expr
);
8758 if (arg
->expr
->ts
.type
== BT_CLASS
)
8760 tmp
= build_fold_indirect_ref_loc (input_location
, argse
.expr
);
8761 if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp
)))
8763 source
= gfc_class_data_get (tmp
);
8768 /* Array elements are evaluated as a reference to the data.
8769 To obtain the vptr for the element size, the argument
8770 expression must be stripped to the class reference and
8771 re-evaluated. The pre and post blocks are not needed. */
8772 gcc_assert (arg
->expr
->expr_type
== EXPR_VARIABLE
);
8773 source
= argse
.expr
;
8774 class_expr
= gfc_find_and_cut_at_last_class_ref (arg
->expr
);
8775 gfc_init_se (&argse
, NULL
);
8776 gfc_conv_expr (&argse
, class_expr
);
8777 class_ref
= argse
.expr
;
8781 source
= argse
.expr
;
8783 /* Obtain the source word length. */
8784 switch (arg
->expr
->ts
.type
)
8787 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
,
8788 argse
.string_length
);
8791 if (class_ref
!= NULL_TREE
)
8793 tmp
= gfc_class_vtab_size_get (class_ref
);
8794 if (UNLIMITED_POLY (source_expr
))
8795 tmp
= gfc_resize_class_size_with_len (NULL
, class_ref
, tmp
);
8799 tmp
= gfc_class_vtab_size_get (argse
.expr
);
8800 if (UNLIMITED_POLY (source_expr
))
8801 tmp
= gfc_resize_class_size_with_len (NULL
, argse
.expr
, tmp
);
8805 source_type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
8807 tmp
= fold_convert (gfc_array_index_type
,
8808 size_in_bytes (source_type
));
8814 argse
.want_pointer
= 0;
8815 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
8816 source
= gfc_conv_descriptor_data_get (argse
.expr
);
8817 source_type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
8819 /* Repack the source if not simply contiguous. */
8820 if (!gfc_is_simply_contiguous (arg
->expr
, false, true))
8822 tmp
= gfc_build_addr_expr (NULL_TREE
, argse
.expr
);
8824 if (warn_array_temporaries
)
8825 gfc_warning (OPT_Warray_temporaries
,
8826 "Creating array temporary at %L", &expr
->where
);
8828 source
= build_call_expr_loc (input_location
,
8829 gfor_fndecl_in_pack
, 1, tmp
);
8830 source
= gfc_evaluate_now (source
, &argse
.pre
);
8832 /* Free the temporary. */
8833 gfc_start_block (&block
);
8834 tmp
= gfc_call_free (source
);
8835 gfc_add_expr_to_block (&block
, tmp
);
8836 stmt
= gfc_finish_block (&block
);
8838 /* Clean up if it was repacked. */
8839 gfc_init_block (&block
);
8840 tmp
= gfc_conv_array_data (argse
.expr
);
8841 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
8843 tmp
= build3_v (COND_EXPR
, tmp
, stmt
,
8844 build_empty_stmt (input_location
));
8845 gfc_add_expr_to_block (&block
, tmp
);
8846 gfc_add_block_to_block (&block
, &se
->post
);
8847 gfc_init_block (&se
->post
);
8848 gfc_add_block_to_block (&se
->post
, &block
);
8851 /* Obtain the source word length. */
8852 if (arg
->expr
->ts
.type
== BT_CHARACTER
)
8853 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
,
8854 argse
.string_length
);
8855 else if (arg
->expr
->ts
.type
== BT_CLASS
)
8857 class_ref
= TREE_OPERAND (argse
.expr
, 0);
8858 tmp
= gfc_class_vtab_size_get (class_ref
);
8859 if (UNLIMITED_POLY (arg
->expr
))
8860 tmp
= gfc_resize_class_size_with_len (&argse
.pre
, class_ref
, tmp
);
8863 tmp
= fold_convert (gfc_array_index_type
,
8864 size_in_bytes (source_type
));
8866 /* Obtain the size of the array in bytes. */
8867 extent
= gfc_create_var (gfc_array_index_type
, NULL
);
8868 for (n
= 0; n
< arg
->expr
->rank
; n
++)
8871 idx
= gfc_rank_cst
[n
];
8872 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
8873 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, idx
);
8874 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, idx
);
8875 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
8876 gfc_array_index_type
, upper
, lower
);
8877 gfc_add_modify (&argse
.pre
, extent
, tmp
);
8878 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
8879 gfc_array_index_type
, extent
,
8880 gfc_index_one_node
);
8881 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
8882 gfc_array_index_type
, tmp
, source_bytes
);
8886 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
8887 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8888 gfc_add_block_to_block (&se
->post
, &argse
.post
);
8890 /* Now convert MOLD. The outputs are:
8891 mold_type = the TREE type of MOLD
8892 dest_word_len = destination word length in bytes. */
8894 mold_expr
= arg
->expr
;
8896 gfc_init_se (&argse
, NULL
);
8898 scalar_mold
= arg
->expr
->rank
== 0;
8900 if (arg
->expr
->rank
== 0)
8902 gfc_conv_expr_reference (&argse
, mold_expr
);
8903 mold_type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
8908 argse
.want_pointer
= 0;
8909 gfc_conv_expr_descriptor (&argse
, mold_expr
);
8910 mold_type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
8913 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8914 gfc_add_block_to_block (&se
->post
, &argse
.post
);
8916 if (strcmp (expr
->value
.function
.name
, "__transfer_in_transfer") == 0)
8918 /* If this TRANSFER is nested in another TRANSFER, use a type
8919 that preserves all bits. */
8920 if (mold_expr
->ts
.type
== BT_LOGICAL
)
8921 mold_type
= gfc_get_int_type (mold_expr
->ts
.kind
);
8924 /* Obtain the destination word length. */
8925 switch (mold_expr
->ts
.type
)
8928 tmp
= size_of_string_in_bytes (mold_expr
->ts
.kind
, argse
.string_length
);
8929 mold_type
= gfc_get_character_type_len (mold_expr
->ts
.kind
,
8930 argse
.string_length
);
8934 class_ref
= argse
.expr
;
8936 class_ref
= TREE_OPERAND (argse
.expr
, 0);
8937 tmp
= gfc_class_vtab_size_get (class_ref
);
8938 if (UNLIMITED_POLY (arg
->expr
))
8939 tmp
= gfc_resize_class_size_with_len (&argse
.pre
, class_ref
, tmp
);
8942 tmp
= fold_convert (gfc_array_index_type
, size_in_bytes (mold_type
));
8946 /* Do not fix dest_word_len if it is a variable, since the temporary can wind
8947 up being used before the assignment. */
8948 if (mold_expr
->ts
.type
== BT_CHARACTER
&& mold_expr
->ts
.deferred
)
8949 dest_word_len
= tmp
;
8952 dest_word_len
= gfc_create_var (gfc_array_index_type
, NULL
);
8953 gfc_add_modify (&se
->pre
, dest_word_len
, tmp
);
8956 /* Finally convert SIZE, if it is present. */
8958 size_words
= gfc_create_var (gfc_array_index_type
, NULL
);
8962 gfc_init_se (&argse
, NULL
);
8963 gfc_conv_expr_reference (&argse
, arg
->expr
);
8964 tmp
= convert (gfc_array_index_type
,
8965 build_fold_indirect_ref_loc (input_location
,
8967 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8968 gfc_add_block_to_block (&se
->post
, &argse
.post
);
8973 /* Separate array and scalar results. */
8974 if (scalar_mold
&& tmp
== NULL_TREE
)
8975 goto scalar_transfer
;
8977 size_bytes
= gfc_create_var (gfc_array_index_type
, NULL
);
8978 if (tmp
!= NULL_TREE
)
8979 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, gfc_array_index_type
,
8980 tmp
, dest_word_len
);
8984 gfc_add_modify (&se
->pre
, size_bytes
, tmp
);
8985 gfc_add_modify (&se
->pre
, size_words
,
8986 fold_build2_loc (input_location
, CEIL_DIV_EXPR
,
8987 gfc_array_index_type
,
8988 size_bytes
, dest_word_len
));
8990 /* Evaluate the bounds of the result. If the loop range exists, we have
8991 to check if it is too large. If so, we modify loop->to be consistent
8992 with min(size, size(source)). Otherwise, size is made consistent with
8993 the loop range, so that the right number of bytes is transferred.*/
8994 n
= se
->loop
->order
[0];
8995 if (se
->loop
->to
[n
] != NULL_TREE
)
8997 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
8998 se
->loop
->to
[n
], se
->loop
->from
[n
]);
8999 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
9000 tmp
, gfc_index_one_node
);
9001 tmp
= fold_build2_loc (input_location
, MIN_EXPR
, gfc_array_index_type
,
9003 gfc_add_modify (&se
->pre
, size_words
, tmp
);
9004 gfc_add_modify (&se
->pre
, size_bytes
,
9005 fold_build2_loc (input_location
, MULT_EXPR
,
9006 gfc_array_index_type
,
9007 size_words
, dest_word_len
));
9008 upper
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
9009 size_words
, se
->loop
->from
[n
]);
9010 upper
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
9011 upper
, gfc_index_one_node
);
9015 upper
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
9016 size_words
, gfc_index_one_node
);
9017 se
->loop
->from
[n
] = gfc_index_zero_node
;
9020 se
->loop
->to
[n
] = upper
;
9022 /* Build a destination descriptor, using the pointer, source, as the
9024 gfc_trans_create_temp_array (&se
->pre
, &se
->post
, se
->ss
, mold_type
,
9025 NULL_TREE
, false, true, false, &expr
->where
);
9027 /* Cast the pointer to the result. */
9028 tmp
= gfc_conv_descriptor_data_get (info
->descriptor
);
9029 tmp
= fold_convert (pvoid_type_node
, tmp
);
9031 /* Use memcpy to do the transfer. */
9033 = build_call_expr_loc (input_location
,
9034 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3, tmp
,
9035 fold_convert (pvoid_type_node
, source
),
9036 fold_convert (size_type_node
,
9037 fold_build2_loc (input_location
,
9039 gfc_array_index_type
,
9042 gfc_add_expr_to_block (&se
->pre
, tmp
);
9044 se
->expr
= info
->descriptor
;
9045 if (expr
->ts
.type
== BT_CHARACTER
)
9047 tmp
= fold_convert (gfc_charlen_type_node
,
9048 TYPE_SIZE_UNIT (gfc_get_char_type (expr
->ts
.kind
)));
9049 se
->string_length
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
9050 gfc_charlen_type_node
,
9051 dest_word_len
, tmp
);
9056 /* Deal with scalar results. */
9058 extent
= fold_build2_loc (input_location
, MIN_EXPR
, gfc_array_index_type
,
9059 dest_word_len
, source_bytes
);
9060 extent
= fold_build2_loc (input_location
, MAX_EXPR
, gfc_array_index_type
,
9061 extent
, gfc_index_zero_node
);
9063 if (expr
->ts
.type
== BT_CHARACTER
)
9065 tree direct
, indirect
, free
;
9067 ptr
= convert (gfc_get_pchar_type (expr
->ts
.kind
), source
);
9068 tmpdecl
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
),
9071 /* If source is longer than the destination, use a pointer to
9072 the source directly. */
9073 gfc_init_block (&block
);
9074 gfc_add_modify (&block
, tmpdecl
, ptr
);
9075 direct
= gfc_finish_block (&block
);
9077 /* Otherwise, allocate a string with the length of the destination
9078 and copy the source into it. */
9079 gfc_init_block (&block
);
9080 tmp
= gfc_get_pchar_type (expr
->ts
.kind
);
9081 tmp
= gfc_call_malloc (&block
, tmp
, dest_word_len
);
9082 gfc_add_modify (&block
, tmpdecl
,
9083 fold_convert (TREE_TYPE (ptr
), tmp
));
9084 tmp
= build_call_expr_loc (input_location
,
9085 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3,
9086 fold_convert (pvoid_type_node
, tmpdecl
),
9087 fold_convert (pvoid_type_node
, ptr
),
9088 fold_convert (size_type_node
, extent
));
9089 gfc_add_expr_to_block (&block
, tmp
);
9090 indirect
= gfc_finish_block (&block
);
9092 /* Wrap it up with the condition. */
9093 tmp
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
,
9094 dest_word_len
, source_bytes
);
9095 tmp
= build3_v (COND_EXPR
, tmp
, direct
, indirect
);
9096 gfc_add_expr_to_block (&se
->pre
, tmp
);
9098 /* Free the temporary string, if necessary. */
9099 free
= gfc_call_free (tmpdecl
);
9100 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
9101 dest_word_len
, source_bytes
);
9102 tmp
= build3_v (COND_EXPR
, tmp
, free
, build_empty_stmt (input_location
));
9103 gfc_add_expr_to_block (&se
->post
, tmp
);
9106 tmp
= fold_convert (gfc_charlen_type_node
,
9107 TYPE_SIZE_UNIT (gfc_get_char_type (expr
->ts
.kind
)));
9108 se
->string_length
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
9109 gfc_charlen_type_node
,
9110 dest_word_len
, tmp
);
9114 tmpdecl
= gfc_create_var (mold_type
, "transfer");
9116 ptr
= convert (build_pointer_type (mold_type
), source
);
9118 /* For CLASS results, allocate the needed memory first. */
9119 if (mold_expr
->ts
.type
== BT_CLASS
)
9122 cdata
= gfc_class_data_get (tmpdecl
);
9123 tmp
= gfc_call_malloc (&se
->pre
, TREE_TYPE (cdata
), dest_word_len
);
9124 gfc_add_modify (&se
->pre
, cdata
, tmp
);
9127 /* Use memcpy to do the transfer. */
9128 if (mold_expr
->ts
.type
== BT_CLASS
)
9129 tmp
= gfc_class_data_get (tmpdecl
);
9131 tmp
= gfc_build_addr_expr (NULL_TREE
, tmpdecl
);
9133 tmp
= build_call_expr_loc (input_location
,
9134 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3,
9135 fold_convert (pvoid_type_node
, tmp
),
9136 fold_convert (pvoid_type_node
, ptr
),
9137 fold_convert (size_type_node
, extent
));
9138 gfc_add_expr_to_block (&se
->pre
, tmp
);
9140 /* For CLASS results, set the _vptr. */
9141 if (mold_expr
->ts
.type
== BT_CLASS
)
9142 gfc_reset_vptr (&se
->pre
, nullptr, tmpdecl
, source_expr
->ts
.u
.derived
);
9149 /* Generate a call to caf_is_present. */
9152 trans_caf_is_present (gfc_se
*se
, gfc_expr
*expr
)
9154 tree caf_reference
, caf_decl
, token
, image_index
;
9156 /* Compile the reference chain. */
9157 caf_reference
= conv_expr_ref_to_caf_ref (&se
->pre
, expr
);
9158 gcc_assert (caf_reference
!= NULL_TREE
);
9160 caf_decl
= gfc_get_tree_for_caf_expr (expr
);
9161 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
9162 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
9163 image_index
= gfc_caf_get_image_index (&se
->pre
, expr
, caf_decl
);
9164 gfc_get_caf_token_offset (se
, &token
, NULL
, caf_decl
, NULL
,
9167 return build_call_expr_loc (input_location
, gfor_fndecl_caf_is_present
,
9168 3, token
, image_index
, caf_reference
);
9172 /* Test whether this ref-chain refs this image only. */
9175 caf_this_image_ref (gfc_ref
*ref
)
9177 for ( ; ref
; ref
= ref
->next
)
9178 if (ref
->type
== REF_ARRAY
&& ref
->u
.ar
.codimen
)
9179 return ref
->u
.ar
.dimen_type
[ref
->u
.ar
.dimen
] == DIMEN_THIS_IMAGE
;
9185 /* Generate code for the ALLOCATED intrinsic.
9186 Generate inline code that directly check the address of the argument. */
9189 gfc_conv_allocated (gfc_se
*se
, gfc_expr
*expr
)
9193 bool coindexed_caf_comp
= false;
9194 gfc_expr
*e
= expr
->value
.function
.actual
->expr
;
9196 gfc_init_se (&arg1se
, NULL
);
9197 if (e
->ts
.type
== BT_CLASS
)
9199 /* Make sure that class array expressions have both a _data
9200 component reference and an array reference.... */
9201 if (CLASS_DATA (e
)->attr
.dimension
)
9202 gfc_add_class_array_ref (e
);
9203 /* .... whilst scalars only need the _data component. */
9205 gfc_add_data_component (e
);
9208 /* When 'e' references an allocatable component in a coarray, then call
9209 the caf-library function caf_is_present (). */
9210 if (flag_coarray
== GFC_FCOARRAY_LIB
&& e
->expr_type
== EXPR_FUNCTION
9211 && e
->value
.function
.isym
9212 && e
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
9214 e
= e
->value
.function
.actual
->expr
;
9215 if (gfc_expr_attr (e
).codimension
)
9217 /* Last partref is the coindexed coarray. As coarrays are collectively
9218 (de)allocated, the allocation status must be the same as the one of
9219 the local allocation. Convert to local access. */
9220 for (gfc_ref
*ref
= e
->ref
; ref
; ref
= ref
->next
)
9221 if (ref
->type
== REF_ARRAY
&& ref
->u
.ar
.codimen
)
9223 for (int i
= ref
->u
.ar
.dimen
;
9224 i
< ref
->u
.ar
.dimen
+ ref
->u
.ar
.codimen
; ++i
)
9225 ref
->u
.ar
.dimen_type
[i
] = DIMEN_THIS_IMAGE
;
9229 else if (!caf_this_image_ref (e
->ref
))
9230 coindexed_caf_comp
= true;
9232 if (coindexed_caf_comp
)
9233 tmp
= trans_caf_is_present (se
, e
);
9238 /* Allocatable scalar. */
9239 arg1se
.want_pointer
= 1;
9240 gfc_conv_expr (&arg1se
, e
);
9245 /* Allocatable array. */
9246 arg1se
.descriptor_only
= 1;
9247 gfc_conv_expr_descriptor (&arg1se
, e
);
9248 tmp
= gfc_conv_descriptor_data_get (arg1se
.expr
);
9251 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, tmp
,
9252 fold_convert (TREE_TYPE (tmp
), null_pointer_node
));
9255 /* Components of pointer array references sometimes come back with a pre block. */
9256 if (arg1se
.pre
.head
)
9257 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
9259 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), tmp
);
9263 /* Generate code for the ASSOCIATED intrinsic.
9264 If both POINTER and TARGET are arrays, generate a call to library function
9265 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
9266 In other cases, generate inline code that directly compare the address of
9267 POINTER with the address of TARGET. */
9270 gfc_conv_associated (gfc_se
*se
, gfc_expr
*expr
)
9272 gfc_actual_arglist
*arg1
;
9273 gfc_actual_arglist
*arg2
;
9278 tree nonzero_arraylen
= NULL_TREE
;
9282 gfc_init_se (&arg1se
, NULL
);
9283 gfc_init_se (&arg2se
, NULL
);
9284 arg1
= expr
->value
.function
.actual
;
9287 /* Check whether the expression is a scalar or not; we cannot use
9288 arg1->expr->rank as it can be nonzero for proc pointers. */
9289 ss
= gfc_walk_expr (arg1
->expr
);
9290 scalar
= ss
== gfc_ss_terminator
;
9292 gfc_free_ss_chain (ss
);
9296 /* No optional target. */
9299 /* A pointer to a scalar. */
9300 arg1se
.want_pointer
= 1;
9301 gfc_conv_expr (&arg1se
, arg1
->expr
);
9302 if (arg1
->expr
->symtree
->n
.sym
->attr
.proc_pointer
9303 && arg1
->expr
->symtree
->n
.sym
->attr
.dummy
)
9304 arg1se
.expr
= build_fold_indirect_ref_loc (input_location
,
9306 if (arg1
->expr
->ts
.type
== BT_CLASS
)
9308 tmp2
= gfc_class_data_get (arg1se
.expr
);
9309 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2
)))
9310 tmp2
= gfc_conv_descriptor_data_get (tmp2
);
9317 /* A pointer to an array. */
9318 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
9319 tmp2
= gfc_conv_descriptor_data_get (arg1se
.expr
);
9321 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
9322 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
9323 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, tmp2
,
9324 fold_convert (TREE_TYPE (tmp2
), null_pointer_node
));
9329 /* An optional target. */
9330 if (arg2
->expr
->ts
.type
== BT_CLASS
9331 && arg2
->expr
->expr_type
!= EXPR_FUNCTION
)
9332 gfc_add_data_component (arg2
->expr
);
9336 /* A pointer to a scalar. */
9337 arg1se
.want_pointer
= 1;
9338 gfc_conv_expr (&arg1se
, arg1
->expr
);
9339 if (arg1
->expr
->symtree
->n
.sym
->attr
.proc_pointer
9340 && arg1
->expr
->symtree
->n
.sym
->attr
.dummy
)
9341 arg1se
.expr
= build_fold_indirect_ref_loc (input_location
,
9343 if (arg1
->expr
->ts
.type
== BT_CLASS
)
9344 arg1se
.expr
= gfc_class_data_get (arg1se
.expr
);
9346 arg2se
.want_pointer
= 1;
9347 gfc_conv_expr (&arg2se
, arg2
->expr
);
9348 if (arg2
->expr
->symtree
->n
.sym
->attr
.proc_pointer
9349 && arg2
->expr
->symtree
->n
.sym
->attr
.dummy
)
9350 arg2se
.expr
= build_fold_indirect_ref_loc (input_location
,
9352 if (arg2
->expr
->ts
.type
== BT_CLASS
)
9354 arg2se
.expr
= gfc_evaluate_now (arg2se
.expr
, &arg2se
.pre
);
9355 arg2se
.expr
= gfc_class_data_get (arg2se
.expr
);
9357 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
9358 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
9359 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
9360 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
9361 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
9362 arg1se
.expr
, arg2se
.expr
);
9363 tmp2
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
9364 arg1se
.expr
, null_pointer_node
);
9365 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
9366 logical_type_node
, tmp
, tmp2
);
9370 /* An array pointer of zero length is not associated if target is
9372 arg1se
.descriptor_only
= 1;
9373 gfc_conv_expr_lhs (&arg1se
, arg1
->expr
);
9374 if (arg1
->expr
->rank
== -1)
9376 tmp
= gfc_conv_descriptor_rank (arg1se
.expr
);
9377 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
9378 TREE_TYPE (tmp
), tmp
,
9379 build_int_cst (TREE_TYPE (tmp
), 1));
9382 tmp
= gfc_rank_cst
[arg1
->expr
->rank
- 1];
9383 tmp
= gfc_conv_descriptor_stride_get (arg1se
.expr
, tmp
);
9384 if (arg2
->expr
->rank
!= 0)
9385 nonzero_arraylen
= fold_build2_loc (input_location
, NE_EXPR
,
9386 logical_type_node
, tmp
,
9387 build_int_cst (TREE_TYPE (tmp
), 0));
9389 /* A pointer to an array, call library function _gfor_associated. */
9390 arg1se
.want_pointer
= 1;
9391 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
9392 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
9393 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
9395 arg2se
.want_pointer
= 1;
9396 arg2se
.force_no_tmp
= 1;
9397 if (arg2
->expr
->rank
!= 0)
9398 gfc_conv_expr_descriptor (&arg2se
, arg2
->expr
);
9401 gfc_conv_expr (&arg2se
, arg2
->expr
);
9403 = gfc_conv_scalar_to_descriptor (&arg2se
, arg2se
.expr
,
9404 gfc_expr_attr (arg2
->expr
));
9405 arg2se
.expr
= gfc_build_addr_expr (NULL_TREE
, arg2se
.expr
);
9407 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
9408 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
9409 se
->expr
= build_call_expr_loc (input_location
,
9410 gfor_fndecl_associated
, 2,
9411 arg1se
.expr
, arg2se
.expr
);
9412 se
->expr
= convert (logical_type_node
, se
->expr
);
9413 if (arg2
->expr
->rank
!= 0)
9414 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
9415 logical_type_node
, se
->expr
,
9419 /* If target is present zero character length pointers cannot
9421 if (arg1
->expr
->ts
.type
== BT_CHARACTER
)
9423 tmp
= arg1se
.string_length
;
9424 tmp
= fold_build2_loc (input_location
, NE_EXPR
,
9425 logical_type_node
, tmp
,
9426 build_zero_cst (TREE_TYPE (tmp
)));
9427 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
9428 logical_type_node
, se
->expr
, tmp
);
9432 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
9436 /* Generate code for the SAME_TYPE_AS intrinsic.
9437 Generate inline code that directly checks the vindices. */
9440 gfc_conv_same_type_as (gfc_se
*se
, gfc_expr
*expr
)
9445 tree conda
= NULL_TREE
, condb
= NULL_TREE
;
9447 gfc_init_se (&se1
, NULL
);
9448 gfc_init_se (&se2
, NULL
);
9450 a
= expr
->value
.function
.actual
->expr
;
9451 b
= expr
->value
.function
.actual
->next
->expr
;
9453 bool unlimited_poly_a
= UNLIMITED_POLY (a
);
9454 bool unlimited_poly_b
= UNLIMITED_POLY (b
);
9455 if (unlimited_poly_a
)
9457 se1
.want_pointer
= 1;
9458 gfc_add_vptr_component (a
);
9460 else if (a
->ts
.type
== BT_CLASS
)
9462 gfc_add_vptr_component (a
);
9463 gfc_add_hash_component (a
);
9465 else if (a
->ts
.type
== BT_DERIVED
)
9466 a
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
,
9467 a
->ts
.u
.derived
->hash_value
);
9469 if (unlimited_poly_b
)
9471 se2
.want_pointer
= 1;
9472 gfc_add_vptr_component (b
);
9474 else if (b
->ts
.type
== BT_CLASS
)
9476 gfc_add_vptr_component (b
);
9477 gfc_add_hash_component (b
);
9479 else if (b
->ts
.type
== BT_DERIVED
)
9480 b
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
,
9481 b
->ts
.u
.derived
->hash_value
);
9483 gfc_conv_expr (&se1
, a
);
9484 gfc_conv_expr (&se2
, b
);
9486 if (unlimited_poly_a
)
9488 conda
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
9490 build_int_cst (TREE_TYPE (se1
.expr
), 0));
9491 se1
.expr
= gfc_vptr_hash_get (se1
.expr
);
9494 if (unlimited_poly_b
)
9496 condb
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
9498 build_int_cst (TREE_TYPE (se2
.expr
), 0));
9499 se2
.expr
= gfc_vptr_hash_get (se2
.expr
);
9502 tmp
= fold_build2_loc (input_location
, EQ_EXPR
,
9503 logical_type_node
, se1
.expr
,
9504 fold_convert (TREE_TYPE (se1
.expr
), se2
.expr
));
9507 tmp
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
9508 logical_type_node
, conda
, tmp
);
9511 tmp
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
9512 logical_type_node
, condb
, tmp
);
9514 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), tmp
);
9518 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
9521 gfc_conv_intrinsic_sc_kind (gfc_se
*se
, gfc_expr
*expr
)
9525 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
9526 se
->expr
= build_call_expr_loc (input_location
,
9527 gfor_fndecl_sc_kind
, 2, args
[0], args
[1]);
9528 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
9532 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
9535 gfc_conv_intrinsic_si_kind (gfc_se
*se
, gfc_expr
*expr
)
9539 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
9541 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
9542 type
= gfc_get_int_type (4);
9543 arg
= gfc_build_addr_expr (NULL_TREE
, fold_convert (type
, arg
));
9545 /* Convert it to the required type. */
9546 type
= gfc_typenode_for_spec (&expr
->ts
);
9547 se
->expr
= build_call_expr_loc (input_location
,
9548 gfor_fndecl_si_kind
, 1, arg
);
9549 se
->expr
= fold_convert (type
, se
->expr
);
9553 /* Generate code for SELECTED_LOGICAL_KIND (BITS) intrinsic function. */
9556 gfc_conv_intrinsic_sl_kind (gfc_se
*se
, gfc_expr
*expr
)
9560 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
9562 /* The argument to SELECTED_LOGICAL_KIND is INTEGER(4). */
9563 type
= gfc_get_int_type (4);
9564 arg
= gfc_build_addr_expr (NULL_TREE
, fold_convert (type
, arg
));
9566 /* Convert it to the required type. */
9567 type
= gfc_typenode_for_spec (&expr
->ts
);
9568 se
->expr
= build_call_expr_loc (input_location
,
9569 gfor_fndecl_sl_kind
, 1, arg
);
9570 se
->expr
= fold_convert (type
, se
->expr
);
9574 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
9577 gfc_conv_intrinsic_sr_kind (gfc_se
*se
, gfc_expr
*expr
)
9579 gfc_actual_arglist
*actual
;
9582 vec
<tree
, va_gc
> *args
= NULL
;
9584 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
9586 gfc_init_se (&argse
, se
);
9588 /* Pass a NULL pointer for an absent arg. */
9589 if (actual
->expr
== NULL
)
9590 argse
.expr
= null_pointer_node
;
9596 if (actual
->expr
->ts
.kind
!= gfc_c_int_kind
)
9598 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
9599 ts
.type
= BT_INTEGER
;
9600 ts
.kind
= gfc_c_int_kind
;
9601 gfc_convert_type (actual
->expr
, &ts
, 2);
9603 gfc_conv_expr_reference (&argse
, actual
->expr
);
9606 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
9607 gfc_add_block_to_block (&se
->post
, &argse
.post
);
9608 vec_safe_push (args
, argse
.expr
);
9611 /* Convert it to the required type. */
9612 type
= gfc_typenode_for_spec (&expr
->ts
);
9613 se
->expr
= build_call_expr_loc_vec (input_location
,
9614 gfor_fndecl_sr_kind
, args
);
9615 se
->expr
= fold_convert (type
, se
->expr
);
9619 /* Generate code for TRIM (A) intrinsic function. */
9622 gfc_conv_intrinsic_trim (gfc_se
* se
, gfc_expr
* expr
)
9632 unsigned int num_args
;
9634 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
9635 args
= XALLOCAVEC (tree
, num_args
);
9637 var
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
), "pstr");
9638 addr
= gfc_build_addr_expr (ppvoid_type_node
, var
);
9639 len
= gfc_create_var (gfc_charlen_type_node
, "len");
9641 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
9642 args
[0] = gfc_build_addr_expr (NULL_TREE
, len
);
9645 if (expr
->ts
.kind
== 1)
9646 function
= gfor_fndecl_string_trim
;
9647 else if (expr
->ts
.kind
== 4)
9648 function
= gfor_fndecl_string_trim_char4
;
9652 fndecl
= build_addr (function
);
9653 tmp
= build_call_array_loc (input_location
,
9654 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
9656 gfc_add_expr_to_block (&se
->pre
, tmp
);
9658 /* Free the temporary afterwards, if necessary. */
9659 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
9660 len
, build_int_cst (TREE_TYPE (len
), 0));
9661 tmp
= gfc_call_free (var
);
9662 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
9663 gfc_add_expr_to_block (&se
->post
, tmp
);
9666 se
->string_length
= len
;
9670 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
9673 gfc_conv_intrinsic_repeat (gfc_se
* se
, gfc_expr
* expr
)
9675 tree args
[3], ncopies
, dest
, dlen
, src
, slen
, ncopies_type
;
9676 tree type
, cond
, tmp
, count
, exit_label
, n
, max
, largest
;
9678 stmtblock_t block
, body
;
9681 /* We store in charsize the size of a character. */
9682 i
= gfc_validate_kind (BT_CHARACTER
, expr
->ts
.kind
, false);
9683 size
= build_int_cst (sizetype
, gfc_character_kinds
[i
].bit_size
/ 8);
9685 /* Get the arguments. */
9686 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
9687 slen
= fold_convert (sizetype
, gfc_evaluate_now (args
[0], &se
->pre
));
9689 ncopies
= gfc_evaluate_now (args
[2], &se
->pre
);
9690 ncopies_type
= TREE_TYPE (ncopies
);
9692 /* Check that NCOPIES is not negative. */
9693 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
, ncopies
,
9694 build_int_cst (ncopies_type
, 0));
9695 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
9696 "Argument NCOPIES of REPEAT intrinsic is negative "
9697 "(its value is %ld)",
9698 fold_convert (long_integer_type_node
, ncopies
));
9700 /* If the source length is zero, any non negative value of NCOPIES
9701 is valid, and nothing happens. */
9702 n
= gfc_create_var (ncopies_type
, "ncopies");
9703 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, slen
,
9705 tmp
= fold_build3_loc (input_location
, COND_EXPR
, ncopies_type
, cond
,
9706 build_int_cst (ncopies_type
, 0), ncopies
);
9707 gfc_add_modify (&se
->pre
, n
, tmp
);
9710 /* Check that ncopies is not too large: ncopies should be less than
9711 (or equal to) MAX / slen, where MAX is the maximal integer of
9712 the gfc_charlen_type_node type. If slen == 0, we need a special
9713 case to avoid the division by zero. */
9714 max
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
, sizetype
,
9715 fold_convert (sizetype
,
9716 TYPE_MAX_VALUE (gfc_charlen_type_node
)),
9718 largest
= TYPE_PRECISION (sizetype
) > TYPE_PRECISION (ncopies_type
)
9719 ? sizetype
: ncopies_type
;
9720 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
9721 fold_convert (largest
, ncopies
),
9722 fold_convert (largest
, max
));
9723 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, slen
,
9725 cond
= fold_build3_loc (input_location
, COND_EXPR
, logical_type_node
, tmp
,
9726 logical_false_node
, cond
);
9727 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
9728 "Argument NCOPIES of REPEAT intrinsic is too large");
9730 /* Compute the destination length. */
9731 dlen
= fold_build2_loc (input_location
, MULT_EXPR
, gfc_charlen_type_node
,
9732 fold_convert (gfc_charlen_type_node
, slen
),
9733 fold_convert (gfc_charlen_type_node
, ncopies
));
9734 type
= gfc_get_character_type (expr
->ts
.kind
, expr
->ts
.u
.cl
);
9735 dest
= gfc_conv_string_tmp (se
, build_pointer_type (type
), dlen
);
9737 /* Generate the code to do the repeat operation:
9738 for (i = 0; i < ncopies; i++)
9739 memmove (dest + (i * slen * size), src, slen*size); */
9740 gfc_start_block (&block
);
9741 count
= gfc_create_var (sizetype
, "count");
9742 gfc_add_modify (&block
, count
, size_zero_node
);
9743 exit_label
= gfc_build_label_decl (NULL_TREE
);
9745 /* Start the loop body. */
9746 gfc_start_block (&body
);
9748 /* Exit the loop if count >= ncopies. */
9749 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, count
,
9750 fold_convert (sizetype
, ncopies
));
9751 tmp
= build1_v (GOTO_EXPR
, exit_label
);
9752 TREE_USED (exit_label
) = 1;
9753 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
, tmp
,
9754 build_empty_stmt (input_location
));
9755 gfc_add_expr_to_block (&body
, tmp
);
9757 /* Call memmove (dest + (i*slen*size), src, slen*size). */
9758 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, sizetype
, slen
,
9760 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, sizetype
, tmp
,
9762 tmp
= fold_build_pointer_plus_loc (input_location
,
9763 fold_convert (pvoid_type_node
, dest
), tmp
);
9764 tmp
= build_call_expr_loc (input_location
,
9765 builtin_decl_explicit (BUILT_IN_MEMMOVE
),
9767 fold_build2_loc (input_location
, MULT_EXPR
,
9768 size_type_node
, slen
, size
));
9769 gfc_add_expr_to_block (&body
, tmp
);
9771 /* Increment count. */
9772 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, sizetype
,
9773 count
, size_one_node
);
9774 gfc_add_modify (&body
, count
, tmp
);
9776 /* Build the loop. */
9777 tmp
= build1_v (LOOP_EXPR
, gfc_finish_block (&body
));
9778 gfc_add_expr_to_block (&block
, tmp
);
9780 /* Add the exit label. */
9781 tmp
= build1_v (LABEL_EXPR
, exit_label
);
9782 gfc_add_expr_to_block (&block
, tmp
);
9784 /* Finish the block. */
9785 tmp
= gfc_finish_block (&block
);
9786 gfc_add_expr_to_block (&se
->pre
, tmp
);
9788 /* Set the result value. */
9790 se
->string_length
= dlen
;
9794 /* Generate code for the IARGC intrinsic. */
9797 gfc_conv_intrinsic_iargc (gfc_se
* se
, gfc_expr
* expr
)
9803 /* Call the library function. This always returns an INTEGER(4). */
9804 fndecl
= gfor_fndecl_iargc
;
9805 tmp
= build_call_expr_loc (input_location
,
9808 /* Convert it to the required type. */
9809 type
= gfc_typenode_for_spec (&expr
->ts
);
9810 tmp
= fold_convert (type
, tmp
);
9816 /* Generate code for the KILL intrinsic. */
9819 conv_intrinsic_kill (gfc_se
*se
, gfc_expr
*expr
)
9822 tree int4_type_node
= gfc_get_int_type (4);
9826 unsigned int num_args
;
9828 num_args
= gfc_intrinsic_argument_list_length (expr
);
9829 args
= XALLOCAVEC (tree
, num_args
);
9830 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
9832 /* Convert PID to a INTEGER(4) entity. */
9833 pid
= convert (int4_type_node
, args
[0]);
9835 /* Convert SIG to a INTEGER(4) entity. */
9836 sig
= convert (int4_type_node
, args
[1]);
9838 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_kill
, 2, pid
, sig
);
9840 se
->expr
= fold_convert (TREE_TYPE (args
[0]), tmp
);
9845 conv_intrinsic_kill_sub (gfc_code
*code
)
9849 tree int4_type_node
= gfc_get_int_type (4);
9855 /* Make the function call. */
9856 gfc_init_block (&block
);
9857 gfc_init_se (&se
, NULL
);
9859 /* Convert PID to a INTEGER(4) entity. */
9860 gfc_conv_expr (&se
, code
->ext
.actual
->expr
);
9861 gfc_add_block_to_block (&block
, &se
.pre
);
9862 pid
= fold_convert (int4_type_node
, gfc_evaluate_now (se
.expr
, &block
));
9863 gfc_add_block_to_block (&block
, &se
.post
);
9865 /* Convert SIG to a INTEGER(4) entity. */
9866 gfc_conv_expr (&se
, code
->ext
.actual
->next
->expr
);
9867 gfc_add_block_to_block (&block
, &se
.pre
);
9868 sig
= fold_convert (int4_type_node
, gfc_evaluate_now (se
.expr
, &block
));
9869 gfc_add_block_to_block (&block
, &se
.post
);
9871 /* Deal with an optional STATUS. */
9872 if (code
->ext
.actual
->next
->next
->expr
)
9874 gfc_init_se (&se_stat
, NULL
);
9875 gfc_conv_expr (&se_stat
, code
->ext
.actual
->next
->next
->expr
);
9876 statp
= gfc_create_var (gfc_get_int_type (4), "_statp");
9881 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_kill_sub
, 3, pid
, sig
,
9882 statp
? gfc_build_addr_expr (NULL_TREE
, statp
) : null_pointer_node
);
9884 gfc_add_expr_to_block (&block
, tmp
);
9886 if (statp
&& statp
!= se_stat
.expr
)
9887 gfc_add_modify (&block
, se_stat
.expr
,
9888 fold_convert (TREE_TYPE (se_stat
.expr
), statp
));
9890 return gfc_finish_block (&block
);
9895 /* The loc intrinsic returns the address of its argument as
9896 gfc_index_integer_kind integer. */
9899 gfc_conv_intrinsic_loc (gfc_se
* se
, gfc_expr
* expr
)
9904 gcc_assert (!se
->ss
);
9906 arg_expr
= expr
->value
.function
.actual
->expr
;
9907 if (arg_expr
->rank
== 0)
9909 if (arg_expr
->ts
.type
== BT_CLASS
)
9910 gfc_add_data_component (arg_expr
);
9911 gfc_conv_expr_reference (se
, arg_expr
);
9914 gfc_conv_array_parameter (se
, arg_expr
, true, NULL
, NULL
, NULL
);
9915 se
->expr
= convert (gfc_get_int_type (gfc_index_integer_kind
), se
->expr
);
9917 /* Create a temporary variable for loc return value. Without this,
9918 we get an error an ICE in gcc/expr.cc(expand_expr_addr_expr_1). */
9919 temp_var
= gfc_create_var (gfc_get_int_type (gfc_index_integer_kind
), NULL
);
9920 gfc_add_modify (&se
->pre
, temp_var
, se
->expr
);
9921 se
->expr
= temp_var
;
9925 /* The following routine generates code for the intrinsic
9926 functions from the ISO_C_BINDING module:
9932 conv_isocbinding_function (gfc_se
*se
, gfc_expr
*expr
)
9934 gfc_actual_arglist
*arg
= expr
->value
.function
.actual
;
9936 if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_LOC
)
9938 if (arg
->expr
->rank
== 0)
9939 gfc_conv_expr_reference (se
, arg
->expr
);
9940 else if (gfc_is_simply_contiguous (arg
->expr
, false, false))
9941 gfc_conv_array_parameter (se
, arg
->expr
, true, NULL
, NULL
, NULL
);
9944 gfc_conv_expr_descriptor (se
, arg
->expr
);
9945 se
->expr
= gfc_conv_descriptor_data_get (se
->expr
);
9948 /* TODO -- the following two lines shouldn't be necessary, but if
9949 they're removed, a bug is exposed later in the code path.
9950 This workaround was thus introduced, but will have to be
9951 removed; please see PR 35150 for details about the issue. */
9952 se
->expr
= convert (pvoid_type_node
, se
->expr
);
9953 se
->expr
= gfc_evaluate_now (se
->expr
, &se
->pre
);
9955 else if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_FUNLOC
)
9956 gfc_conv_expr_reference (se
, arg
->expr
);
9957 else if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_ASSOCIATED
)
9962 /* Build the addr_expr for the first argument. The argument is
9963 already an *address* so we don't need to set want_pointer in
9965 gfc_init_se (&arg1se
, NULL
);
9966 gfc_conv_expr (&arg1se
, arg
->expr
);
9967 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
9968 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
9970 /* See if we were given two arguments. */
9971 if (arg
->next
->expr
== NULL
)
9972 /* Only given one arg so generate a null and do a
9973 not-equal comparison against the first arg. */
9974 se
->expr
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
9976 fold_convert (TREE_TYPE (arg1se
.expr
),
9977 null_pointer_node
));
9983 /* Given two arguments so build the arg2se from second arg. */
9984 gfc_init_se (&arg2se
, NULL
);
9985 gfc_conv_expr (&arg2se
, arg
->next
->expr
);
9986 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
9987 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
9989 /* Generate test to compare that the two args are equal. */
9990 eq_expr
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
9991 arg1se
.expr
, arg2se
.expr
);
9992 /* Generate test to ensure that the first arg is not null. */
9993 not_null_expr
= fold_build2_loc (input_location
, NE_EXPR
,
9995 arg1se
.expr
, null_pointer_node
);
9997 /* Finally, the generated test must check that both arg1 is not
9998 NULL and that it is equal to the second arg. */
9999 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
10001 not_null_expr
, eq_expr
);
10005 gcc_unreachable ();
10009 /* The following routine generates code for the intrinsic
10010 subroutines from the ISO_C_BINDING module:
10012 * C_F_PROCPOINTER. */
10015 conv_isocbinding_subroutine (gfc_code
*code
)
10022 tree desc
, dim
, tmp
, stride
, offset
;
10023 stmtblock_t body
, block
;
10025 gfc_actual_arglist
*arg
= code
->ext
.actual
;
10027 gfc_init_se (&se
, NULL
);
10028 gfc_init_se (&cptrse
, NULL
);
10029 gfc_conv_expr (&cptrse
, arg
->expr
);
10030 gfc_add_block_to_block (&se
.pre
, &cptrse
.pre
);
10031 gfc_add_block_to_block (&se
.post
, &cptrse
.post
);
10033 gfc_init_se (&fptrse
, NULL
);
10034 if (arg
->next
->expr
->rank
== 0)
10036 fptrse
.want_pointer
= 1;
10037 gfc_conv_expr (&fptrse
, arg
->next
->expr
);
10038 gfc_add_block_to_block (&se
.pre
, &fptrse
.pre
);
10039 gfc_add_block_to_block (&se
.post
, &fptrse
.post
);
10040 if (arg
->next
->expr
->symtree
->n
.sym
->attr
.proc_pointer
10041 && arg
->next
->expr
->symtree
->n
.sym
->attr
.dummy
)
10042 fptrse
.expr
= build_fold_indirect_ref_loc (input_location
,
10044 se
.expr
= fold_build2_loc (input_location
, MODIFY_EXPR
,
10045 TREE_TYPE (fptrse
.expr
),
10047 fold_convert (TREE_TYPE (fptrse
.expr
),
10049 gfc_add_expr_to_block (&se
.pre
, se
.expr
);
10050 gfc_add_block_to_block (&se
.pre
, &se
.post
);
10051 return gfc_finish_block (&se
.pre
);
10054 gfc_start_block (&block
);
10056 /* Get the descriptor of the Fortran pointer. */
10057 fptrse
.descriptor_only
= 1;
10058 gfc_conv_expr_descriptor (&fptrse
, arg
->next
->expr
);
10059 gfc_add_block_to_block (&block
, &fptrse
.pre
);
10060 desc
= fptrse
.expr
;
10062 /* Set the span field. */
10063 tmp
= TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc
)));
10064 tmp
= fold_convert (gfc_array_index_type
, tmp
);
10065 gfc_conv_descriptor_span_set (&block
, desc
, tmp
);
10067 /* Set data value, dtype, and offset. */
10068 tmp
= GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc
));
10069 gfc_conv_descriptor_data_set (&block
, desc
, fold_convert (tmp
, cptrse
.expr
));
10070 gfc_add_modify (&block
, gfc_conv_descriptor_dtype (desc
),
10071 gfc_get_dtype (TREE_TYPE (desc
)));
10073 /* Start scalarization of the bounds, using the shape argument. */
10075 shape_ss
= gfc_walk_expr (arg
->next
->next
->expr
);
10076 gcc_assert (shape_ss
!= gfc_ss_terminator
);
10077 gfc_init_se (&shapese
, NULL
);
10079 gfc_init_loopinfo (&loop
);
10080 gfc_add_ss_to_loop (&loop
, shape_ss
);
10081 gfc_conv_ss_startstride (&loop
);
10082 gfc_conv_loop_setup (&loop
, &arg
->next
->expr
->where
);
10083 gfc_mark_ss_chain_used (shape_ss
, 1);
10085 gfc_copy_loopinfo_to_se (&shapese
, &loop
);
10086 shapese
.ss
= shape_ss
;
10088 stride
= gfc_create_var (gfc_array_index_type
, "stride");
10089 offset
= gfc_create_var (gfc_array_index_type
, "offset");
10090 gfc_add_modify (&block
, stride
, gfc_index_one_node
);
10091 gfc_add_modify (&block
, offset
, gfc_index_zero_node
);
10094 gfc_start_scalarized_body (&loop
, &body
);
10096 dim
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
10097 loop
.loopvar
[0], loop
.from
[0]);
10099 /* Set bounds and stride. */
10100 gfc_conv_descriptor_lbound_set (&body
, desc
, dim
, gfc_index_one_node
);
10101 gfc_conv_descriptor_stride_set (&body
, desc
, dim
, stride
);
10103 gfc_conv_expr (&shapese
, arg
->next
->next
->expr
);
10104 gfc_add_block_to_block (&body
, &shapese
.pre
);
10105 gfc_conv_descriptor_ubound_set (&body
, desc
, dim
, shapese
.expr
);
10106 gfc_add_block_to_block (&body
, &shapese
.post
);
10108 /* Calculate offset. */
10109 gfc_add_modify (&body
, offset
,
10110 fold_build2_loc (input_location
, PLUS_EXPR
,
10111 gfc_array_index_type
, offset
, stride
));
10112 /* Update stride. */
10113 gfc_add_modify (&body
, stride
,
10114 fold_build2_loc (input_location
, MULT_EXPR
,
10115 gfc_array_index_type
, stride
,
10116 fold_convert (gfc_array_index_type
,
10118 /* Finish scalarization loop. */
10119 gfc_trans_scalarizing_loops (&loop
, &body
);
10120 gfc_add_block_to_block (&block
, &loop
.pre
);
10121 gfc_add_block_to_block (&block
, &loop
.post
);
10122 gfc_add_block_to_block (&block
, &fptrse
.post
);
10123 gfc_cleanup_loop (&loop
);
10125 gfc_add_modify (&block
, offset
,
10126 fold_build1_loc (input_location
, NEGATE_EXPR
,
10127 gfc_array_index_type
, offset
));
10128 gfc_conv_descriptor_offset_set (&block
, desc
, offset
);
10130 gfc_add_expr_to_block (&se
.pre
, gfc_finish_block (&block
));
10131 gfc_add_block_to_block (&se
.pre
, &se
.post
);
10132 return gfc_finish_block (&se
.pre
);
10136 /* Save and restore floating-point state. */
10139 gfc_save_fp_state (stmtblock_t
*block
)
10141 tree type
, fpstate
, tmp
;
10143 type
= build_array_type (char_type_node
,
10144 build_range_type (size_type_node
, size_zero_node
,
10145 size_int (GFC_FPE_STATE_BUFFER_SIZE
)));
10146 fpstate
= gfc_create_var (type
, "fpstate");
10147 fpstate
= gfc_build_addr_expr (pvoid_type_node
, fpstate
);
10149 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_ieee_procedure_entry
,
10151 gfc_add_expr_to_block (block
, tmp
);
10158 gfc_restore_fp_state (stmtblock_t
*block
, tree fpstate
)
10162 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_ieee_procedure_exit
,
10164 gfc_add_expr_to_block (block
, tmp
);
10168 /* Generate code for arguments of IEEE functions. */
10171 conv_ieee_function_args (gfc_se
*se
, gfc_expr
*expr
, tree
*argarray
,
10174 gfc_actual_arglist
*actual
;
10179 actual
= expr
->value
.function
.actual
;
10180 for (arg
= 0; arg
< nargs
; arg
++, actual
= actual
->next
)
10182 gcc_assert (actual
);
10185 gfc_init_se (&argse
, se
);
10186 gfc_conv_expr_val (&argse
, e
);
10188 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
10189 gfc_add_block_to_block (&se
->post
, &argse
.post
);
10190 argarray
[arg
] = argse
.expr
;
10195 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE
10196 and IEEE_UNORDERED, which translate directly to GCC type-generic
10200 conv_intrinsic_ieee_builtin (gfc_se
* se
, gfc_expr
* expr
,
10201 enum built_in_function code
, int nargs
)
10204 gcc_assert ((unsigned) nargs
<= ARRAY_SIZE (args
));
10206 conv_ieee_function_args (se
, expr
, args
, nargs
);
10207 se
->expr
= build_call_expr_loc_array (input_location
,
10208 builtin_decl_explicit (code
),
10210 STRIP_TYPE_NOPS (se
->expr
);
10211 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
10215 /* Generate code for intrinsics IEEE_SIGNBIT. */
10218 conv_intrinsic_ieee_signbit (gfc_se
* se
, gfc_expr
* expr
)
10222 conv_ieee_function_args (se
, expr
, &arg
, 1);
10223 signbit
= build_call_expr_loc (input_location
,
10224 builtin_decl_explicit (BUILT_IN_SIGNBIT
),
10226 signbit
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
10227 signbit
, integer_zero_node
);
10228 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), signbit
);
10232 /* Generate code for IEEE_IS_NORMAL intrinsic:
10233 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
10236 conv_intrinsic_ieee_is_normal (gfc_se
* se
, gfc_expr
* expr
)
10238 tree arg
, isnormal
, iszero
;
10240 /* Convert arg, evaluate it only once. */
10241 conv_ieee_function_args (se
, expr
, &arg
, 1);
10242 arg
= gfc_evaluate_now (arg
, &se
->pre
);
10244 isnormal
= build_call_expr_loc (input_location
,
10245 builtin_decl_explicit (BUILT_IN_ISNORMAL
),
10247 iszero
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, arg
,
10248 build_real_from_int_cst (TREE_TYPE (arg
),
10249 integer_zero_node
));
10250 se
->expr
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
10251 logical_type_node
, isnormal
, iszero
);
10252 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
10256 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
10257 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
10260 conv_intrinsic_ieee_is_negative (gfc_se
* se
, gfc_expr
* expr
)
10262 tree arg
, signbit
, isnan
;
10264 /* Convert arg, evaluate it only once. */
10265 conv_ieee_function_args (se
, expr
, &arg
, 1);
10266 arg
= gfc_evaluate_now (arg
, &se
->pre
);
10268 isnan
= build_call_expr_loc (input_location
,
10269 builtin_decl_explicit (BUILT_IN_ISNAN
),
10271 STRIP_TYPE_NOPS (isnan
);
10273 signbit
= build_call_expr_loc (input_location
,
10274 builtin_decl_explicit (BUILT_IN_SIGNBIT
),
10276 signbit
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
10277 signbit
, integer_zero_node
);
10279 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
10280 logical_type_node
, signbit
,
10281 fold_build1_loc (input_location
, TRUTH_NOT_EXPR
,
10282 TREE_TYPE(isnan
), isnan
));
10284 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
10288 /* Generate code for IEEE_LOGB and IEEE_RINT. */
10291 conv_intrinsic_ieee_logb_rint (gfc_se
* se
, gfc_expr
* expr
,
10292 enum built_in_function code
)
10294 tree arg
, decl
, call
, fpstate
;
10297 conv_ieee_function_args (se
, expr
, &arg
, 1);
10298 argprec
= TYPE_PRECISION (TREE_TYPE (arg
));
10299 decl
= builtin_decl_for_precision (code
, argprec
);
10301 /* Save floating-point state. */
10302 fpstate
= gfc_save_fp_state (&se
->pre
);
10304 /* Make the function call. */
10305 call
= build_call_expr_loc (input_location
, decl
, 1, arg
);
10306 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), call
);
10308 /* Restore floating-point state. */
10309 gfc_restore_fp_state (&se
->post
, fpstate
);
10313 /* Generate code for IEEE_REM. */
10316 conv_intrinsic_ieee_rem (gfc_se
* se
, gfc_expr
* expr
)
10318 tree args
[2], decl
, call
, fpstate
;
10321 conv_ieee_function_args (se
, expr
, args
, 2);
10323 /* If arguments have unequal size, convert them to the larger. */
10324 if (TYPE_PRECISION (TREE_TYPE (args
[0]))
10325 > TYPE_PRECISION (TREE_TYPE (args
[1])))
10326 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
10327 else if (TYPE_PRECISION (TREE_TYPE (args
[1]))
10328 > TYPE_PRECISION (TREE_TYPE (args
[0])))
10329 args
[0] = fold_convert (TREE_TYPE (args
[1]), args
[0]);
10331 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
10332 decl
= builtin_decl_for_precision (BUILT_IN_REMAINDER
, argprec
);
10334 /* Save floating-point state. */
10335 fpstate
= gfc_save_fp_state (&se
->pre
);
10337 /* Make the function call. */
10338 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
10339 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
10341 /* Restore floating-point state. */
10342 gfc_restore_fp_state (&se
->post
, fpstate
);
10346 /* Generate code for IEEE_NEXT_AFTER. */
10349 conv_intrinsic_ieee_next_after (gfc_se
* se
, gfc_expr
* expr
)
10351 tree args
[2], decl
, call
, fpstate
;
10354 conv_ieee_function_args (se
, expr
, args
, 2);
10356 /* Result has the characteristics of first argument. */
10357 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
10358 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
10359 decl
= builtin_decl_for_precision (BUILT_IN_NEXTAFTER
, argprec
);
10361 /* Save floating-point state. */
10362 fpstate
= gfc_save_fp_state (&se
->pre
);
10364 /* Make the function call. */
10365 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
10366 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
10368 /* Restore floating-point state. */
10369 gfc_restore_fp_state (&se
->post
, fpstate
);
10373 /* Generate code for IEEE_SCALB. */
10376 conv_intrinsic_ieee_scalb (gfc_se
* se
, gfc_expr
* expr
)
10378 tree args
[2], decl
, call
, huge
, type
;
10381 conv_ieee_function_args (se
, expr
, args
, 2);
10383 /* Result has the characteristics of first argument. */
10384 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
10385 decl
= builtin_decl_for_precision (BUILT_IN_SCALBN
, argprec
);
10387 if (TYPE_PRECISION (TREE_TYPE (args
[1])) > TYPE_PRECISION (integer_type_node
))
10389 /* We need to fold the integer into the range of a C int. */
10390 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
10391 type
= TREE_TYPE (args
[1]);
10393 n
= gfc_validate_kind (BT_INTEGER
, gfc_c_int_kind
, false);
10394 huge
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
,
10396 huge
= fold_convert (type
, huge
);
10397 args
[1] = fold_build2_loc (input_location
, MIN_EXPR
, type
, args
[1],
10399 args
[1] = fold_build2_loc (input_location
, MAX_EXPR
, type
, args
[1],
10400 fold_build1_loc (input_location
, NEGATE_EXPR
,
10404 args
[1] = fold_convert (integer_type_node
, args
[1]);
10406 /* Make the function call. */
10407 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
10408 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
10412 /* Generate code for IEEE_COPY_SIGN. */
10415 conv_intrinsic_ieee_copy_sign (gfc_se
* se
, gfc_expr
* expr
)
10417 tree args
[2], decl
, sign
;
10420 conv_ieee_function_args (se
, expr
, args
, 2);
10422 /* Get the sign of the second argument. */
10423 sign
= build_call_expr_loc (input_location
,
10424 builtin_decl_explicit (BUILT_IN_SIGNBIT
),
10426 sign
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
10427 sign
, integer_zero_node
);
10429 /* Create a value of one, with the right sign. */
10430 sign
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
10432 fold_build1_loc (input_location
, NEGATE_EXPR
,
10436 args
[1] = fold_convert (TREE_TYPE (args
[0]), sign
);
10438 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
10439 decl
= builtin_decl_for_precision (BUILT_IN_COPYSIGN
, argprec
);
10441 se
->expr
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
10445 /* Generate code for IEEE_CLASS. */
10448 conv_intrinsic_ieee_class (gfc_se
*se
, gfc_expr
*expr
)
10450 tree arg
, c
, t1
, t2
, t3
, t4
;
10452 /* Convert arg, evaluate it only once. */
10453 conv_ieee_function_args (se
, expr
, &arg
, 1);
10454 arg
= gfc_evaluate_now (arg
, &se
->pre
);
10456 c
= build_call_expr_loc (input_location
,
10457 builtin_decl_explicit (BUILT_IN_FPCLASSIFY
), 6,
10458 build_int_cst (integer_type_node
, IEEE_QUIET_NAN
),
10459 build_int_cst (integer_type_node
,
10460 IEEE_POSITIVE_INF
),
10461 build_int_cst (integer_type_node
,
10462 IEEE_POSITIVE_NORMAL
),
10463 build_int_cst (integer_type_node
,
10464 IEEE_POSITIVE_DENORMAL
),
10465 build_int_cst (integer_type_node
,
10466 IEEE_POSITIVE_ZERO
),
10468 c
= gfc_evaluate_now (c
, &se
->pre
);
10469 t1
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
10470 c
, build_int_cst (integer_type_node
,
10472 t2
= build_call_expr_loc (input_location
,
10473 builtin_decl_explicit (BUILT_IN_ISSIGNALING
), 1,
10475 t2
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
10476 t2
, build_zero_cst (TREE_TYPE (t2
)));
10477 t1
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
10478 logical_type_node
, t1
, t2
);
10479 t3
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
10480 c
, build_int_cst (integer_type_node
,
10481 IEEE_POSITIVE_ZERO
));
10482 t4
= build_call_expr_loc (input_location
,
10483 builtin_decl_explicit (BUILT_IN_SIGNBIT
), 1,
10485 t4
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
10486 t4
, build_zero_cst (TREE_TYPE (t4
)));
10487 t3
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
10488 logical_type_node
, t3
, t4
);
10489 int s
= IEEE_NEGATIVE_ZERO
+ IEEE_POSITIVE_ZERO
;
10490 gcc_assert (IEEE_NEGATIVE_INF
== s
- IEEE_POSITIVE_INF
);
10491 gcc_assert (IEEE_NEGATIVE_NORMAL
== s
- IEEE_POSITIVE_NORMAL
);
10492 gcc_assert (IEEE_NEGATIVE_DENORMAL
== s
- IEEE_POSITIVE_DENORMAL
);
10493 gcc_assert (IEEE_NEGATIVE_SUBNORMAL
== s
- IEEE_POSITIVE_SUBNORMAL
);
10494 gcc_assert (IEEE_NEGATIVE_ZERO
== s
- IEEE_POSITIVE_ZERO
);
10495 t4
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (c
),
10496 build_int_cst (TREE_TYPE (c
), s
), c
);
10497 t3
= fold_build3_loc (input_location
, COND_EXPR
, TREE_TYPE (c
),
10499 t1
= fold_build3_loc (input_location
, COND_EXPR
, TREE_TYPE (c
), t1
,
10500 build_int_cst (TREE_TYPE (c
), IEEE_SIGNALING_NAN
),
10502 tree type
= gfc_typenode_for_spec (&expr
->ts
);
10503 /* Perform a quick sanity check that the return type is
10504 IEEE_CLASS_TYPE derived type defined in
10505 libgfortran/ieee/ieee_arithmetic.F90
10506 Primarily check that it is a derived type with a single
10508 gcc_assert (TREE_CODE (type
) == RECORD_TYPE
);
10509 tree field
= NULL_TREE
;
10510 for (tree f
= TYPE_FIELDS (type
); f
!= NULL_TREE
; f
= DECL_CHAIN (f
))
10511 if (TREE_CODE (f
) == FIELD_DECL
)
10513 gcc_assert (field
== NULL_TREE
);
10516 gcc_assert (field
);
10517 t1
= fold_convert (TREE_TYPE (field
), t1
);
10518 se
->expr
= build_constructor_single (type
, field
, t1
);
10522 /* Generate code for IEEE_VALUE. */
10525 conv_intrinsic_ieee_value (gfc_se
*se
, gfc_expr
*expr
)
10527 tree args
[2], arg
, ret
, tmp
;
10530 /* Convert args, evaluate the second one only once. */
10531 conv_ieee_function_args (se
, expr
, args
, 2);
10532 arg
= gfc_evaluate_now (args
[1], &se
->pre
);
10534 tree type
= TREE_TYPE (arg
);
10535 /* Perform a quick sanity check that the second argument's type is
10536 IEEE_CLASS_TYPE derived type defined in
10537 libgfortran/ieee/ieee_arithmetic.F90
10538 Primarily check that it is a derived type with a single
10540 gcc_assert (TREE_CODE (type
) == RECORD_TYPE
);
10541 tree field
= NULL_TREE
;
10542 for (tree f
= TYPE_FIELDS (type
); f
!= NULL_TREE
; f
= DECL_CHAIN (f
))
10543 if (TREE_CODE (f
) == FIELD_DECL
)
10545 gcc_assert (field
== NULL_TREE
);
10548 gcc_assert (field
);
10549 arg
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
10550 arg
, field
, NULL_TREE
);
10551 arg
= gfc_evaluate_now (arg
, &se
->pre
);
10553 type
= gfc_typenode_for_spec (&expr
->ts
);
10554 gcc_assert (SCALAR_FLOAT_TYPE_P (type
));
10555 ret
= gfc_create_var (type
, NULL
);
10557 gfc_init_block (&body
);
10559 tree end_label
= gfc_build_label_decl (NULL_TREE
);
10560 for (int c
= IEEE_SIGNALING_NAN
; c
<= IEEE_POSITIVE_INF
; ++c
)
10562 tree label
= gfc_build_label_decl (NULL_TREE
);
10563 tree low
= build_int_cst (TREE_TYPE (arg
), c
);
10564 tmp
= build_case_label (low
, low
, label
);
10565 gfc_add_expr_to_block (&body
, tmp
);
10567 REAL_VALUE_TYPE real
;
10571 case IEEE_SIGNALING_NAN
:
10572 real_nan (&real
, "", 0, TYPE_MODE (type
));
10574 case IEEE_QUIET_NAN
:
10575 real_nan (&real
, "", 1, TYPE_MODE (type
));
10577 case IEEE_NEGATIVE_INF
:
10579 real
= real_value_negate (&real
);
10581 case IEEE_NEGATIVE_NORMAL
:
10582 real_from_integer (&real
, TYPE_MODE (type
), -42, SIGNED
);
10584 case IEEE_NEGATIVE_DENORMAL
:
10585 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
10586 real_from_mpfr (&real
, gfc_real_kinds
[k
].tiny
,
10587 type
, GFC_RND_MODE
);
10588 real_arithmetic (&real
, RDIV_EXPR
, &real
, &dconst2
);
10589 real
= real_value_negate (&real
);
10591 case IEEE_NEGATIVE_ZERO
:
10592 real_from_integer (&real
, TYPE_MODE (type
), 0, SIGNED
);
10593 real
= real_value_negate (&real
);
10595 case IEEE_POSITIVE_ZERO
:
10596 /* Make this also the default: label. The other possibility
10597 would be to add a separate default: label followed by
10598 __builtin_unreachable (). */
10599 label
= gfc_build_label_decl (NULL_TREE
);
10600 tmp
= build_case_label (NULL_TREE
, NULL_TREE
, label
);
10601 gfc_add_expr_to_block (&body
, tmp
);
10602 real_from_integer (&real
, TYPE_MODE (type
), 0, SIGNED
);
10604 case IEEE_POSITIVE_DENORMAL
:
10605 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
10606 real_from_mpfr (&real
, gfc_real_kinds
[k
].tiny
,
10607 type
, GFC_RND_MODE
);
10608 real_arithmetic (&real
, RDIV_EXPR
, &real
, &dconst2
);
10610 case IEEE_POSITIVE_NORMAL
:
10611 real_from_integer (&real
, TYPE_MODE (type
), 42, SIGNED
);
10613 case IEEE_POSITIVE_INF
:
10617 gcc_unreachable ();
10620 tree val
= build_real (type
, real
);
10621 gfc_add_modify (&body
, ret
, val
);
10623 tmp
= build1_v (GOTO_EXPR
, end_label
);
10624 gfc_add_expr_to_block (&body
, tmp
);
10627 tmp
= gfc_finish_block (&body
);
10628 tmp
= fold_build2_loc (input_location
, SWITCH_EXPR
, NULL_TREE
, arg
, tmp
);
10629 gfc_add_expr_to_block (&se
->pre
, tmp
);
10631 tmp
= build1_v (LABEL_EXPR
, end_label
);
10632 gfc_add_expr_to_block (&se
->pre
, tmp
);
10638 /* Generate code for IEEE_FMA. */
10641 conv_intrinsic_ieee_fma (gfc_se
* se
, gfc_expr
* expr
)
10643 tree args
[3], decl
, call
;
10646 conv_ieee_function_args (se
, expr
, args
, 3);
10648 /* All three arguments should have the same type. */
10649 gcc_assert (TYPE_PRECISION (TREE_TYPE (args
[0])) == TYPE_PRECISION (TREE_TYPE (args
[1])));
10650 gcc_assert (TYPE_PRECISION (TREE_TYPE (args
[0])) == TYPE_PRECISION (TREE_TYPE (args
[2])));
10652 /* Call the type-generic FMA built-in. */
10653 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
10654 decl
= builtin_decl_for_precision (BUILT_IN_FMA
, argprec
);
10655 call
= build_call_expr_loc_array (input_location
, decl
, 3, args
);
10657 /* Convert to the final type. */
10658 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
10662 /* Generate code for IEEE_{MIN,MAX}_NUM{,_MAG}. */
10665 conv_intrinsic_ieee_minmax (gfc_se
* se
, gfc_expr
* expr
, int max
,
10668 tree args
[2], func
;
10669 built_in_function fn
;
10671 conv_ieee_function_args (se
, expr
, args
, 2);
10672 gcc_assert (TYPE_PRECISION (TREE_TYPE (args
[0])) == TYPE_PRECISION (TREE_TYPE (args
[1])));
10673 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
10674 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
10676 if (startswith (name
, "mag"))
10678 /* IEEE_MIN_NUM_MAG and IEEE_MAX_NUM_MAG translate to C functions
10679 fminmag() and fmaxmag(), which do not exist as built-ins.
10681 Following glibc, we emit this:
10686 if (isless (ax, ay))
10688 else if (isgreater (ax, ay))
10691 return x < y ? x : y;
10692 else if (issignaling (x) || issignaling (y))
10695 return isnan (y) ? x : y;
10701 if (isgreater (ax, ay))
10703 else if (isless (ax, ay))
10706 return x > y ? x : y;
10707 else if (issignaling (x) || issignaling (y))
10710 return isnan (y) ? x : y;
10715 tree abs0
, abs1
, sig0
, sig1
;
10716 tree cond1
, cond2
, cond3
, cond4
, cond5
;
10718 tree type
= TREE_TYPE (args
[0]);
10720 func
= gfc_builtin_decl_for_float_kind (BUILT_IN_FABS
, expr
->ts
.kind
);
10721 abs0
= build_call_expr_loc (input_location
, func
, 1, args
[0]);
10722 abs1
= build_call_expr_loc (input_location
, func
, 1, args
[1]);
10723 abs0
= gfc_evaluate_now (abs0
, &se
->pre
);
10724 abs1
= gfc_evaluate_now (abs1
, &se
->pre
);
10726 cond5
= build_call_expr_loc (input_location
,
10727 builtin_decl_explicit (BUILT_IN_ISNAN
),
10729 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond5
,
10732 sig0
= build_call_expr_loc (input_location
,
10733 builtin_decl_explicit (BUILT_IN_ISSIGNALING
),
10735 sig1
= build_call_expr_loc (input_location
,
10736 builtin_decl_explicit (BUILT_IN_ISSIGNALING
),
10738 cond4
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
10739 logical_type_node
, sig0
, sig1
);
10740 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond4
,
10741 fold_build2_loc (input_location
, PLUS_EXPR
,
10742 type
, args
[0], args
[1]),
10745 cond3
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
10747 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond3
,
10748 fold_build2_loc (input_location
,
10749 max
? MAX_EXPR
: MIN_EXPR
,
10750 type
, args
[0], args
[1]),
10753 func
= builtin_decl_explicit (max
? BUILT_IN_ISLESS
: BUILT_IN_ISGREATER
);
10754 cond2
= build_call_expr_loc (input_location
, func
, 2, abs0
, abs1
);
10755 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond2
,
10758 func
= builtin_decl_explicit (max
? BUILT_IN_ISGREATER
: BUILT_IN_ISLESS
);
10759 cond1
= build_call_expr_loc (input_location
, func
, 2, abs0
, abs1
);
10760 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond1
,
10767 /* IEEE_MIN_NUM and IEEE_MAX_NUM translate to fmin() and fmax(). */
10768 fn
= max
? BUILT_IN_FMAX
: BUILT_IN_FMIN
;
10769 func
= gfc_builtin_decl_for_float_kind (fn
, expr
->ts
.kind
);
10770 se
->expr
= build_call_expr_loc_array (input_location
, func
, 2, args
);
10775 /* Generate code for comparison functions IEEE_QUIET_* and
10776 IEEE_SIGNALING_*. */
10779 conv_intrinsic_ieee_comparison (gfc_se
* se
, gfc_expr
* expr
, int signaling
,
10783 tree arg1
, arg2
, res
;
10785 /* Evaluate arguments only once. */
10786 conv_ieee_function_args (se
, expr
, args
, 2);
10787 arg1
= gfc_evaluate_now (args
[0], &se
->pre
);
10788 arg2
= gfc_evaluate_now (args
[1], &se
->pre
);
10790 if (startswith (name
, "eq"))
10793 res
= build_call_expr_loc (input_location
,
10794 builtin_decl_explicit (BUILT_IN_ISEQSIG
),
10797 res
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
10800 else if (startswith (name
, "ne"))
10804 res
= build_call_expr_loc (input_location
,
10805 builtin_decl_explicit (BUILT_IN_ISEQSIG
),
10807 res
= fold_build1_loc (input_location
, TRUTH_NOT_EXPR
,
10808 logical_type_node
, res
);
10811 res
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
10814 else if (startswith (name
, "ge"))
10817 res
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
10820 res
= build_call_expr_loc (input_location
,
10821 builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL
),
10824 else if (startswith (name
, "gt"))
10827 res
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
10830 res
= build_call_expr_loc (input_location
,
10831 builtin_decl_explicit (BUILT_IN_ISGREATER
),
10834 else if (startswith (name
, "le"))
10837 res
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
,
10840 res
= build_call_expr_loc (input_location
,
10841 builtin_decl_explicit (BUILT_IN_ISLESSEQUAL
),
10844 else if (startswith (name
, "lt"))
10847 res
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
10850 res
= build_call_expr_loc (input_location
,
10851 builtin_decl_explicit (BUILT_IN_ISLESS
),
10855 gcc_unreachable ();
10857 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), res
);
10861 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
10865 gfc_conv_ieee_arithmetic_function (gfc_se
* se
, gfc_expr
* expr
)
10867 const char *name
= expr
->value
.function
.name
;
10869 if (startswith (name
, "_gfortran_ieee_is_nan"))
10870 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISNAN
, 1);
10871 else if (startswith (name
, "_gfortran_ieee_is_finite"))
10872 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISFINITE
, 1);
10873 else if (startswith (name
, "_gfortran_ieee_unordered"))
10874 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISUNORDERED
, 2);
10875 else if (startswith (name
, "_gfortran_ieee_signbit"))
10876 conv_intrinsic_ieee_signbit (se
, expr
);
10877 else if (startswith (name
, "_gfortran_ieee_is_normal"))
10878 conv_intrinsic_ieee_is_normal (se
, expr
);
10879 else if (startswith (name
, "_gfortran_ieee_is_negative"))
10880 conv_intrinsic_ieee_is_negative (se
, expr
);
10881 else if (startswith (name
, "_gfortran_ieee_copy_sign"))
10882 conv_intrinsic_ieee_copy_sign (se
, expr
);
10883 else if (startswith (name
, "_gfortran_ieee_scalb"))
10884 conv_intrinsic_ieee_scalb (se
, expr
);
10885 else if (startswith (name
, "_gfortran_ieee_next_after"))
10886 conv_intrinsic_ieee_next_after (se
, expr
);
10887 else if (startswith (name
, "_gfortran_ieee_rem"))
10888 conv_intrinsic_ieee_rem (se
, expr
);
10889 else if (startswith (name
, "_gfortran_ieee_logb"))
10890 conv_intrinsic_ieee_logb_rint (se
, expr
, BUILT_IN_LOGB
);
10891 else if (startswith (name
, "_gfortran_ieee_rint"))
10892 conv_intrinsic_ieee_logb_rint (se
, expr
, BUILT_IN_RINT
);
10893 else if (startswith (name
, "ieee_class_") && ISDIGIT (name
[11]))
10894 conv_intrinsic_ieee_class (se
, expr
);
10895 else if (startswith (name
, "ieee_value_") && ISDIGIT (name
[11]))
10896 conv_intrinsic_ieee_value (se
, expr
);
10897 else if (startswith (name
, "_gfortran_ieee_fma"))
10898 conv_intrinsic_ieee_fma (se
, expr
);
10899 else if (startswith (name
, "_gfortran_ieee_min_num_"))
10900 conv_intrinsic_ieee_minmax (se
, expr
, 0, name
+ 23);
10901 else if (startswith (name
, "_gfortran_ieee_max_num_"))
10902 conv_intrinsic_ieee_minmax (se
, expr
, 1, name
+ 23);
10903 else if (startswith (name
, "_gfortran_ieee_quiet_"))
10904 conv_intrinsic_ieee_comparison (se
, expr
, 0, name
+ 21);
10905 else if (startswith (name
, "_gfortran_ieee_signaling_"))
10906 conv_intrinsic_ieee_comparison (se
, expr
, 1, name
+ 25);
10908 /* It is not among the functions we translate directly. We return
10909 false, so a library function call is emitted. */
10916 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
10919 gfc_conv_intrinsic_malloc (gfc_se
* se
, gfc_expr
* expr
)
10921 tree arg
, res
, restype
;
10923 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
10924 arg
= fold_convert (size_type_node
, arg
);
10925 res
= build_call_expr_loc (input_location
,
10926 builtin_decl_explicit (BUILT_IN_MALLOC
), 1, arg
);
10927 restype
= gfc_typenode_for_spec (&expr
->ts
);
10928 se
->expr
= fold_convert (restype
, res
);
10932 /* Generate code for an intrinsic function. Some map directly to library
10933 calls, others get special handling. In some cases the name of the function
10934 used depends on the type specifiers. */
10937 gfc_conv_intrinsic_function (gfc_se
* se
, gfc_expr
* expr
)
10943 name
= &expr
->value
.function
.name
[2];
10945 if (expr
->rank
> 0)
10947 lib
= gfc_is_intrinsic_libcall (expr
);
10951 se
->ignore_optional
= 1;
10953 switch (expr
->value
.function
.isym
->id
)
10955 case GFC_ISYM_EOSHIFT
:
10956 case GFC_ISYM_PACK
:
10957 case GFC_ISYM_RESHAPE
:
10958 /* For all of those the first argument specifies the type and the
10959 third is optional. */
10960 conv_generic_with_optional_char_arg (se
, expr
, 1, 3);
10963 case GFC_ISYM_FINDLOC
:
10964 gfc_conv_intrinsic_findloc (se
, expr
);
10967 case GFC_ISYM_MINLOC
:
10968 gfc_conv_intrinsic_minmaxloc (se
, expr
, LT_EXPR
);
10971 case GFC_ISYM_MAXLOC
:
10972 gfc_conv_intrinsic_minmaxloc (se
, expr
, GT_EXPR
);
10976 gfc_conv_intrinsic_funcall (se
, expr
);
10984 switch (expr
->value
.function
.isym
->id
)
10986 case GFC_ISYM_NONE
:
10987 gcc_unreachable ();
10989 case GFC_ISYM_REPEAT
:
10990 gfc_conv_intrinsic_repeat (se
, expr
);
10993 case GFC_ISYM_TRIM
:
10994 gfc_conv_intrinsic_trim (se
, expr
);
10997 case GFC_ISYM_SC_KIND
:
10998 gfc_conv_intrinsic_sc_kind (se
, expr
);
11001 case GFC_ISYM_SI_KIND
:
11002 gfc_conv_intrinsic_si_kind (se
, expr
);
11005 case GFC_ISYM_SL_KIND
:
11006 gfc_conv_intrinsic_sl_kind (se
, expr
);
11009 case GFC_ISYM_SR_KIND
:
11010 gfc_conv_intrinsic_sr_kind (se
, expr
);
11013 case GFC_ISYM_EXPONENT
:
11014 gfc_conv_intrinsic_exponent (se
, expr
);
11017 case GFC_ISYM_SCAN
:
11018 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
11020 fndecl
= gfor_fndecl_string_scan
;
11021 else if (kind
== 4)
11022 fndecl
= gfor_fndecl_string_scan_char4
;
11024 gcc_unreachable ();
11026 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
11029 case GFC_ISYM_VERIFY
:
11030 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
11032 fndecl
= gfor_fndecl_string_verify
;
11033 else if (kind
== 4)
11034 fndecl
= gfor_fndecl_string_verify_char4
;
11036 gcc_unreachable ();
11038 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
11041 case GFC_ISYM_ALLOCATED
:
11042 gfc_conv_allocated (se
, expr
);
11045 case GFC_ISYM_ASSOCIATED
:
11046 gfc_conv_associated(se
, expr
);
11049 case GFC_ISYM_SAME_TYPE_AS
:
11050 gfc_conv_same_type_as (se
, expr
);
11054 gfc_conv_intrinsic_abs (se
, expr
);
11057 case GFC_ISYM_ADJUSTL
:
11058 if (expr
->ts
.kind
== 1)
11059 fndecl
= gfor_fndecl_adjustl
;
11060 else if (expr
->ts
.kind
== 4)
11061 fndecl
= gfor_fndecl_adjustl_char4
;
11063 gcc_unreachable ();
11065 gfc_conv_intrinsic_adjust (se
, expr
, fndecl
);
11068 case GFC_ISYM_ADJUSTR
:
11069 if (expr
->ts
.kind
== 1)
11070 fndecl
= gfor_fndecl_adjustr
;
11071 else if (expr
->ts
.kind
== 4)
11072 fndecl
= gfor_fndecl_adjustr_char4
;
11074 gcc_unreachable ();
11076 gfc_conv_intrinsic_adjust (se
, expr
, fndecl
);
11079 case GFC_ISYM_AIMAG
:
11080 gfc_conv_intrinsic_imagpart (se
, expr
);
11083 case GFC_ISYM_AINT
:
11084 gfc_conv_intrinsic_aint (se
, expr
, RND_TRUNC
);
11088 gfc_conv_intrinsic_anyall (se
, expr
, EQ_EXPR
);
11091 case GFC_ISYM_ANINT
:
11092 gfc_conv_intrinsic_aint (se
, expr
, RND_ROUND
);
11096 gfc_conv_intrinsic_bitop (se
, expr
, BIT_AND_EXPR
);
11100 gfc_conv_intrinsic_anyall (se
, expr
, NE_EXPR
);
11103 case GFC_ISYM_ACOSD
:
11104 case GFC_ISYM_ASIND
:
11105 case GFC_ISYM_ATAND
:
11106 gfc_conv_intrinsic_atrigd (se
, expr
, expr
->value
.function
.isym
->id
);
11109 case GFC_ISYM_COTAN
:
11110 gfc_conv_intrinsic_cotan (se
, expr
);
11113 case GFC_ISYM_COTAND
:
11114 gfc_conv_intrinsic_cotand (se
, expr
);
11117 case GFC_ISYM_ATAN2D
:
11118 gfc_conv_intrinsic_atan2d (se
, expr
);
11121 case GFC_ISYM_BTEST
:
11122 gfc_conv_intrinsic_btest (se
, expr
);
11126 gfc_conv_intrinsic_bitcomp (se
, expr
, GE_EXPR
);
11130 gfc_conv_intrinsic_bitcomp (se
, expr
, GT_EXPR
);
11134 gfc_conv_intrinsic_bitcomp (se
, expr
, LE_EXPR
);
11138 gfc_conv_intrinsic_bitcomp (se
, expr
, LT_EXPR
);
11141 case GFC_ISYM_C_ASSOCIATED
:
11142 case GFC_ISYM_C_FUNLOC
:
11143 case GFC_ISYM_C_LOC
:
11144 conv_isocbinding_function (se
, expr
);
11147 case GFC_ISYM_ACHAR
:
11148 case GFC_ISYM_CHAR
:
11149 gfc_conv_intrinsic_char (se
, expr
);
11152 case GFC_ISYM_CONVERSION
:
11153 case GFC_ISYM_DBLE
:
11154 case GFC_ISYM_DFLOAT
:
11155 case GFC_ISYM_FLOAT
:
11156 case GFC_ISYM_LOGICAL
:
11157 case GFC_ISYM_REAL
:
11158 case GFC_ISYM_REALPART
:
11159 case GFC_ISYM_SNGL
:
11160 gfc_conv_intrinsic_conversion (se
, expr
);
11163 /* Integer conversions are handled separately to make sure we get the
11164 correct rounding mode. */
11166 case GFC_ISYM_INT2
:
11167 case GFC_ISYM_INT8
:
11168 case GFC_ISYM_LONG
:
11169 case GFC_ISYM_UINT
:
11170 gfc_conv_intrinsic_int (se
, expr
, RND_TRUNC
);
11173 case GFC_ISYM_NINT
:
11174 gfc_conv_intrinsic_int (se
, expr
, RND_ROUND
);
11177 case GFC_ISYM_CEILING
:
11178 gfc_conv_intrinsic_int (se
, expr
, RND_CEIL
);
11181 case GFC_ISYM_FLOOR
:
11182 gfc_conv_intrinsic_int (se
, expr
, RND_FLOOR
);
11186 gfc_conv_intrinsic_mod (se
, expr
, 0);
11189 case GFC_ISYM_MODULO
:
11190 gfc_conv_intrinsic_mod (se
, expr
, 1);
11193 case GFC_ISYM_CAF_GET
:
11194 gfc_conv_intrinsic_caf_get (se
, expr
, NULL_TREE
, NULL_TREE
, NULL_TREE
,
11198 case GFC_ISYM_CMPLX
:
11199 gfc_conv_intrinsic_cmplx (se
, expr
, name
[5] == '1');
11202 case GFC_ISYM_COMMAND_ARGUMENT_COUNT
:
11203 gfc_conv_intrinsic_iargc (se
, expr
);
11206 case GFC_ISYM_COMPLEX
:
11207 gfc_conv_intrinsic_cmplx (se
, expr
, 1);
11210 case GFC_ISYM_CONJG
:
11211 gfc_conv_intrinsic_conjg (se
, expr
);
11214 case GFC_ISYM_COUNT
:
11215 gfc_conv_intrinsic_count (se
, expr
);
11218 case GFC_ISYM_CTIME
:
11219 gfc_conv_intrinsic_ctime (se
, expr
);
11223 gfc_conv_intrinsic_dim (se
, expr
);
11226 case GFC_ISYM_DOT_PRODUCT
:
11227 gfc_conv_intrinsic_dot_product (se
, expr
);
11230 case GFC_ISYM_DPROD
:
11231 gfc_conv_intrinsic_dprod (se
, expr
);
11234 case GFC_ISYM_DSHIFTL
:
11235 gfc_conv_intrinsic_dshift (se
, expr
, true);
11238 case GFC_ISYM_DSHIFTR
:
11239 gfc_conv_intrinsic_dshift (se
, expr
, false);
11242 case GFC_ISYM_FDATE
:
11243 gfc_conv_intrinsic_fdate (se
, expr
);
11246 case GFC_ISYM_FRACTION
:
11247 gfc_conv_intrinsic_fraction (se
, expr
);
11250 case GFC_ISYM_IALL
:
11251 gfc_conv_intrinsic_arith (se
, expr
, BIT_AND_EXPR
, false);
11254 case GFC_ISYM_IAND
:
11255 gfc_conv_intrinsic_bitop (se
, expr
, BIT_AND_EXPR
);
11258 case GFC_ISYM_IANY
:
11259 gfc_conv_intrinsic_arith (se
, expr
, BIT_IOR_EXPR
, false);
11262 case GFC_ISYM_IBCLR
:
11263 gfc_conv_intrinsic_singlebitop (se
, expr
, 0);
11266 case GFC_ISYM_IBITS
:
11267 gfc_conv_intrinsic_ibits (se
, expr
);
11270 case GFC_ISYM_IBSET
:
11271 gfc_conv_intrinsic_singlebitop (se
, expr
, 1);
11274 case GFC_ISYM_IACHAR
:
11275 case GFC_ISYM_ICHAR
:
11276 /* We assume ASCII character sequence. */
11277 gfc_conv_intrinsic_ichar (se
, expr
);
11280 case GFC_ISYM_IARGC
:
11281 gfc_conv_intrinsic_iargc (se
, expr
);
11284 case GFC_ISYM_IEOR
:
11285 gfc_conv_intrinsic_bitop (se
, expr
, BIT_XOR_EXPR
);
11288 case GFC_ISYM_INDEX
:
11289 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
11291 fndecl
= gfor_fndecl_string_index
;
11292 else if (kind
== 4)
11293 fndecl
= gfor_fndecl_string_index_char4
;
11295 gcc_unreachable ();
11297 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
11301 gfc_conv_intrinsic_bitop (se
, expr
, BIT_IOR_EXPR
);
11304 case GFC_ISYM_IPARITY
:
11305 gfc_conv_intrinsic_arith (se
, expr
, BIT_XOR_EXPR
, false);
11308 case GFC_ISYM_IS_IOSTAT_END
:
11309 gfc_conv_has_intvalue (se
, expr
, LIBERROR_END
);
11312 case GFC_ISYM_IS_IOSTAT_EOR
:
11313 gfc_conv_has_intvalue (se
, expr
, LIBERROR_EOR
);
11316 case GFC_ISYM_IS_CONTIGUOUS
:
11317 gfc_conv_intrinsic_is_contiguous (se
, expr
);
11320 case GFC_ISYM_ISNAN
:
11321 gfc_conv_intrinsic_isnan (se
, expr
);
11324 case GFC_ISYM_KILL
:
11325 conv_intrinsic_kill (se
, expr
);
11328 case GFC_ISYM_LSHIFT
:
11329 gfc_conv_intrinsic_shift (se
, expr
, false, false);
11332 case GFC_ISYM_RSHIFT
:
11333 gfc_conv_intrinsic_shift (se
, expr
, true, true);
11336 case GFC_ISYM_SHIFTA
:
11337 gfc_conv_intrinsic_shift (se
, expr
, true, true);
11340 case GFC_ISYM_SHIFTL
:
11341 gfc_conv_intrinsic_shift (se
, expr
, false, false);
11344 case GFC_ISYM_SHIFTR
:
11345 gfc_conv_intrinsic_shift (se
, expr
, true, false);
11348 case GFC_ISYM_ISHFT
:
11349 gfc_conv_intrinsic_ishft (se
, expr
);
11352 case GFC_ISYM_ISHFTC
:
11353 gfc_conv_intrinsic_ishftc (se
, expr
);
11356 case GFC_ISYM_LEADZ
:
11357 gfc_conv_intrinsic_leadz (se
, expr
);
11360 case GFC_ISYM_TRAILZ
:
11361 gfc_conv_intrinsic_trailz (se
, expr
);
11364 case GFC_ISYM_POPCNT
:
11365 gfc_conv_intrinsic_popcnt_poppar (se
, expr
, 0);
11368 case GFC_ISYM_POPPAR
:
11369 gfc_conv_intrinsic_popcnt_poppar (se
, expr
, 1);
11372 case GFC_ISYM_LBOUND
:
11373 gfc_conv_intrinsic_bound (se
, expr
, GFC_ISYM_LBOUND
);
11376 case GFC_ISYM_LCOBOUND
:
11377 conv_intrinsic_cobound (se
, expr
);
11380 case GFC_ISYM_TRANSPOSE
:
11381 /* The scalarizer has already been set up for reversed dimension access
11382 order ; now we just get the argument value normally. */
11383 gfc_conv_expr (se
, expr
->value
.function
.actual
->expr
);
11387 gfc_conv_intrinsic_len (se
, expr
);
11390 case GFC_ISYM_LEN_TRIM
:
11391 gfc_conv_intrinsic_len_trim (se
, expr
);
11395 gfc_conv_intrinsic_strcmp (se
, expr
, GE_EXPR
);
11399 gfc_conv_intrinsic_strcmp (se
, expr
, GT_EXPR
);
11403 gfc_conv_intrinsic_strcmp (se
, expr
, LE_EXPR
);
11407 gfc_conv_intrinsic_strcmp (se
, expr
, LT_EXPR
);
11410 case GFC_ISYM_MALLOC
:
11411 gfc_conv_intrinsic_malloc (se
, expr
);
11414 case GFC_ISYM_MASKL
:
11415 gfc_conv_intrinsic_mask (se
, expr
, 1);
11418 case GFC_ISYM_MASKR
:
11419 gfc_conv_intrinsic_mask (se
, expr
, 0);
11423 if (expr
->ts
.type
== BT_CHARACTER
)
11424 gfc_conv_intrinsic_minmax_char (se
, expr
, 1);
11426 gfc_conv_intrinsic_minmax (se
, expr
, GT_EXPR
);
11429 case GFC_ISYM_MAXLOC
:
11430 gfc_conv_intrinsic_minmaxloc (se
, expr
, GT_EXPR
);
11433 case GFC_ISYM_FINDLOC
:
11434 gfc_conv_intrinsic_findloc (se
, expr
);
11437 case GFC_ISYM_MAXVAL
:
11438 gfc_conv_intrinsic_minmaxval (se
, expr
, GT_EXPR
);
11441 case GFC_ISYM_MERGE
:
11442 gfc_conv_intrinsic_merge (se
, expr
);
11445 case GFC_ISYM_MERGE_BITS
:
11446 gfc_conv_intrinsic_merge_bits (se
, expr
);
11450 if (expr
->ts
.type
== BT_CHARACTER
)
11451 gfc_conv_intrinsic_minmax_char (se
, expr
, -1);
11453 gfc_conv_intrinsic_minmax (se
, expr
, LT_EXPR
);
11456 case GFC_ISYM_MINLOC
:
11457 gfc_conv_intrinsic_minmaxloc (se
, expr
, LT_EXPR
);
11460 case GFC_ISYM_MINVAL
:
11461 gfc_conv_intrinsic_minmaxval (se
, expr
, LT_EXPR
);
11464 case GFC_ISYM_NEAREST
:
11465 gfc_conv_intrinsic_nearest (se
, expr
);
11468 case GFC_ISYM_NORM2
:
11469 gfc_conv_intrinsic_arith (se
, expr
, PLUS_EXPR
, true);
11473 gfc_conv_intrinsic_not (se
, expr
);
11477 gfc_conv_intrinsic_bitop (se
, expr
, BIT_IOR_EXPR
);
11480 case GFC_ISYM_PARITY
:
11481 gfc_conv_intrinsic_arith (se
, expr
, NE_EXPR
, false);
11484 case GFC_ISYM_PRESENT
:
11485 gfc_conv_intrinsic_present (se
, expr
);
11488 case GFC_ISYM_PRODUCT
:
11489 gfc_conv_intrinsic_arith (se
, expr
, MULT_EXPR
, false);
11492 case GFC_ISYM_RANK
:
11493 gfc_conv_intrinsic_rank (se
, expr
);
11496 case GFC_ISYM_RRSPACING
:
11497 gfc_conv_intrinsic_rrspacing (se
, expr
);
11500 case GFC_ISYM_SET_EXPONENT
:
11501 gfc_conv_intrinsic_set_exponent (se
, expr
);
11504 case GFC_ISYM_SCALE
:
11505 gfc_conv_intrinsic_scale (se
, expr
);
11508 case GFC_ISYM_SHAPE
:
11509 gfc_conv_intrinsic_bound (se
, expr
, GFC_ISYM_SHAPE
);
11512 case GFC_ISYM_SIGN
:
11513 gfc_conv_intrinsic_sign (se
, expr
);
11516 case GFC_ISYM_SIZE
:
11517 gfc_conv_intrinsic_size (se
, expr
);
11520 case GFC_ISYM_SIZEOF
:
11521 case GFC_ISYM_C_SIZEOF
:
11522 gfc_conv_intrinsic_sizeof (se
, expr
);
11525 case GFC_ISYM_STORAGE_SIZE
:
11526 gfc_conv_intrinsic_storage_size (se
, expr
);
11529 case GFC_ISYM_SPACING
:
11530 gfc_conv_intrinsic_spacing (se
, expr
);
11533 case GFC_ISYM_STRIDE
:
11534 conv_intrinsic_stride (se
, expr
);
11538 gfc_conv_intrinsic_arith (se
, expr
, PLUS_EXPR
, false);
11541 case GFC_ISYM_TEAM_NUMBER
:
11542 conv_intrinsic_team_number (se
, expr
);
11545 case GFC_ISYM_TRANSFER
:
11546 if (se
->ss
&& se
->ss
->info
->useflags
)
11547 /* Access the previously obtained result. */
11548 gfc_conv_tmp_array_ref (se
);
11550 gfc_conv_intrinsic_transfer (se
, expr
);
11553 case GFC_ISYM_TTYNAM
:
11554 gfc_conv_intrinsic_ttynam (se
, expr
);
11557 case GFC_ISYM_UBOUND
:
11558 gfc_conv_intrinsic_bound (se
, expr
, GFC_ISYM_UBOUND
);
11561 case GFC_ISYM_UCOBOUND
:
11562 conv_intrinsic_cobound (se
, expr
);
11566 gfc_conv_intrinsic_bitop (se
, expr
, BIT_XOR_EXPR
);
11570 gfc_conv_intrinsic_loc (se
, expr
);
11573 case GFC_ISYM_THIS_IMAGE
:
11574 /* For num_images() == 1, handle as LCOBOUND. */
11575 if (expr
->value
.function
.actual
->expr
11576 && flag_coarray
== GFC_FCOARRAY_SINGLE
)
11577 conv_intrinsic_cobound (se
, expr
);
11579 trans_this_image (se
, expr
);
11582 case GFC_ISYM_IMAGE_INDEX
:
11583 trans_image_index (se
, expr
);
11586 case GFC_ISYM_IMAGE_STATUS
:
11587 conv_intrinsic_image_status (se
, expr
);
11590 case GFC_ISYM_NUM_IMAGES
:
11591 trans_num_images (se
, expr
);
11594 case GFC_ISYM_ACCESS
:
11595 case GFC_ISYM_CHDIR
:
11596 case GFC_ISYM_CHMOD
:
11597 case GFC_ISYM_DTIME
:
11598 case GFC_ISYM_ETIME
:
11599 case GFC_ISYM_EXTENDS_TYPE_OF
:
11600 case GFC_ISYM_FGET
:
11601 case GFC_ISYM_FGETC
:
11602 case GFC_ISYM_FNUM
:
11603 case GFC_ISYM_FPUT
:
11604 case GFC_ISYM_FPUTC
:
11605 case GFC_ISYM_FSTAT
:
11606 case GFC_ISYM_FTELL
:
11607 case GFC_ISYM_GETCWD
:
11608 case GFC_ISYM_GETGID
:
11609 case GFC_ISYM_GETPID
:
11610 case GFC_ISYM_GETUID
:
11611 case GFC_ISYM_HOSTNM
:
11612 case GFC_ISYM_IERRNO
:
11613 case GFC_ISYM_IRAND
:
11614 case GFC_ISYM_ISATTY
:
11616 case GFC_ISYM_LINK
:
11617 case GFC_ISYM_LSTAT
:
11618 case GFC_ISYM_MATMUL
:
11619 case GFC_ISYM_MCLOCK
:
11620 case GFC_ISYM_MCLOCK8
:
11621 case GFC_ISYM_RAND
:
11622 case GFC_ISYM_RENAME
:
11623 case GFC_ISYM_SECOND
:
11624 case GFC_ISYM_SECNDS
:
11625 case GFC_ISYM_SIGNAL
:
11626 case GFC_ISYM_STAT
:
11627 case GFC_ISYM_SYMLNK
:
11628 case GFC_ISYM_SYSTEM
:
11629 case GFC_ISYM_TIME
:
11630 case GFC_ISYM_TIME8
:
11631 case GFC_ISYM_UMASK
:
11632 case GFC_ISYM_UNLINK
:
11634 gfc_conv_intrinsic_funcall (se
, expr
);
11637 case GFC_ISYM_EOSHIFT
:
11638 case GFC_ISYM_PACK
:
11639 case GFC_ISYM_RESHAPE
:
11640 /* For those, expr->rank should always be >0 and thus the if above the
11641 switch should have matched. */
11642 gcc_unreachable ();
11646 gfc_conv_intrinsic_lib_function (se
, expr
);
11653 walk_inline_intrinsic_transpose (gfc_ss
*ss
, gfc_expr
*expr
)
11655 gfc_ss
*arg_ss
, *tmp_ss
;
11656 gfc_actual_arglist
*arg
;
11658 arg
= expr
->value
.function
.actual
;
11660 gcc_assert (arg
->expr
);
11662 arg_ss
= gfc_walk_subexpr (gfc_ss_terminator
, arg
->expr
);
11663 gcc_assert (arg_ss
!= gfc_ss_terminator
);
11665 for (tmp_ss
= arg_ss
; ; tmp_ss
= tmp_ss
->next
)
11667 if (tmp_ss
->info
->type
!= GFC_SS_SCALAR
11668 && tmp_ss
->info
->type
!= GFC_SS_REFERENCE
)
11670 gcc_assert (tmp_ss
->dimen
== 2);
11672 /* We just invert dimensions. */
11673 std::swap (tmp_ss
->dim
[0], tmp_ss
->dim
[1]);
11676 /* Stop when tmp_ss points to the last valid element of the chain... */
11677 if (tmp_ss
->next
== gfc_ss_terminator
)
11681 /* ... so that we can attach the rest of the chain to it. */
11688 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
11689 This has the side effect of reversing the nested list, so there is no
11690 need to call gfc_reverse_ss on it (the given list is assumed not to be
11694 nest_loop_dimension (gfc_ss
*ss
, int dim
)
11697 gfc_ss
*new_ss
, *prev_ss
= gfc_ss_terminator
;
11698 gfc_loopinfo
*new_loop
;
11700 gcc_assert (ss
!= gfc_ss_terminator
);
11702 for (; ss
!= gfc_ss_terminator
; ss
= ss
->next
)
11704 new_ss
= gfc_get_ss ();
11705 new_ss
->next
= prev_ss
;
11706 new_ss
->parent
= ss
;
11707 new_ss
->info
= ss
->info
;
11708 new_ss
->info
->refcount
++;
11709 if (ss
->dimen
!= 0)
11711 gcc_assert (ss
->info
->type
!= GFC_SS_SCALAR
11712 && ss
->info
->type
!= GFC_SS_REFERENCE
);
11715 new_ss
->dim
[0] = ss
->dim
[dim
];
11717 gcc_assert (dim
< ss
->dimen
);
11719 ss_dim
= --ss
->dimen
;
11720 for (i
= dim
; i
< ss_dim
; i
++)
11721 ss
->dim
[i
] = ss
->dim
[i
+ 1];
11723 ss
->dim
[ss_dim
] = 0;
11729 ss
->nested_ss
->parent
= new_ss
;
11730 new_ss
->nested_ss
= ss
->nested_ss
;
11732 ss
->nested_ss
= new_ss
;
11735 new_loop
= gfc_get_loopinfo ();
11736 gfc_init_loopinfo (new_loop
);
11738 gcc_assert (prev_ss
!= NULL
);
11739 gcc_assert (prev_ss
!= gfc_ss_terminator
);
11740 gfc_add_ss_to_loop (new_loop
, prev_ss
);
11741 return new_ss
->parent
;
11745 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
11746 is to be inlined. */
11749 walk_inline_intrinsic_arith (gfc_ss
*ss
, gfc_expr
*expr
)
11751 gfc_ss
*tmp_ss
, *tail
, *array_ss
;
11752 gfc_actual_arglist
*arg1
, *arg2
, *arg3
;
11754 bool scalar_mask
= false;
11756 /* The rank of the result will be determined later. */
11757 arg1
= expr
->value
.function
.actual
;
11760 gcc_assert (arg3
!= NULL
);
11762 if (expr
->rank
== 0)
11765 tmp_ss
= gfc_ss_terminator
;
11771 mask_ss
= gfc_walk_subexpr (tmp_ss
, arg3
->expr
);
11772 if (mask_ss
== tmp_ss
)
11778 array_ss
= gfc_walk_subexpr (tmp_ss
, arg1
->expr
);
11779 gcc_assert (array_ss
!= tmp_ss
);
11781 /* Odd thing: If the mask is scalar, it is used by the frontend after
11782 the array (to make an if around the nested loop). Thus it shall
11783 be after array_ss once the gfc_ss list is reversed. */
11785 tmp_ss
= gfc_get_scalar_ss (array_ss
, arg3
->expr
);
11789 /* "Hide" the dimension on which we will sum in the first arg's scalarization
11791 sum_dim
= mpz_get_si (arg2
->expr
->value
.integer
) - 1;
11792 tail
= nest_loop_dimension (tmp_ss
, sum_dim
);
11799 /* Create the gfc_ss list for the arguments to MINLOC or MAXLOC when the
11800 function is to be inlined. */
11803 walk_inline_intrinsic_minmaxloc (gfc_ss
*ss
, gfc_expr
*expr ATTRIBUTE_UNUSED
)
11805 if (expr
->rank
== 0)
11808 return gfc_get_array_ss (ss
, expr
, 1, GFC_SS_INTRINSIC
);
11813 walk_inline_intrinsic_function (gfc_ss
* ss
, gfc_expr
* expr
)
11816 switch (expr
->value
.function
.isym
->id
)
11818 case GFC_ISYM_PRODUCT
:
11820 return walk_inline_intrinsic_arith (ss
, expr
);
11822 case GFC_ISYM_TRANSPOSE
:
11823 return walk_inline_intrinsic_transpose (ss
, expr
);
11825 case GFC_ISYM_MAXLOC
:
11826 case GFC_ISYM_MINLOC
:
11827 return walk_inline_intrinsic_minmaxloc (ss
, expr
);
11830 gcc_unreachable ();
11832 gcc_unreachable ();
11836 /* This generates code to execute before entering the scalarization loop.
11837 Currently does nothing. */
11840 gfc_add_intrinsic_ss_code (gfc_loopinfo
* loop ATTRIBUTE_UNUSED
, gfc_ss
* ss
)
11842 switch (ss
->info
->expr
->value
.function
.isym
->id
)
11844 case GFC_ISYM_UBOUND
:
11845 case GFC_ISYM_LBOUND
:
11846 case GFC_ISYM_UCOBOUND
:
11847 case GFC_ISYM_LCOBOUND
:
11848 case GFC_ISYM_MAXLOC
:
11849 case GFC_ISYM_MINLOC
:
11850 case GFC_ISYM_THIS_IMAGE
:
11851 case GFC_ISYM_SHAPE
:
11855 gcc_unreachable ();
11860 /* The LBOUND, LCOBOUND, UBOUND, UCOBOUND, and SHAPE intrinsics with
11861 one parameter are expanded into code inside the scalarization loop. */
11864 gfc_walk_intrinsic_bound (gfc_ss
* ss
, gfc_expr
* expr
)
11866 if (expr
->value
.function
.actual
->expr
->ts
.type
== BT_CLASS
)
11867 gfc_add_class_array_ref (expr
->value
.function
.actual
->expr
);
11869 /* The two argument version returns a scalar. */
11870 if (expr
->value
.function
.isym
->id
!= GFC_ISYM_SHAPE
11871 && expr
->value
.function
.actual
->next
->expr
)
11874 return gfc_get_array_ss (ss
, expr
, 1, GFC_SS_INTRINSIC
);
11878 /* Walk an intrinsic array libcall. */
11881 gfc_walk_intrinsic_libfunc (gfc_ss
* ss
, gfc_expr
* expr
)
11883 gcc_assert (expr
->rank
> 0);
11884 return gfc_get_array_ss (ss
, expr
, expr
->rank
, GFC_SS_FUNCTION
);
11888 /* Return whether the function call expression EXPR will be expanded
11889 inline by gfc_conv_intrinsic_function. */
11892 gfc_inline_intrinsic_function_p (gfc_expr
*expr
)
11894 gfc_actual_arglist
*args
, *dim_arg
, *mask_arg
;
11895 gfc_expr
*maskexpr
;
11897 gfc_intrinsic_sym
*isym
= expr
->value
.function
.isym
;
11903 case GFC_ISYM_PRODUCT
:
11905 /* Disable inline expansion if code size matters. */
11909 args
= expr
->value
.function
.actual
;
11910 dim_arg
= args
->next
;
11912 /* We need to be able to subset the SUM argument at compile-time. */
11913 if (dim_arg
->expr
&& dim_arg
->expr
->expr_type
!= EXPR_CONSTANT
)
11916 /* FIXME: If MASK is optional for a more than two-dimensional
11917 argument, the scalarizer gets confused if the mask is
11918 absent. See PR 82995. For now, fall back to the library
11921 mask_arg
= dim_arg
->next
;
11922 maskexpr
= mask_arg
->expr
;
11924 if (expr
->rank
> 0 && maskexpr
&& maskexpr
->expr_type
== EXPR_VARIABLE
11925 && maskexpr
->symtree
->n
.sym
->attr
.dummy
11926 && maskexpr
->symtree
->n
.sym
->attr
.optional
)
11931 case GFC_ISYM_TRANSPOSE
:
11934 case GFC_ISYM_MINLOC
:
11935 case GFC_ISYM_MAXLOC
:
11937 if ((isym
->id
== GFC_ISYM_MINLOC
11938 && (flag_inline_intrinsics
11939 & GFC_FLAG_INLINE_INTRINSIC_MINLOC
) == 0)
11940 || (isym
->id
== GFC_ISYM_MAXLOC
11941 && (flag_inline_intrinsics
11942 & GFC_FLAG_INLINE_INTRINSIC_MAXLOC
) == 0))
11945 gfc_actual_arglist
*array_arg
= expr
->value
.function
.actual
;
11946 gfc_actual_arglist
*dim_arg
= array_arg
->next
;
11948 gfc_expr
*array
= array_arg
->expr
;
11949 gfc_expr
*dim
= dim_arg
->expr
;
11951 if (!(array
->ts
.type
== BT_INTEGER
11952 || array
->ts
.type
== BT_REAL
))
11955 if (array
->rank
== 1)
11958 if (dim
== nullptr)
11970 /* Returns nonzero if the specified intrinsic function call maps directly to
11971 an external library call. Should only be used for functions that return
11975 gfc_is_intrinsic_libcall (gfc_expr
* expr
)
11977 gcc_assert (expr
->expr_type
== EXPR_FUNCTION
&& expr
->value
.function
.isym
);
11978 gcc_assert (expr
->rank
> 0);
11980 if (gfc_inline_intrinsic_function_p (expr
))
11983 switch (expr
->value
.function
.isym
->id
)
11987 case GFC_ISYM_COUNT
:
11988 case GFC_ISYM_FINDLOC
:
11990 case GFC_ISYM_IANY
:
11991 case GFC_ISYM_IALL
:
11992 case GFC_ISYM_IPARITY
:
11993 case GFC_ISYM_MATMUL
:
11994 case GFC_ISYM_MAXLOC
:
11995 case GFC_ISYM_MAXVAL
:
11996 case GFC_ISYM_MINLOC
:
11997 case GFC_ISYM_MINVAL
:
11998 case GFC_ISYM_NORM2
:
11999 case GFC_ISYM_PARITY
:
12000 case GFC_ISYM_PRODUCT
:
12002 case GFC_ISYM_SPREAD
:
12004 /* Ignore absent optional parameters. */
12007 case GFC_ISYM_CSHIFT
:
12008 case GFC_ISYM_EOSHIFT
:
12009 case GFC_ISYM_GET_TEAM
:
12010 case GFC_ISYM_FAILED_IMAGES
:
12011 case GFC_ISYM_STOPPED_IMAGES
:
12012 case GFC_ISYM_PACK
:
12013 case GFC_ISYM_RESHAPE
:
12014 case GFC_ISYM_UNPACK
:
12015 /* Pass absent optional parameters. */
12023 /* Walk an intrinsic function. */
12025 gfc_walk_intrinsic_function (gfc_ss
* ss
, gfc_expr
* expr
,
12026 gfc_intrinsic_sym
* isym
)
12030 if (isym
->elemental
)
12031 return gfc_walk_elemental_function_args (ss
, expr
->value
.function
.actual
,
12032 expr
->value
.function
.isym
,
12035 if (expr
->rank
== 0 && expr
->corank
== 0)
12038 if (gfc_inline_intrinsic_function_p (expr
))
12039 return walk_inline_intrinsic_function (ss
, expr
);
12041 if (expr
->rank
!= 0 && gfc_is_intrinsic_libcall (expr
))
12042 return gfc_walk_intrinsic_libfunc (ss
, expr
);
12044 /* Special cases. */
12047 case GFC_ISYM_LBOUND
:
12048 case GFC_ISYM_LCOBOUND
:
12049 case GFC_ISYM_UBOUND
:
12050 case GFC_ISYM_UCOBOUND
:
12051 case GFC_ISYM_THIS_IMAGE
:
12052 case GFC_ISYM_SHAPE
:
12053 return gfc_walk_intrinsic_bound (ss
, expr
);
12055 case GFC_ISYM_TRANSFER
:
12056 case GFC_ISYM_CAF_GET
:
12057 return gfc_walk_intrinsic_libfunc (ss
, expr
);
12060 /* This probably meant someone forgot to add an intrinsic to the above
12061 list(s) when they implemented it, or something's gone horribly
12063 gcc_unreachable ();
12068 conv_co_collective (gfc_code
*code
)
12071 stmtblock_t block
, post_block
;
12072 tree fndecl
, array
= NULL_TREE
, strlen
, image_index
, stat
, errmsg
, errmsg_len
;
12073 gfc_expr
*image_idx_expr
, *stat_expr
, *errmsg_expr
, *opr_expr
;
12075 gfc_start_block (&block
);
12076 gfc_init_block (&post_block
);
12078 if (code
->resolved_isym
->id
== GFC_ISYM_CO_REDUCE
)
12080 opr_expr
= code
->ext
.actual
->next
->expr
;
12081 image_idx_expr
= code
->ext
.actual
->next
->next
->expr
;
12082 stat_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
12083 errmsg_expr
= code
->ext
.actual
->next
->next
->next
->next
->expr
;
12088 image_idx_expr
= code
->ext
.actual
->next
->expr
;
12089 stat_expr
= code
->ext
.actual
->next
->next
->expr
;
12090 errmsg_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
12096 gfc_init_se (&argse
, NULL
);
12097 gfc_conv_expr (&argse
, stat_expr
);
12098 gfc_add_block_to_block (&block
, &argse
.pre
);
12099 gfc_add_block_to_block (&post_block
, &argse
.post
);
12101 if (flag_coarray
!= GFC_FCOARRAY_SINGLE
)
12102 stat
= gfc_build_addr_expr (NULL_TREE
, stat
);
12104 else if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
12107 stat
= null_pointer_node
;
12109 /* Early exit for GFC_FCOARRAY_SINGLE. */
12110 if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
12112 if (stat
!= NULL_TREE
)
12114 /* For optional stats, check the pointer is valid before zero'ing. */
12115 if (gfc_expr_attr (stat_expr
).optional
)
12118 stmtblock_t ass_block
;
12119 gfc_start_block (&ass_block
);
12120 gfc_add_modify (&ass_block
, stat
,
12121 fold_convert (TREE_TYPE (stat
),
12122 integer_zero_node
));
12123 tmp
= fold_build2 (NE_EXPR
, logical_type_node
,
12124 gfc_build_addr_expr (NULL_TREE
, stat
),
12125 null_pointer_node
);
12126 tmp
= fold_build3 (COND_EXPR
, void_type_node
, tmp
,
12127 gfc_finish_block (&ass_block
),
12128 build_empty_stmt (input_location
));
12129 gfc_add_expr_to_block (&block
, tmp
);
12132 gfc_add_modify (&block
, stat
,
12133 fold_convert (TREE_TYPE (stat
), integer_zero_node
));
12135 return gfc_finish_block (&block
);
12138 gfc_symbol
*derived
= code
->ext
.actual
->expr
->ts
.type
== BT_DERIVED
12139 ? code
->ext
.actual
->expr
->ts
.u
.derived
: NULL
;
12141 /* Handle the array. */
12142 gfc_init_se (&argse
, NULL
);
12143 if (!derived
|| !derived
->attr
.alloc_comp
12144 || code
->resolved_isym
->id
!= GFC_ISYM_CO_BROADCAST
)
12146 if (code
->ext
.actual
->expr
->rank
== 0)
12148 symbol_attribute attr
;
12149 gfc_clear_attr (&attr
);
12150 gfc_init_se (&argse
, NULL
);
12151 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
12152 gfc_add_block_to_block (&block
, &argse
.pre
);
12153 gfc_add_block_to_block (&post_block
, &argse
.post
);
12154 array
= gfc_conv_scalar_to_descriptor (&argse
, argse
.expr
, attr
);
12155 array
= gfc_build_addr_expr (NULL_TREE
, array
);
12159 argse
.want_pointer
= 1;
12160 gfc_conv_expr_descriptor (&argse
, code
->ext
.actual
->expr
);
12161 array
= argse
.expr
;
12165 gfc_add_block_to_block (&block
, &argse
.pre
);
12166 gfc_add_block_to_block (&post_block
, &argse
.post
);
12168 if (code
->ext
.actual
->expr
->ts
.type
== BT_CHARACTER
)
12169 strlen
= argse
.string_length
;
12171 strlen
= integer_zero_node
;
12174 if (image_idx_expr
)
12176 gfc_init_se (&argse
, NULL
);
12177 gfc_conv_expr (&argse
, image_idx_expr
);
12178 gfc_add_block_to_block (&block
, &argse
.pre
);
12179 gfc_add_block_to_block (&post_block
, &argse
.post
);
12180 image_index
= fold_convert (integer_type_node
, argse
.expr
);
12183 image_index
= integer_zero_node
;
12188 gfc_init_se (&argse
, NULL
);
12189 gfc_conv_expr (&argse
, errmsg_expr
);
12190 gfc_add_block_to_block (&block
, &argse
.pre
);
12191 gfc_add_block_to_block (&post_block
, &argse
.post
);
12192 errmsg
= argse
.expr
;
12193 errmsg_len
= fold_convert (size_type_node
, argse
.string_length
);
12197 errmsg
= null_pointer_node
;
12198 errmsg_len
= build_zero_cst (size_type_node
);
12201 /* Generate the function call. */
12202 switch (code
->resolved_isym
->id
)
12204 case GFC_ISYM_CO_BROADCAST
:
12205 fndecl
= gfor_fndecl_co_broadcast
;
12207 case GFC_ISYM_CO_MAX
:
12208 fndecl
= gfor_fndecl_co_max
;
12210 case GFC_ISYM_CO_MIN
:
12211 fndecl
= gfor_fndecl_co_min
;
12213 case GFC_ISYM_CO_REDUCE
:
12214 fndecl
= gfor_fndecl_co_reduce
;
12216 case GFC_ISYM_CO_SUM
:
12217 fndecl
= gfor_fndecl_co_sum
;
12220 gcc_unreachable ();
12223 if (derived
&& derived
->attr
.alloc_comp
12224 && code
->resolved_isym
->id
== GFC_ISYM_CO_BROADCAST
)
12225 /* The derived type has the attribute 'alloc_comp'. */
12227 tree tmp
= gfc_bcast_alloc_comp (derived
, code
->ext
.actual
->expr
,
12228 code
->ext
.actual
->expr
->rank
,
12229 image_index
, stat
, errmsg
, errmsg_len
);
12230 gfc_add_expr_to_block (&block
, tmp
);
12234 if (code
->resolved_isym
->id
== GFC_ISYM_CO_SUM
12235 || code
->resolved_isym
->id
== GFC_ISYM_CO_BROADCAST
)
12236 fndecl
= build_call_expr_loc (input_location
, fndecl
, 5, array
,
12237 image_index
, stat
, errmsg
, errmsg_len
);
12238 else if (code
->resolved_isym
->id
!= GFC_ISYM_CO_REDUCE
)
12239 fndecl
= build_call_expr_loc (input_location
, fndecl
, 6, array
,
12240 image_index
, stat
, errmsg
,
12241 strlen
, errmsg_len
);
12244 tree opr
, opr_flags
;
12246 // FIXME: Handle TS29113's bind(C) strings with descriptor.
12248 if (gfc_is_proc_ptr_comp (opr_expr
))
12250 gfc_symbol
*sym
= gfc_get_proc_ptr_comp (opr_expr
)->ts
.interface
;
12251 opr_flag_int
= sym
->attr
.dimension
12252 || (sym
->ts
.type
== BT_CHARACTER
12253 && !sym
->attr
.is_bind_c
)
12254 ? GFC_CAF_BYREF
: 0;
12255 opr_flag_int
|= opr_expr
->ts
.type
== BT_CHARACTER
12256 && !sym
->attr
.is_bind_c
12257 ? GFC_CAF_HIDDENLEN
: 0;
12258 opr_flag_int
|= sym
->formal
->sym
->attr
.value
12259 ? GFC_CAF_ARG_VALUE
: 0;
12263 opr_flag_int
= gfc_return_by_reference (opr_expr
->symtree
->n
.sym
)
12264 ? GFC_CAF_BYREF
: 0;
12265 opr_flag_int
|= opr_expr
->ts
.type
== BT_CHARACTER
12266 && !opr_expr
->symtree
->n
.sym
->attr
.is_bind_c
12267 ? GFC_CAF_HIDDENLEN
: 0;
12268 opr_flag_int
|= opr_expr
->symtree
->n
.sym
->formal
->sym
->attr
.value
12269 ? GFC_CAF_ARG_VALUE
: 0;
12271 opr_flags
= build_int_cst (integer_type_node
, opr_flag_int
);
12272 gfc_conv_expr (&argse
, opr_expr
);
12274 fndecl
= build_call_expr_loc (input_location
, fndecl
, 8, array
, opr
,
12275 opr_flags
, image_index
, stat
, errmsg
,
12276 strlen
, errmsg_len
);
12280 gfc_add_expr_to_block (&block
, fndecl
);
12281 gfc_add_block_to_block (&block
, &post_block
);
12283 return gfc_finish_block (&block
);
12288 conv_intrinsic_atomic_op (gfc_code
*code
)
12291 tree tmp
, atom
, value
, old
= NULL_TREE
, stat
= NULL_TREE
;
12292 stmtblock_t block
, post_block
;
12293 gfc_expr
*atom_expr
= code
->ext
.actual
->expr
;
12294 gfc_expr
*stat_expr
;
12295 built_in_function fn
;
12297 if (atom_expr
->expr_type
== EXPR_FUNCTION
12298 && atom_expr
->value
.function
.isym
12299 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
12300 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
12302 gfc_start_block (&block
);
12303 gfc_init_block (&post_block
);
12305 gfc_init_se (&argse
, NULL
);
12306 argse
.want_pointer
= 1;
12307 gfc_conv_expr (&argse
, atom_expr
);
12308 gfc_add_block_to_block (&block
, &argse
.pre
);
12309 gfc_add_block_to_block (&post_block
, &argse
.post
);
12312 gfc_init_se (&argse
, NULL
);
12313 if (flag_coarray
== GFC_FCOARRAY_LIB
12314 && code
->ext
.actual
->next
->expr
->ts
.kind
== atom_expr
->ts
.kind
)
12315 argse
.want_pointer
= 1;
12316 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->expr
);
12317 gfc_add_block_to_block (&block
, &argse
.pre
);
12318 gfc_add_block_to_block (&post_block
, &argse
.post
);
12319 value
= argse
.expr
;
12321 switch (code
->resolved_isym
->id
)
12323 case GFC_ISYM_ATOMIC_ADD
:
12324 case GFC_ISYM_ATOMIC_AND
:
12325 case GFC_ISYM_ATOMIC_DEF
:
12326 case GFC_ISYM_ATOMIC_OR
:
12327 case GFC_ISYM_ATOMIC_XOR
:
12328 stat_expr
= code
->ext
.actual
->next
->next
->expr
;
12329 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12330 old
= null_pointer_node
;
12333 gfc_init_se (&argse
, NULL
);
12334 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12335 argse
.want_pointer
= 1;
12336 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->expr
);
12337 gfc_add_block_to_block (&block
, &argse
.pre
);
12338 gfc_add_block_to_block (&post_block
, &argse
.post
);
12340 stat_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
12344 if (stat_expr
!= NULL
)
12346 gcc_assert (stat_expr
->expr_type
== EXPR_VARIABLE
);
12347 gfc_init_se (&argse
, NULL
);
12348 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12349 argse
.want_pointer
= 1;
12350 gfc_conv_expr_val (&argse
, stat_expr
);
12351 gfc_add_block_to_block (&block
, &argse
.pre
);
12352 gfc_add_block_to_block (&post_block
, &argse
.post
);
12355 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
12356 stat
= null_pointer_node
;
12358 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12360 tree image_index
, caf_decl
, offset
, token
;
12363 switch (code
->resolved_isym
->id
)
12365 case GFC_ISYM_ATOMIC_ADD
:
12366 case GFC_ISYM_ATOMIC_FETCH_ADD
:
12367 op
= (int) GFC_CAF_ATOMIC_ADD
;
12369 case GFC_ISYM_ATOMIC_AND
:
12370 case GFC_ISYM_ATOMIC_FETCH_AND
:
12371 op
= (int) GFC_CAF_ATOMIC_AND
;
12373 case GFC_ISYM_ATOMIC_OR
:
12374 case GFC_ISYM_ATOMIC_FETCH_OR
:
12375 op
= (int) GFC_CAF_ATOMIC_OR
;
12377 case GFC_ISYM_ATOMIC_XOR
:
12378 case GFC_ISYM_ATOMIC_FETCH_XOR
:
12379 op
= (int) GFC_CAF_ATOMIC_XOR
;
12381 case GFC_ISYM_ATOMIC_DEF
:
12382 op
= 0; /* Unused. */
12385 gcc_unreachable ();
12388 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
12389 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
12390 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
12392 if (gfc_is_coindexed (atom_expr
))
12393 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
12395 image_index
= integer_zero_node
;
12397 if (!POINTER_TYPE_P (TREE_TYPE (value
)))
12399 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (atom
)), "value");
12400 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), value
));
12401 value
= gfc_build_addr_expr (NULL_TREE
, tmp
);
12404 gfc_init_se (&argse
, NULL
);
12405 gfc_get_caf_token_offset (&argse
, &token
, &offset
, caf_decl
, atom
,
12408 gfc_add_block_to_block (&block
, &argse
.pre
);
12409 if (code
->resolved_isym
->id
== GFC_ISYM_ATOMIC_DEF
)
12410 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_def
, 7,
12411 token
, offset
, image_index
, value
, stat
,
12412 build_int_cst (integer_type_node
,
12413 (int) atom_expr
->ts
.type
),
12414 build_int_cst (integer_type_node
,
12415 (int) atom_expr
->ts
.kind
));
12417 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_op
, 9,
12418 build_int_cst (integer_type_node
, op
),
12419 token
, offset
, image_index
, value
, old
, stat
,
12420 build_int_cst (integer_type_node
,
12421 (int) atom_expr
->ts
.type
),
12422 build_int_cst (integer_type_node
,
12423 (int) atom_expr
->ts
.kind
));
12425 gfc_add_expr_to_block (&block
, tmp
);
12426 gfc_add_block_to_block (&block
, &argse
.post
);
12427 gfc_add_block_to_block (&block
, &post_block
);
12428 return gfc_finish_block (&block
);
12432 switch (code
->resolved_isym
->id
)
12434 case GFC_ISYM_ATOMIC_ADD
:
12435 case GFC_ISYM_ATOMIC_FETCH_ADD
:
12436 fn
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
12438 case GFC_ISYM_ATOMIC_AND
:
12439 case GFC_ISYM_ATOMIC_FETCH_AND
:
12440 fn
= BUILT_IN_ATOMIC_FETCH_AND_N
;
12442 case GFC_ISYM_ATOMIC_DEF
:
12443 fn
= BUILT_IN_ATOMIC_STORE_N
;
12445 case GFC_ISYM_ATOMIC_OR
:
12446 case GFC_ISYM_ATOMIC_FETCH_OR
:
12447 fn
= BUILT_IN_ATOMIC_FETCH_OR_N
;
12449 case GFC_ISYM_ATOMIC_XOR
:
12450 case GFC_ISYM_ATOMIC_FETCH_XOR
:
12451 fn
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
12454 gcc_unreachable ();
12457 tmp
= TREE_TYPE (TREE_TYPE (atom
));
12458 fn
= (built_in_function
) ((int) fn
12459 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
12461 tree itype
= TREE_TYPE (TREE_TYPE (atom
));
12462 tmp
= builtin_decl_explicit (fn
);
12464 switch (code
->resolved_isym
->id
)
12466 case GFC_ISYM_ATOMIC_ADD
:
12467 case GFC_ISYM_ATOMIC_AND
:
12468 case GFC_ISYM_ATOMIC_DEF
:
12469 case GFC_ISYM_ATOMIC_OR
:
12470 case GFC_ISYM_ATOMIC_XOR
:
12471 tmp
= build_call_expr_loc (input_location
, tmp
, 3, atom
,
12472 fold_convert (itype
, value
),
12473 build_int_cst (NULL
, MEMMODEL_RELAXED
));
12474 gfc_add_expr_to_block (&block
, tmp
);
12477 tmp
= build_call_expr_loc (input_location
, tmp
, 3, atom
,
12478 fold_convert (itype
, value
),
12479 build_int_cst (NULL
, MEMMODEL_RELAXED
));
12480 gfc_add_modify (&block
, old
, fold_convert (TREE_TYPE (old
), tmp
));
12484 if (stat
!= NULL_TREE
)
12485 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
12486 gfc_add_block_to_block (&block
, &post_block
);
12487 return gfc_finish_block (&block
);
12492 conv_intrinsic_atomic_ref (gfc_code
*code
)
12495 tree tmp
, atom
, value
, stat
= NULL_TREE
;
12496 stmtblock_t block
, post_block
;
12497 built_in_function fn
;
12498 gfc_expr
*atom_expr
= code
->ext
.actual
->next
->expr
;
12500 if (atom_expr
->expr_type
== EXPR_FUNCTION
12501 && atom_expr
->value
.function
.isym
12502 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
12503 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
12505 gfc_start_block (&block
);
12506 gfc_init_block (&post_block
);
12507 gfc_init_se (&argse
, NULL
);
12508 argse
.want_pointer
= 1;
12509 gfc_conv_expr (&argse
, atom_expr
);
12510 gfc_add_block_to_block (&block
, &argse
.pre
);
12511 gfc_add_block_to_block (&post_block
, &argse
.post
);
12514 gfc_init_se (&argse
, NULL
);
12515 if (flag_coarray
== GFC_FCOARRAY_LIB
12516 && code
->ext
.actual
->expr
->ts
.kind
== atom_expr
->ts
.kind
)
12517 argse
.want_pointer
= 1;
12518 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
12519 gfc_add_block_to_block (&block
, &argse
.pre
);
12520 gfc_add_block_to_block (&post_block
, &argse
.post
);
12521 value
= argse
.expr
;
12524 if (code
->ext
.actual
->next
->next
->expr
!= NULL
)
12526 gcc_assert (code
->ext
.actual
->next
->next
->expr
->expr_type
12528 gfc_init_se (&argse
, NULL
);
12529 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12530 argse
.want_pointer
= 1;
12531 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->next
->expr
);
12532 gfc_add_block_to_block (&block
, &argse
.pre
);
12533 gfc_add_block_to_block (&post_block
, &argse
.post
);
12536 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
12537 stat
= null_pointer_node
;
12539 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12541 tree image_index
, caf_decl
, offset
, token
;
12542 tree orig_value
= NULL_TREE
, vardecl
= NULL_TREE
;
12544 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
12545 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
12546 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
12548 if (gfc_is_coindexed (atom_expr
))
12549 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
12551 image_index
= integer_zero_node
;
12553 gfc_init_se (&argse
, NULL
);
12554 gfc_get_caf_token_offset (&argse
, &token
, &offset
, caf_decl
, atom
,
12556 gfc_add_block_to_block (&block
, &argse
.pre
);
12558 /* Different type, need type conversion. */
12559 if (!POINTER_TYPE_P (TREE_TYPE (value
)))
12561 vardecl
= gfc_create_var (TREE_TYPE (TREE_TYPE (atom
)), "value");
12562 orig_value
= value
;
12563 value
= gfc_build_addr_expr (NULL_TREE
, vardecl
);
12566 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_ref
, 7,
12567 token
, offset
, image_index
, value
, stat
,
12568 build_int_cst (integer_type_node
,
12569 (int) atom_expr
->ts
.type
),
12570 build_int_cst (integer_type_node
,
12571 (int) atom_expr
->ts
.kind
));
12572 gfc_add_expr_to_block (&block
, tmp
);
12573 if (vardecl
!= NULL_TREE
)
12574 gfc_add_modify (&block
, orig_value
,
12575 fold_convert (TREE_TYPE (orig_value
), vardecl
));
12576 gfc_add_block_to_block (&block
, &argse
.post
);
12577 gfc_add_block_to_block (&block
, &post_block
);
12578 return gfc_finish_block (&block
);
12581 tmp
= TREE_TYPE (TREE_TYPE (atom
));
12582 fn
= (built_in_function
) ((int) BUILT_IN_ATOMIC_LOAD_N
12583 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
12585 tmp
= builtin_decl_explicit (fn
);
12586 tmp
= build_call_expr_loc (input_location
, tmp
, 2, atom
,
12587 build_int_cst (integer_type_node
,
12588 MEMMODEL_RELAXED
));
12589 gfc_add_modify (&block
, value
, fold_convert (TREE_TYPE (value
), tmp
));
12591 if (stat
!= NULL_TREE
)
12592 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
12593 gfc_add_block_to_block (&block
, &post_block
);
12594 return gfc_finish_block (&block
);
12599 conv_intrinsic_atomic_cas (gfc_code
*code
)
12602 tree tmp
, atom
, old
, new_val
, comp
, stat
= NULL_TREE
;
12603 stmtblock_t block
, post_block
;
12604 built_in_function fn
;
12605 gfc_expr
*atom_expr
= code
->ext
.actual
->expr
;
12607 if (atom_expr
->expr_type
== EXPR_FUNCTION
12608 && atom_expr
->value
.function
.isym
12609 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
12610 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
12612 gfc_init_block (&block
);
12613 gfc_init_block (&post_block
);
12614 gfc_init_se (&argse
, NULL
);
12615 argse
.want_pointer
= 1;
12616 gfc_conv_expr (&argse
, atom_expr
);
12619 gfc_init_se (&argse
, NULL
);
12620 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12621 argse
.want_pointer
= 1;
12622 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->expr
);
12623 gfc_add_block_to_block (&block
, &argse
.pre
);
12624 gfc_add_block_to_block (&post_block
, &argse
.post
);
12627 gfc_init_se (&argse
, NULL
);
12628 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12629 argse
.want_pointer
= 1;
12630 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->expr
);
12631 gfc_add_block_to_block (&block
, &argse
.pre
);
12632 gfc_add_block_to_block (&post_block
, &argse
.post
);
12635 gfc_init_se (&argse
, NULL
);
12636 if (flag_coarray
== GFC_FCOARRAY_LIB
12637 && code
->ext
.actual
->next
->next
->next
->expr
->ts
.kind
12638 == atom_expr
->ts
.kind
)
12639 argse
.want_pointer
= 1;
12640 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->next
->expr
);
12641 gfc_add_block_to_block (&block
, &argse
.pre
);
12642 gfc_add_block_to_block (&post_block
, &argse
.post
);
12643 new_val
= argse
.expr
;
12646 if (code
->ext
.actual
->next
->next
->next
->next
->expr
!= NULL
)
12648 gcc_assert (code
->ext
.actual
->next
->next
->next
->next
->expr
->expr_type
12650 gfc_init_se (&argse
, NULL
);
12651 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12652 argse
.want_pointer
= 1;
12653 gfc_conv_expr_val (&argse
,
12654 code
->ext
.actual
->next
->next
->next
->next
->expr
);
12655 gfc_add_block_to_block (&block
, &argse
.pre
);
12656 gfc_add_block_to_block (&post_block
, &argse
.post
);
12659 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
12660 stat
= null_pointer_node
;
12662 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12664 tree image_index
, caf_decl
, offset
, token
;
12666 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
12667 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
12668 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
12670 if (gfc_is_coindexed (atom_expr
))
12671 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
12673 image_index
= integer_zero_node
;
12675 if (TREE_TYPE (TREE_TYPE (new_val
)) != TREE_TYPE (TREE_TYPE (old
)))
12677 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (old
)), "new");
12678 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), new_val
));
12679 new_val
= gfc_build_addr_expr (NULL_TREE
, tmp
);
12682 /* Convert a constant to a pointer. */
12683 if (!POINTER_TYPE_P (TREE_TYPE (comp
)))
12685 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (old
)), "comp");
12686 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), comp
));
12687 comp
= gfc_build_addr_expr (NULL_TREE
, tmp
);
12690 gfc_init_se (&argse
, NULL
);
12691 gfc_get_caf_token_offset (&argse
, &token
, &offset
, caf_decl
, atom
,
12693 gfc_add_block_to_block (&block
, &argse
.pre
);
12695 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_cas
, 9,
12696 token
, offset
, image_index
, old
, comp
, new_val
,
12697 stat
, build_int_cst (integer_type_node
,
12698 (int) atom_expr
->ts
.type
),
12699 build_int_cst (integer_type_node
,
12700 (int) atom_expr
->ts
.kind
));
12701 gfc_add_expr_to_block (&block
, tmp
);
12702 gfc_add_block_to_block (&block
, &argse
.post
);
12703 gfc_add_block_to_block (&block
, &post_block
);
12704 return gfc_finish_block (&block
);
12707 tmp
= TREE_TYPE (TREE_TYPE (atom
));
12708 fn
= (built_in_function
) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
12709 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
12711 tmp
= builtin_decl_explicit (fn
);
12713 gfc_add_modify (&block
, old
, comp
);
12714 tmp
= build_call_expr_loc (input_location
, tmp
, 6, atom
,
12715 gfc_build_addr_expr (NULL
, old
),
12716 fold_convert (TREE_TYPE (old
), new_val
),
12717 boolean_false_node
,
12718 build_int_cst (NULL
, MEMMODEL_RELAXED
),
12719 build_int_cst (NULL
, MEMMODEL_RELAXED
));
12720 gfc_add_expr_to_block (&block
, tmp
);
12722 if (stat
!= NULL_TREE
)
12723 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
12724 gfc_add_block_to_block (&block
, &post_block
);
12725 return gfc_finish_block (&block
);
12729 conv_intrinsic_event_query (gfc_code
*code
)
12732 tree stat
= NULL_TREE
, stat2
= NULL_TREE
;
12733 tree count
= NULL_TREE
, count2
= NULL_TREE
;
12735 gfc_expr
*event_expr
= code
->ext
.actual
->expr
;
12737 if (code
->ext
.actual
->next
->next
->expr
)
12739 gcc_assert (code
->ext
.actual
->next
->next
->expr
->expr_type
12741 gfc_init_se (&argse
, NULL
);
12742 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->next
->expr
);
12745 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
12746 stat
= null_pointer_node
;
12748 if (code
->ext
.actual
->next
->expr
)
12750 gcc_assert (code
->ext
.actual
->next
->expr
->expr_type
== EXPR_VARIABLE
);
12751 gfc_init_se (&argse
, NULL
);
12752 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->expr
);
12753 count
= argse
.expr
;
12756 gfc_start_block (&se
.pre
);
12757 if (flag_coarray
== GFC_FCOARRAY_LIB
)
12759 tree tmp
, token
, image_index
;
12760 tree index
= build_zero_cst (gfc_array_index_type
);
12762 if (event_expr
->expr_type
== EXPR_FUNCTION
12763 && event_expr
->value
.function
.isym
12764 && event_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
12765 event_expr
= event_expr
->value
.function
.actual
->expr
;
12767 tree caf_decl
= gfc_get_tree_for_caf_expr (event_expr
);
12769 if (event_expr
->symtree
->n
.sym
->ts
.type
!= BT_DERIVED
12770 || event_expr
->symtree
->n
.sym
->ts
.u
.derived
->from_intmod
12771 != INTMOD_ISO_FORTRAN_ENV
12772 || event_expr
->symtree
->n
.sym
->ts
.u
.derived
->intmod_sym_id
12773 != ISOFORTRAN_EVENT_TYPE
)
12775 gfc_error ("Sorry, the event component of derived type at %L is not "
12776 "yet supported", &event_expr
->where
);
12780 if (gfc_is_coindexed (event_expr
))
12782 gfc_error ("The event variable at %L shall not be coindexed",
12783 &event_expr
->where
);
12787 image_index
= integer_zero_node
;
12789 gfc_get_caf_token_offset (&se
, &token
, NULL
, caf_decl
, NULL_TREE
,
12792 /* For arrays, obtain the array index. */
12793 if (gfc_expr_attr (event_expr
).dimension
)
12795 tree desc
, tmp
, extent
, lbound
, ubound
;
12796 gfc_array_ref
*ar
, ar2
;
12799 /* TODO: Extend this, once DT components are supported. */
12800 ar
= &event_expr
->ref
->u
.ar
;
12802 memset (ar
, '\0', sizeof (*ar
));
12804 ar
->type
= AR_FULL
;
12806 gfc_init_se (&argse
, NULL
);
12807 argse
.descriptor_only
= 1;
12808 gfc_conv_expr_descriptor (&argse
, event_expr
);
12809 gfc_add_block_to_block (&se
.pre
, &argse
.pre
);
12813 extent
= build_one_cst (gfc_array_index_type
);
12814 for (i
= 0; i
< ar
->dimen
; i
++)
12816 gfc_init_se (&argse
, NULL
);
12817 gfc_conv_expr_type (&argse
, ar
->start
[i
], gfc_array_index_type
);
12818 gfc_add_block_to_block (&argse
.pre
, &argse
.pre
);
12819 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[i
]);
12820 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
12821 TREE_TYPE (lbound
), argse
.expr
, lbound
);
12822 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
12823 TREE_TYPE (tmp
), extent
, tmp
);
12824 index
= fold_build2_loc (input_location
, PLUS_EXPR
,
12825 TREE_TYPE (tmp
), index
, tmp
);
12826 if (i
< ar
->dimen
- 1)
12828 ubound
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[i
]);
12829 tmp
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
12830 extent
= fold_build2_loc (input_location
, MULT_EXPR
,
12831 TREE_TYPE (tmp
), extent
, tmp
);
12836 if (count
!= null_pointer_node
&& TREE_TYPE (count
) != integer_type_node
)
12839 count
= gfc_create_var (integer_type_node
, "count");
12842 if (stat
!= null_pointer_node
&& TREE_TYPE (stat
) != integer_type_node
)
12845 stat
= gfc_create_var (integer_type_node
, "stat");
12848 index
= fold_convert (size_type_node
, index
);
12849 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_event_query
, 5,
12850 token
, index
, image_index
, count
12851 ? gfc_build_addr_expr (NULL
, count
) : count
,
12852 stat
!= null_pointer_node
12853 ? gfc_build_addr_expr (NULL
, stat
) : stat
);
12854 gfc_add_expr_to_block (&se
.pre
, tmp
);
12856 if (count2
!= NULL_TREE
)
12857 gfc_add_modify (&se
.pre
, count2
,
12858 fold_convert (TREE_TYPE (count2
), count
));
12860 if (stat2
!= NULL_TREE
)
12861 gfc_add_modify (&se
.pre
, stat2
,
12862 fold_convert (TREE_TYPE (stat2
), stat
));
12864 return gfc_finish_block (&se
.pre
);
12867 gfc_init_se (&argse
, NULL
);
12868 gfc_conv_expr_val (&argse
, code
->ext
.actual
->expr
);
12869 gfc_add_modify (&se
.pre
, count
, fold_convert (TREE_TYPE (count
), argse
.expr
));
12871 if (stat
!= NULL_TREE
)
12872 gfc_add_modify (&se
.pre
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
12874 return gfc_finish_block (&se
.pre
);
12878 /* This is a peculiar case because of the need to do dependency checking.
12879 It is called via trans-stmt.cc(gfc_trans_call), where it is picked out as
12880 a special case and this function called instead of
12881 gfc_conv_procedure_call. */
12883 gfc_conv_intrinsic_mvbits (gfc_se
*se
, gfc_actual_arglist
*actual_args
,
12884 gfc_loopinfo
*loop
)
12886 gfc_actual_arglist
*actual
;
12892 tree from
, frompos
, len
, to
, topos
;
12893 tree lenmask
, oldbits
, newbits
, bitsize
;
12894 tree type
, utype
, above
, mask1
, mask2
;
12899 lss
= gfc_ss_terminator
;
12901 actual
= actual_args
;
12902 for (n
= 0; n
< 5; n
++, actual
= actual
->next
)
12904 arg
[n
] = actual
->expr
;
12905 gfc_init_se (&argse
[n
], NULL
);
12907 if (lss
!= gfc_ss_terminator
)
12909 gfc_copy_loopinfo_to_se (&argse
[n
], loop
);
12910 /* Find the ss for the expression if it is there. */
12912 gfc_mark_ss_chain_used (lss
, 1);
12915 gfc_conv_expr (&argse
[n
], arg
[n
]);
12921 from
= argse
[0].expr
;
12922 frompos
= argse
[1].expr
;
12923 len
= argse
[2].expr
;
12924 to
= argse
[3].expr
;
12925 topos
= argse
[4].expr
;
12927 /* The type of the result (TO). */
12928 type
= TREE_TYPE (to
);
12929 bitsize
= build_int_cst (integer_type_node
, TYPE_PRECISION (type
));
12931 /* Optionally generate code for runtime argument check. */
12932 if (gfc_option
.rtcheck
& GFC_RTCHECK_BITS
)
12934 tree nbits
, below
, ccond
;
12935 tree fp
= fold_convert (long_integer_type_node
, frompos
);
12936 tree ln
= fold_convert (long_integer_type_node
, len
);
12937 tree tp
= fold_convert (long_integer_type_node
, topos
);
12938 below
= fold_build2_loc (input_location
, LT_EXPR
,
12939 logical_type_node
, frompos
,
12940 build_int_cst (TREE_TYPE (frompos
), 0));
12941 above
= fold_build2_loc (input_location
, GT_EXPR
,
12942 logical_type_node
, frompos
,
12943 fold_convert (TREE_TYPE (frompos
), bitsize
));
12944 ccond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
12945 logical_type_node
, below
, above
);
12946 gfc_trans_runtime_check (true, false, ccond
, &argse
[1].pre
,
12948 "FROMPOS argument (%ld) out of range 0:%d "
12949 "in intrinsic MVBITS", fp
, bitsize
);
12950 below
= fold_build2_loc (input_location
, LT_EXPR
,
12951 logical_type_node
, len
,
12952 build_int_cst (TREE_TYPE (len
), 0));
12953 above
= fold_build2_loc (input_location
, GT_EXPR
,
12954 logical_type_node
, len
,
12955 fold_convert (TREE_TYPE (len
), bitsize
));
12956 ccond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
12957 logical_type_node
, below
, above
);
12958 gfc_trans_runtime_check (true, false, ccond
, &argse
[2].pre
,
12960 "LEN argument (%ld) out of range 0:%d "
12961 "in intrinsic MVBITS", ln
, bitsize
);
12962 below
= fold_build2_loc (input_location
, LT_EXPR
,
12963 logical_type_node
, topos
,
12964 build_int_cst (TREE_TYPE (topos
), 0));
12965 above
= fold_build2_loc (input_location
, GT_EXPR
,
12966 logical_type_node
, topos
,
12967 fold_convert (TREE_TYPE (topos
), bitsize
));
12968 ccond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
12969 logical_type_node
, below
, above
);
12970 gfc_trans_runtime_check (true, false, ccond
, &argse
[4].pre
,
12972 "TOPOS argument (%ld) out of range 0:%d "
12973 "in intrinsic MVBITS", tp
, bitsize
);
12975 /* The tests above ensure that FROMPOS, LEN and TOPOS fit into short
12976 integers. Additions below cannot overflow. */
12977 nbits
= fold_convert (long_integer_type_node
, bitsize
);
12978 above
= fold_build2_loc (input_location
, PLUS_EXPR
,
12979 long_integer_type_node
, fp
, ln
);
12980 ccond
= fold_build2_loc (input_location
, GT_EXPR
,
12981 logical_type_node
, above
, nbits
);
12982 gfc_trans_runtime_check (true, false, ccond
, &argse
[1].pre
,
12984 "FROMPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
12985 "in intrinsic MVBITS", fp
, ln
, bitsize
);
12986 above
= fold_build2_loc (input_location
, PLUS_EXPR
,
12987 long_integer_type_node
, tp
, ln
);
12988 ccond
= fold_build2_loc (input_location
, GT_EXPR
,
12989 logical_type_node
, above
, nbits
);
12990 gfc_trans_runtime_check (true, false, ccond
, &argse
[4].pre
,
12992 "TOPOS(%ld)+LEN(%ld)>BIT_SIZE(%d) "
12993 "in intrinsic MVBITS", tp
, ln
, bitsize
);
12996 for (n
= 0; n
< 5; n
++)
12998 gfc_add_block_to_block (&se
->pre
, &argse
[n
].pre
);
12999 gfc_add_block_to_block (&se
->post
, &argse
[n
].post
);
13002 /* lenmask = (LEN >= bit_size (TYPE)) ? ~(TYPE)0 : ((TYPE)1 << LEN) - 1 */
13003 above
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
13004 len
, fold_convert (TREE_TYPE (len
), bitsize
));
13005 mask1
= build_int_cst (type
, -1);
13006 mask2
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
13007 build_int_cst (type
, 1), len
);
13008 mask2
= fold_build2_loc (input_location
, MINUS_EXPR
, type
,
13009 mask2
, build_int_cst (type
, 1));
13010 lenmask
= fold_build3_loc (input_location
, COND_EXPR
, type
,
13011 above
, mask1
, mask2
);
13013 /* newbits = (((UTYPE)(FROM) >> FROMPOS) & lenmask) << TOPOS.
13014 * For valid frompos+len <= bit_size(FROM) the conversion to unsigned is
13015 * not strictly necessary; artificial bits from rshift will be masked. */
13016 utype
= unsigned_type_for (type
);
13017 newbits
= fold_build2_loc (input_location
, RSHIFT_EXPR
, utype
,
13018 fold_convert (utype
, from
), frompos
);
13019 newbits
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
,
13020 fold_convert (type
, newbits
), lenmask
);
13021 newbits
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
13024 /* oldbits = TO & (~(lenmask << TOPOS)). */
13025 oldbits
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
13027 oldbits
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, type
, oldbits
);
13028 oldbits
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, oldbits
, to
);
13030 /* TO = newbits | oldbits. */
13031 se
->expr
= fold_build2_loc (input_location
, BIT_IOR_EXPR
, type
,
13034 /* Return the assignment. */
13035 se
->expr
= fold_build2_loc (input_location
, MODIFY_EXPR
,
13036 void_type_node
, to
, se
->expr
);
13041 conv_intrinsic_move_alloc (gfc_code
*code
)
13044 gfc_expr
*from_expr
, *to_expr
;
13045 gfc_se from_se
, to_se
;
13046 tree tmp
, to_tree
, from_tree
;
13047 bool coarray
, from_is_class
, from_is_scalar
;
13049 gfc_start_block (&block
);
13051 from_expr
= code
->ext
.actual
->expr
;
13052 to_expr
= code
->ext
.actual
->next
->expr
;
13054 gfc_init_se (&from_se
, NULL
);
13055 gfc_init_se (&to_se
, NULL
);
13057 gcc_assert (from_expr
->ts
.type
!= BT_CLASS
|| to_expr
->ts
.type
== BT_CLASS
);
13058 coarray
= from_expr
->corank
!= 0;
13060 from_is_class
= from_expr
->ts
.type
== BT_CLASS
;
13061 from_is_scalar
= from_expr
->rank
== 0 && !coarray
;
13062 if (to_expr
->ts
.type
== BT_CLASS
|| from_is_scalar
)
13064 from_se
.want_pointer
= 1;
13065 if (from_is_scalar
)
13066 gfc_conv_expr (&from_se
, from_expr
);
13068 gfc_conv_expr_descriptor (&from_se
, from_expr
);
13070 from_tree
= gfc_class_data_get (from_se
.expr
);
13074 from_tree
= from_se
.expr
;
13076 if (to_expr
->ts
.type
== BT_CLASS
)
13078 vtab
= gfc_find_vtab (&from_expr
->ts
);
13080 from_se
.expr
= gfc_get_symbol_decl (vtab
);
13083 gfc_add_block_to_block (&block
, &from_se
.pre
);
13085 to_se
.want_pointer
= 1;
13086 if (to_expr
->rank
== 0)
13087 gfc_conv_expr (&to_se
, to_expr
);
13089 gfc_conv_expr_descriptor (&to_se
, to_expr
);
13090 if (to_expr
->ts
.type
== BT_CLASS
)
13091 to_tree
= gfc_class_data_get (to_se
.expr
);
13093 to_tree
= to_se
.expr
;
13094 gfc_add_block_to_block (&block
, &to_se
.pre
);
13096 /* Deallocate "to". */
13097 if (to_expr
->rank
== 0)
13100 = gfc_deallocate_scalar_with_status (to_tree
, NULL_TREE
, NULL_TREE
,
13101 true, to_expr
, to_expr
->ts
);
13102 gfc_add_expr_to_block (&block
, tmp
);
13105 if (from_is_scalar
)
13107 /* Assign (_data) pointers. */
13108 gfc_add_modify_loc (input_location
, &block
, to_tree
,
13109 fold_convert (TREE_TYPE (to_tree
), from_tree
));
13111 /* Set "from" to NULL. */
13112 gfc_add_modify_loc (input_location
, &block
, from_tree
,
13113 fold_convert (TREE_TYPE (from_tree
),
13114 null_pointer_node
));
13116 gfc_add_block_to_block (&block
, &from_se
.post
);
13118 gfc_add_block_to_block (&block
, &to_se
.post
);
13121 if (to_expr
->ts
.type
== BT_CLASS
)
13123 gfc_class_set_vptr (&block
, to_se
.expr
, from_se
.expr
);
13125 gfc_reset_vptr (&block
, from_expr
);
13126 if (UNLIMITED_POLY (to_expr
))
13128 tree to_len
= gfc_class_len_get (to_se
.class_container
);
13129 tmp
= from_expr
->ts
.type
== BT_CHARACTER
&& from_se
.string_length
13130 ? from_se
.string_length
13132 gfc_add_modify_loc (input_location
, &block
, to_len
,
13133 fold_convert (TREE_TYPE (to_len
), tmp
));
13137 if (from_is_scalar
)
13139 if (to_expr
->ts
.type
== BT_CHARACTER
&& to_expr
->ts
.deferred
)
13141 gfc_add_modify_loc (input_location
, &block
, to_se
.string_length
,
13142 fold_convert (TREE_TYPE (to_se
.string_length
),
13143 from_se
.string_length
));
13144 if (from_expr
->ts
.deferred
)
13145 gfc_add_modify_loc (
13146 input_location
, &block
, from_se
.string_length
,
13147 build_int_cst (TREE_TYPE (from_se
.string_length
), 0));
13149 if (UNLIMITED_POLY (from_expr
))
13150 gfc_reset_len (&block
, from_expr
);
13152 return gfc_finish_block (&block
);
13155 gfc_init_se (&to_se
, NULL
);
13156 gfc_init_se (&from_se
, NULL
);
13159 /* Deallocate "to". */
13160 if (from_expr
->rank
== 0)
13162 to_se
.want_coarray
= 1;
13163 from_se
.want_coarray
= 1;
13165 gfc_conv_expr_descriptor (&to_se
, to_expr
);
13166 gfc_conv_expr_descriptor (&from_se
, from_expr
);
13168 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
13169 is an image control "statement", cf. IR F08/0040 in 12-006A. */
13170 if (coarray
&& flag_coarray
== GFC_FCOARRAY_LIB
)
13174 tmp
= gfc_deallocate_with_status (to_se
.expr
, NULL_TREE
, NULL_TREE
,
13175 NULL_TREE
, NULL_TREE
, true, to_expr
,
13176 GFC_CAF_COARRAY_DEALLOCATE_ONLY
);
13177 gfc_add_expr_to_block (&block
, tmp
);
13179 tmp
= gfc_conv_descriptor_data_get (to_se
.expr
);
13180 cond
= fold_build2_loc (input_location
, EQ_EXPR
,
13181 logical_type_node
, tmp
,
13182 fold_convert (TREE_TYPE (tmp
),
13183 null_pointer_node
));
13184 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_sync_all
,
13185 3, null_pointer_node
, null_pointer_node
,
13186 integer_zero_node
);
13188 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
,
13189 tmp
, build_empty_stmt (input_location
));
13190 gfc_add_expr_to_block (&block
, tmp
);
13194 if (to_expr
->ts
.type
== BT_DERIVED
13195 && to_expr
->ts
.u
.derived
->attr
.alloc_comp
)
13197 tmp
= gfc_deallocate_alloc_comp (to_expr
->ts
.u
.derived
,
13198 to_se
.expr
, to_expr
->rank
);
13199 gfc_add_expr_to_block (&block
, tmp
);
13202 tmp
= gfc_deallocate_with_status (to_se
.expr
, NULL_TREE
, NULL_TREE
,
13203 NULL_TREE
, NULL_TREE
, true, to_expr
,
13204 GFC_CAF_COARRAY_NOCOARRAY
);
13205 gfc_add_expr_to_block (&block
, tmp
);
13208 /* Copy the array descriptor data. */
13209 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
, from_se
.expr
);
13211 /* Set "from" to NULL. */
13212 tmp
= gfc_conv_descriptor_data_get (from_se
.expr
);
13213 gfc_add_modify_loc (input_location
, &block
, tmp
,
13214 fold_convert (TREE_TYPE (tmp
), null_pointer_node
));
13217 if (to_expr
->ts
.type
== BT_CHARACTER
&& to_expr
->ts
.deferred
)
13219 gfc_add_modify_loc (input_location
, &block
, to_se
.string_length
,
13220 fold_convert (TREE_TYPE (to_se
.string_length
),
13221 from_se
.string_length
));
13222 if (from_expr
->ts
.deferred
)
13223 gfc_add_modify_loc (input_location
, &block
, from_se
.string_length
,
13224 build_int_cst (TREE_TYPE (from_se
.string_length
), 0));
13227 return gfc_finish_block (&block
);
13232 gfc_conv_intrinsic_subroutine (gfc_code
*code
)
13236 gcc_assert (code
->resolved_isym
);
13238 switch (code
->resolved_isym
->id
)
13240 case GFC_ISYM_MOVE_ALLOC
:
13241 res
= conv_intrinsic_move_alloc (code
);
13244 case GFC_ISYM_ATOMIC_CAS
:
13245 res
= conv_intrinsic_atomic_cas (code
);
13248 case GFC_ISYM_ATOMIC_ADD
:
13249 case GFC_ISYM_ATOMIC_AND
:
13250 case GFC_ISYM_ATOMIC_DEF
:
13251 case GFC_ISYM_ATOMIC_OR
:
13252 case GFC_ISYM_ATOMIC_XOR
:
13253 case GFC_ISYM_ATOMIC_FETCH_ADD
:
13254 case GFC_ISYM_ATOMIC_FETCH_AND
:
13255 case GFC_ISYM_ATOMIC_FETCH_OR
:
13256 case GFC_ISYM_ATOMIC_FETCH_XOR
:
13257 res
= conv_intrinsic_atomic_op (code
);
13260 case GFC_ISYM_ATOMIC_REF
:
13261 res
= conv_intrinsic_atomic_ref (code
);
13264 case GFC_ISYM_EVENT_QUERY
:
13265 res
= conv_intrinsic_event_query (code
);
13268 case GFC_ISYM_C_F_POINTER
:
13269 case GFC_ISYM_C_F_PROCPOINTER
:
13270 res
= conv_isocbinding_subroutine (code
);
13273 case GFC_ISYM_CAF_SEND
:
13274 res
= conv_caf_send (code
);
13277 case GFC_ISYM_CO_BROADCAST
:
13278 case GFC_ISYM_CO_MIN
:
13279 case GFC_ISYM_CO_MAX
:
13280 case GFC_ISYM_CO_REDUCE
:
13281 case GFC_ISYM_CO_SUM
:
13282 res
= conv_co_collective (code
);
13285 case GFC_ISYM_FREE
:
13286 res
= conv_intrinsic_free (code
);
13289 case GFC_ISYM_RANDOM_INIT
:
13290 res
= conv_intrinsic_random_init (code
);
13293 case GFC_ISYM_KILL
:
13294 res
= conv_intrinsic_kill_sub (code
);
13297 case GFC_ISYM_MVBITS
:
13301 case GFC_ISYM_SYSTEM_CLOCK
:
13302 res
= conv_intrinsic_system_clock (code
);
13313 #include "gt-fortran-trans-intrinsic.h"