1 /* Intrinsic translation
2 Copyright (C) 2002-2018 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.c-- 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 "tree-nested.h"
35 #include "stor-layout.h"
36 #include "toplev.h" /* For rest_of_decl_compilation. */
38 #include "trans-const.h"
39 #include "trans-types.h"
40 #include "trans-array.h"
41 #include "dependency.h" /* For CAF array alias analysis. */
42 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
44 /* This maps Fortran intrinsic math functions to external library or GCC
46 typedef struct GTY(()) gfc_intrinsic_map_t
{
47 /* The explicit enum is required to work around inadequacies in the
48 garbage collection/gengtype parsing mechanism. */
51 /* Enum value from the "language-independent", aka C-centric, part
52 of gcc, or END_BUILTINS of no such value set. */
53 enum built_in_function float_built_in
;
54 enum built_in_function double_built_in
;
55 enum built_in_function long_double_built_in
;
56 enum built_in_function complex_float_built_in
;
57 enum built_in_function complex_double_built_in
;
58 enum built_in_function complex_long_double_built_in
;
60 /* True if the naming pattern is to prepend "c" for complex and
61 append "f" for kind=4. False if the naming pattern is to
62 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
65 /* True if a complex version of the function exists. */
66 bool complex_available
;
68 /* True if the function should be marked const. */
71 /* The base library name of this function. */
74 /* Cache decls created for the various operand types. */
86 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
87 defines complex variants of all of the entries in mathbuiltins.def
89 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
90 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
91 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
92 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
93 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
95 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
96 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
97 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
98 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
99 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
101 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
102 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
103 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
104 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
105 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
107 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
108 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
109 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
110 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
111 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
113 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map
[] =
115 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
116 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
117 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
118 #include "mathbuiltins.def"
120 /* Functions in libgfortran. */
121 LIB_FUNCTION (ERFC_SCALED
, "erfc_scaled", false),
124 LIB_FUNCTION (NONE
, NULL
, false)
129 #undef DEFINE_MATH_BUILTIN
130 #undef DEFINE_MATH_BUILTIN_C
133 enum rounding_mode
{ RND_ROUND
, RND_TRUNC
, RND_CEIL
, RND_FLOOR
};
136 /* Find the correct variant of a given builtin from its argument. */
138 builtin_decl_for_precision (enum built_in_function base_built_in
,
141 enum built_in_function i
= END_BUILTINS
;
143 gfc_intrinsic_map_t
*m
;
144 for (m
= gfc_intrinsic_map
; m
->double_built_in
!= base_built_in
; m
++)
147 if (precision
== TYPE_PRECISION (float_type_node
))
148 i
= m
->float_built_in
;
149 else if (precision
== TYPE_PRECISION (double_type_node
))
150 i
= m
->double_built_in
;
151 else if (precision
== TYPE_PRECISION (long_double_type_node
))
152 i
= m
->long_double_built_in
;
153 else if (precision
== TYPE_PRECISION (gfc_float128_type_node
))
155 /* Special treatment, because it is not exactly a built-in, but
156 a library function. */
157 return m
->real16_decl
;
160 return (i
== END_BUILTINS
? NULL_TREE
: builtin_decl_explicit (i
));
165 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in
,
168 int i
= gfc_validate_kind (BT_REAL
, kind
, false);
170 if (gfc_real_kinds
[i
].c_float128
)
172 /* For __float128, the story is a bit different, because we return
173 a decl to a library function rather than a built-in. */
174 gfc_intrinsic_map_t
*m
;
175 for (m
= gfc_intrinsic_map
; m
->double_built_in
!= double_built_in
; m
++)
178 return m
->real16_decl
;
181 return builtin_decl_for_precision (double_built_in
,
182 gfc_real_kinds
[i
].mode_precision
);
186 /* Evaluate the arguments to an intrinsic function. The value
187 of NARGS may be less than the actual number of arguments in EXPR
188 to allow optional "KIND" arguments that are not included in the
189 generated code to be ignored. */
192 gfc_conv_intrinsic_function_args (gfc_se
*se
, gfc_expr
*expr
,
193 tree
*argarray
, int nargs
)
195 gfc_actual_arglist
*actual
;
197 gfc_intrinsic_arg
*formal
;
201 formal
= expr
->value
.function
.isym
->formal
;
202 actual
= expr
->value
.function
.actual
;
204 for (curr_arg
= 0; curr_arg
< nargs
; curr_arg
++,
205 actual
= actual
->next
,
206 formal
= formal
? formal
->next
: NULL
)
210 /* Skip omitted optional arguments. */
217 /* Evaluate the parameter. This will substitute scalarized
218 references automatically. */
219 gfc_init_se (&argse
, se
);
221 if (e
->ts
.type
== BT_CHARACTER
)
223 gfc_conv_expr (&argse
, e
);
224 gfc_conv_string_parameter (&argse
);
225 argarray
[curr_arg
++] = argse
.string_length
;
226 gcc_assert (curr_arg
< nargs
);
229 gfc_conv_expr_val (&argse
, e
);
231 /* If an optional argument is itself an optional dummy argument,
232 check its presence and substitute a null if absent. */
233 if (e
->expr_type
== EXPR_VARIABLE
234 && e
->symtree
->n
.sym
->attr
.optional
237 gfc_conv_missing_dummy (&argse
, e
, formal
->ts
, 0);
239 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
240 gfc_add_block_to_block (&se
->post
, &argse
.post
);
241 argarray
[curr_arg
] = argse
.expr
;
245 /* Count the number of actual arguments to the intrinsic function EXPR
246 including any "hidden" string length arguments. */
249 gfc_intrinsic_argument_list_length (gfc_expr
*expr
)
252 gfc_actual_arglist
*actual
;
254 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
259 if (actual
->expr
->ts
.type
== BT_CHARACTER
)
269 /* Conversions between different types are output by the frontend as
270 intrinsic functions. We implement these directly with inline code. */
273 gfc_conv_intrinsic_conversion (gfc_se
* se
, gfc_expr
* expr
)
279 nargs
= gfc_intrinsic_argument_list_length (expr
);
280 args
= XALLOCAVEC (tree
, nargs
);
282 /* Evaluate all the arguments passed. Whilst we're only interested in the
283 first one here, there are other parts of the front-end that assume this
284 and will trigger an ICE if it's not the case. */
285 type
= gfc_typenode_for_spec (&expr
->ts
);
286 gcc_assert (expr
->value
.function
.actual
->expr
);
287 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
289 /* Conversion between character kinds involves a call to a library
291 if (expr
->ts
.type
== BT_CHARACTER
)
293 tree fndecl
, var
, addr
, tmp
;
295 if (expr
->ts
.kind
== 1
296 && expr
->value
.function
.actual
->expr
->ts
.kind
== 4)
297 fndecl
= gfor_fndecl_convert_char4_to_char1
;
298 else if (expr
->ts
.kind
== 4
299 && expr
->value
.function
.actual
->expr
->ts
.kind
== 1)
300 fndecl
= gfor_fndecl_convert_char1_to_char4
;
304 /* Create the variable storing the converted value. */
305 type
= gfc_get_pchar_type (expr
->ts
.kind
);
306 var
= gfc_create_var (type
, "str");
307 addr
= gfc_build_addr_expr (build_pointer_type (type
), var
);
309 /* Call the library function that will perform the conversion. */
310 gcc_assert (nargs
>= 2);
311 tmp
= build_call_expr_loc (input_location
,
312 fndecl
, 3, addr
, args
[0], args
[1]);
313 gfc_add_expr_to_block (&se
->pre
, tmp
);
315 /* Free the temporary afterwards. */
316 tmp
= gfc_call_free (var
);
317 gfc_add_expr_to_block (&se
->post
, tmp
);
320 se
->string_length
= args
[0];
325 /* Conversion from complex to non-complex involves taking the real
326 component of the value. */
327 if (TREE_CODE (TREE_TYPE (args
[0])) == COMPLEX_TYPE
328 && expr
->ts
.type
!= BT_COMPLEX
)
332 artype
= TREE_TYPE (TREE_TYPE (args
[0]));
333 args
[0] = fold_build1_loc (input_location
, REALPART_EXPR
, artype
,
337 se
->expr
= convert (type
, args
[0]);
340 /* This is needed because the gcc backend only implements
341 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
342 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
343 Similarly for CEILING. */
346 build_fixbound_expr (stmtblock_t
* pblock
, tree arg
, tree type
, int up
)
353 argtype
= TREE_TYPE (arg
);
354 arg
= gfc_evaluate_now (arg
, pblock
);
356 intval
= convert (type
, arg
);
357 intval
= gfc_evaluate_now (intval
, pblock
);
359 tmp
= convert (argtype
, intval
);
360 cond
= fold_build2_loc (input_location
, up
? GE_EXPR
: LE_EXPR
,
361 logical_type_node
, tmp
, arg
);
363 tmp
= fold_build2_loc (input_location
, up
? PLUS_EXPR
: MINUS_EXPR
, type
,
364 intval
, build_int_cst (type
, 1));
365 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
, intval
, tmp
);
370 /* Round to nearest integer, away from zero. */
373 build_round_expr (tree arg
, tree restype
)
377 int argprec
, resprec
;
379 argtype
= TREE_TYPE (arg
);
380 argprec
= TYPE_PRECISION (argtype
);
381 resprec
= TYPE_PRECISION (restype
);
383 /* Depending on the type of the result, choose the int intrinsic
384 (iround, available only as a builtin, therefore cannot use it for
385 __float128), long int intrinsic (lround family) or long long
386 intrinsic (llround). We might also need to convert the result
388 if (resprec
<= INT_TYPE_SIZE
&& argprec
<= LONG_DOUBLE_TYPE_SIZE
)
389 fn
= builtin_decl_for_precision (BUILT_IN_IROUND
, argprec
);
390 else if (resprec
<= LONG_TYPE_SIZE
)
391 fn
= builtin_decl_for_precision (BUILT_IN_LROUND
, argprec
);
392 else if (resprec
<= LONG_LONG_TYPE_SIZE
)
393 fn
= builtin_decl_for_precision (BUILT_IN_LLROUND
, argprec
);
397 return fold_convert (restype
, build_call_expr_loc (input_location
,
402 /* Convert a real to an integer using a specific rounding mode.
403 Ideally we would just build the corresponding GENERIC node,
404 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
407 build_fix_expr (stmtblock_t
* pblock
, tree arg
, tree type
,
408 enum rounding_mode op
)
413 return build_fixbound_expr (pblock
, arg
, type
, 0);
416 return build_fixbound_expr (pblock
, arg
, type
, 1);
419 return build_round_expr (arg
, type
);
422 return fold_build1_loc (input_location
, FIX_TRUNC_EXPR
, type
, arg
);
430 /* Round a real value using the specified rounding mode.
431 We use a temporary integer of that same kind size as the result.
432 Values larger than those that can be represented by this kind are
433 unchanged, as they will not be accurate enough to represent the
435 huge = HUGE (KIND (a))
436 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
440 gfc_conv_intrinsic_aint (gfc_se
* se
, gfc_expr
* expr
, enum rounding_mode op
)
452 kind
= expr
->ts
.kind
;
453 nargs
= gfc_intrinsic_argument_list_length (expr
);
456 /* We have builtin functions for some cases. */
460 decl
= gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND
, kind
);
464 decl
= gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC
, kind
);
471 /* Evaluate the argument. */
472 gcc_assert (expr
->value
.function
.actual
->expr
);
473 gfc_conv_intrinsic_function_args (se
, expr
, arg
, nargs
);
475 /* Use a builtin function if one exists. */
476 if (decl
!= NULL_TREE
)
478 se
->expr
= build_call_expr_loc (input_location
, decl
, 1, arg
[0]);
482 /* This code is probably redundant, but we'll keep it lying around just
484 type
= gfc_typenode_for_spec (&expr
->ts
);
485 arg
[0] = gfc_evaluate_now (arg
[0], &se
->pre
);
487 /* Test if the value is too large to handle sensibly. */
488 gfc_set_model_kind (kind
);
490 n
= gfc_validate_kind (BT_INTEGER
, kind
, false);
491 mpfr_set_z (huge
, gfc_integer_kinds
[n
].huge
, GFC_RND_MODE
);
492 tmp
= gfc_conv_mpfr_to_tree (huge
, kind
, 0);
493 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
, arg
[0],
496 mpfr_neg (huge
, huge
, GFC_RND_MODE
);
497 tmp
= gfc_conv_mpfr_to_tree (huge
, kind
, 0);
498 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
, arg
[0],
500 cond
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
, logical_type_node
,
502 itype
= gfc_get_int_type (kind
);
504 tmp
= build_fix_expr (&se
->pre
, arg
[0], itype
, op
);
505 tmp
= convert (type
, tmp
);
506 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
, tmp
,
512 /* Convert to an integer using the specified rounding mode. */
515 gfc_conv_intrinsic_int (gfc_se
* se
, gfc_expr
* expr
, enum rounding_mode op
)
521 nargs
= gfc_intrinsic_argument_list_length (expr
);
522 args
= XALLOCAVEC (tree
, nargs
);
524 /* Evaluate the argument, we process all arguments even though we only
525 use the first one for code generation purposes. */
526 type
= gfc_typenode_for_spec (&expr
->ts
);
527 gcc_assert (expr
->value
.function
.actual
->expr
);
528 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
530 if (TREE_CODE (TREE_TYPE (args
[0])) == INTEGER_TYPE
)
532 /* Conversion to a different integer kind. */
533 se
->expr
= convert (type
, args
[0]);
537 /* Conversion from complex to non-complex involves taking the real
538 component of the value. */
539 if (TREE_CODE (TREE_TYPE (args
[0])) == COMPLEX_TYPE
540 && expr
->ts
.type
!= BT_COMPLEX
)
544 artype
= TREE_TYPE (TREE_TYPE (args
[0]));
545 args
[0] = fold_build1_loc (input_location
, REALPART_EXPR
, artype
,
549 se
->expr
= build_fix_expr (&se
->pre
, args
[0], type
, op
);
554 /* Get the imaginary component of a value. */
557 gfc_conv_intrinsic_imagpart (gfc_se
* se
, gfc_expr
* expr
)
561 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
562 se
->expr
= fold_build1_loc (input_location
, IMAGPART_EXPR
,
563 TREE_TYPE (TREE_TYPE (arg
)), arg
);
567 /* Get the complex conjugate of a value. */
570 gfc_conv_intrinsic_conjg (gfc_se
* se
, gfc_expr
* expr
)
574 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
575 se
->expr
= fold_build1_loc (input_location
, CONJ_EXPR
, TREE_TYPE (arg
), arg
);
581 define_quad_builtin (const char *name
, tree type
, bool is_const
)
584 fndecl
= build_decl (input_location
, FUNCTION_DECL
, get_identifier (name
),
587 /* Mark the decl as external. */
588 DECL_EXTERNAL (fndecl
) = 1;
589 TREE_PUBLIC (fndecl
) = 1;
591 /* Mark it __attribute__((const)). */
592 TREE_READONLY (fndecl
) = is_const
;
594 rest_of_decl_compilation (fndecl
, 1, 0);
601 /* Initialize function decls for library functions. The external functions
602 are created as required. Builtin functions are added here. */
605 gfc_build_intrinsic_lib_fndecls (void)
607 gfc_intrinsic_map_t
*m
;
608 tree quad_decls
[END_BUILTINS
+ 1];
610 if (gfc_real16_is_float128
)
612 /* If we have soft-float types, we create the decls for their
613 C99-like library functions. For now, we only handle __float128
614 q-suffixed functions. */
616 tree type
, complex_type
, func_1
, func_2
, func_cabs
, func_frexp
;
617 tree func_iround
, func_lround
, func_llround
, func_scalbn
, func_cpow
;
619 memset (quad_decls
, 0, sizeof(tree
) * (END_BUILTINS
+ 1));
621 type
= gfc_float128_type_node
;
622 complex_type
= gfc_complex_float128_type_node
;
623 /* type (*) (type) */
624 func_1
= build_function_type_list (type
, type
, NULL_TREE
);
626 func_iround
= build_function_type_list (integer_type_node
,
628 /* long (*) (type) */
629 func_lround
= build_function_type_list (long_integer_type_node
,
631 /* long long (*) (type) */
632 func_llround
= build_function_type_list (long_long_integer_type_node
,
634 /* type (*) (type, type) */
635 func_2
= build_function_type_list (type
, type
, type
, NULL_TREE
);
636 /* type (*) (type, &int) */
638 = build_function_type_list (type
,
640 build_pointer_type (integer_type_node
),
642 /* type (*) (type, int) */
643 func_scalbn
= build_function_type_list (type
,
644 type
, integer_type_node
, NULL_TREE
);
645 /* type (*) (complex type) */
646 func_cabs
= build_function_type_list (type
, complex_type
, NULL_TREE
);
647 /* complex type (*) (complex type, complex type) */
649 = build_function_type_list (complex_type
,
650 complex_type
, complex_type
, NULL_TREE
);
652 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
653 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
654 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
656 /* Only these built-ins are actually needed here. These are used directly
657 from the code, when calling builtin_decl_for_precision() or
658 builtin_decl_for_float_type(). The others are all constructed by
659 gfc_get_intrinsic_lib_fndecl(). */
660 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
661 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
663 #include "mathbuiltins.def"
667 #undef DEFINE_MATH_BUILTIN
668 #undef DEFINE_MATH_BUILTIN_C
670 /* There is one built-in we defined manually, because it gets called
671 with builtin_decl_for_precision() or builtin_decl_for_float_type()
672 even though it is not an OTHER_BUILTIN: it is SQRT. */
673 quad_decls
[BUILT_IN_SQRT
] = define_quad_builtin ("sqrtq", func_1
, true);
677 /* Add GCC builtin functions. */
678 for (m
= gfc_intrinsic_map
;
679 m
->id
!= GFC_ISYM_NONE
|| m
->double_built_in
!= END_BUILTINS
; m
++)
681 if (m
->float_built_in
!= END_BUILTINS
)
682 m
->real4_decl
= builtin_decl_explicit (m
->float_built_in
);
683 if (m
->complex_float_built_in
!= END_BUILTINS
)
684 m
->complex4_decl
= builtin_decl_explicit (m
->complex_float_built_in
);
685 if (m
->double_built_in
!= END_BUILTINS
)
686 m
->real8_decl
= builtin_decl_explicit (m
->double_built_in
);
687 if (m
->complex_double_built_in
!= END_BUILTINS
)
688 m
->complex8_decl
= builtin_decl_explicit (m
->complex_double_built_in
);
690 /* If real(kind=10) exists, it is always long double. */
691 if (m
->long_double_built_in
!= END_BUILTINS
)
692 m
->real10_decl
= builtin_decl_explicit (m
->long_double_built_in
);
693 if (m
->complex_long_double_built_in
!= END_BUILTINS
)
695 = builtin_decl_explicit (m
->complex_long_double_built_in
);
697 if (!gfc_real16_is_float128
)
699 if (m
->long_double_built_in
!= END_BUILTINS
)
700 m
->real16_decl
= builtin_decl_explicit (m
->long_double_built_in
);
701 if (m
->complex_long_double_built_in
!= END_BUILTINS
)
703 = builtin_decl_explicit (m
->complex_long_double_built_in
);
705 else if (quad_decls
[m
->double_built_in
] != NULL_TREE
)
707 /* Quad-precision function calls are constructed when first
708 needed by builtin_decl_for_precision(), except for those
709 that will be used directly (define by OTHER_BUILTIN). */
710 m
->real16_decl
= quad_decls
[m
->double_built_in
];
712 else if (quad_decls
[m
->complex_double_built_in
] != NULL_TREE
)
714 /* Same thing for the complex ones. */
715 m
->complex16_decl
= quad_decls
[m
->double_built_in
];
721 /* Create a fndecl for a simple intrinsic library function. */
724 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t
* m
, gfc_expr
* expr
)
727 vec
<tree
, va_gc
> *argtypes
;
729 gfc_actual_arglist
*actual
;
732 char name
[GFC_MAX_SYMBOL_LEN
+ 3];
735 if (ts
->type
== BT_REAL
)
740 pdecl
= &m
->real4_decl
;
743 pdecl
= &m
->real8_decl
;
746 pdecl
= &m
->real10_decl
;
749 pdecl
= &m
->real16_decl
;
755 else if (ts
->type
== BT_COMPLEX
)
757 gcc_assert (m
->complex_available
);
762 pdecl
= &m
->complex4_decl
;
765 pdecl
= &m
->complex8_decl
;
768 pdecl
= &m
->complex10_decl
;
771 pdecl
= &m
->complex16_decl
;
785 int n
= gfc_validate_kind (BT_REAL
, ts
->kind
, false);
786 if (gfc_real_kinds
[n
].c_float
)
787 snprintf (name
, sizeof (name
), "%s%s%s",
788 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
, "f");
789 else if (gfc_real_kinds
[n
].c_double
)
790 snprintf (name
, sizeof (name
), "%s%s",
791 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
);
792 else if (gfc_real_kinds
[n
].c_long_double
)
793 snprintf (name
, sizeof (name
), "%s%s%s",
794 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
, "l");
795 else if (gfc_real_kinds
[n
].c_float128
)
796 snprintf (name
, sizeof (name
), "%s%s%s",
797 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
, "q");
803 snprintf (name
, sizeof (name
), PREFIX ("%s_%c%d"), m
->name
,
804 ts
->type
== BT_COMPLEX
? 'c' : 'r',
809 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
811 type
= gfc_typenode_for_spec (&actual
->expr
->ts
);
812 vec_safe_push (argtypes
, type
);
814 type
= build_function_type_vec (gfc_typenode_for_spec (ts
), argtypes
);
815 fndecl
= build_decl (input_location
,
816 FUNCTION_DECL
, get_identifier (name
), type
);
818 /* Mark the decl as external. */
819 DECL_EXTERNAL (fndecl
) = 1;
820 TREE_PUBLIC (fndecl
) = 1;
822 /* Mark it __attribute__((const)), if possible. */
823 TREE_READONLY (fndecl
) = m
->is_constant
;
825 rest_of_decl_compilation (fndecl
, 1, 0);
832 /* Convert an intrinsic function into an external or builtin call. */
835 gfc_conv_intrinsic_lib_function (gfc_se
* se
, gfc_expr
* expr
)
837 gfc_intrinsic_map_t
*m
;
841 unsigned int num_args
;
844 id
= expr
->value
.function
.isym
->id
;
845 /* Find the entry for this function. */
846 for (m
= gfc_intrinsic_map
;
847 m
->id
!= GFC_ISYM_NONE
|| m
->double_built_in
!= END_BUILTINS
; m
++)
853 if (m
->id
== GFC_ISYM_NONE
)
855 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
856 expr
->value
.function
.name
, id
);
859 /* Get the decl and generate the call. */
860 num_args
= gfc_intrinsic_argument_list_length (expr
);
861 args
= XALLOCAVEC (tree
, num_args
);
863 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
864 fndecl
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
865 rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
867 fndecl
= build_addr (fndecl
);
868 se
->expr
= build_call_array_loc (input_location
, rettype
, fndecl
, num_args
, args
);
872 /* If bounds-checking is enabled, create code to verify at runtime that the
873 string lengths for both expressions are the same (needed for e.g. MERGE).
874 If bounds-checking is not enabled, does nothing. */
877 gfc_trans_same_strlen_check (const char* intr_name
, locus
* where
,
878 tree a
, tree b
, stmtblock_t
* target
)
883 /* If bounds-checking is disabled, do nothing. */
884 if (!(gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
))
887 /* Compare the two string lengths. */
888 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, a
, b
);
890 /* Output the runtime-check. */
891 name
= gfc_build_cstring_const (intr_name
);
892 name
= gfc_build_addr_expr (pchar_type_node
, name
);
893 gfc_trans_runtime_check (true, false, cond
, target
, where
,
894 "Unequal character lengths (%ld/%ld) in %s",
895 fold_convert (long_integer_type_node
, a
),
896 fold_convert (long_integer_type_node
, b
), name
);
900 /* The EXPONENT(X) intrinsic function is translated into
902 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
903 so that if X is a NaN or infinity, the result is HUGE(0).
907 gfc_conv_intrinsic_exponent (gfc_se
*se
, gfc_expr
*expr
)
909 tree arg
, type
, res
, tmp
, frexp
, cond
, huge
;
912 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
,
913 expr
->value
.function
.actual
->expr
->ts
.kind
);
915 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
916 arg
= gfc_evaluate_now (arg
, &se
->pre
);
918 i
= gfc_validate_kind (BT_INTEGER
, gfc_c_int_kind
, false);
919 huge
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].huge
, gfc_c_int_kind
);
920 cond
= build_call_expr_loc (input_location
,
921 builtin_decl_explicit (BUILT_IN_ISFINITE
),
924 res
= gfc_create_var (integer_type_node
, NULL
);
925 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
926 gfc_build_addr_expr (NULL_TREE
, res
));
927 tmp
= fold_build2_loc (input_location
, COMPOUND_EXPR
, integer_type_node
,
929 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
932 type
= gfc_typenode_for_spec (&expr
->ts
);
933 se
->expr
= fold_convert (type
, se
->expr
);
937 /* Fill in the following structure
938 struct caf_vector_t {
939 size_t nvec; // size of the vector
946 ptrdiff_t lower_bound;
947 ptrdiff_t upper_bound;
954 conv_caf_vector_subscript_elem (stmtblock_t
*block
, int i
, tree desc
,
955 tree lower
, tree upper
, tree stride
,
956 tree vector
, int kind
, tree nvec
)
958 tree field
, type
, tmp
;
960 desc
= gfc_build_array_ref (desc
, gfc_rank_cst
[i
], NULL_TREE
);
961 type
= TREE_TYPE (desc
);
963 field
= gfc_advance_chain (TYPE_FIELDS (type
), 0);
964 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
965 desc
, field
, NULL_TREE
);
966 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), nvec
));
969 field
= gfc_advance_chain (TYPE_FIELDS (type
), 1);
970 desc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
971 desc
, field
, NULL_TREE
);
972 type
= TREE_TYPE (desc
);
974 /* Access the inner struct. */
975 field
= gfc_advance_chain (TYPE_FIELDS (type
), vector
!= NULL_TREE
? 0 : 1);
976 desc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
977 desc
, field
, NULL_TREE
);
978 type
= TREE_TYPE (desc
);
980 if (vector
!= NULL_TREE
)
982 /* Set vector and kind. */
983 field
= gfc_advance_chain (TYPE_FIELDS (type
), 0);
984 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
985 desc
, field
, NULL_TREE
);
986 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), vector
));
987 field
= gfc_advance_chain (TYPE_FIELDS (type
), 1);
988 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
989 desc
, field
, NULL_TREE
);
990 gfc_add_modify (block
, tmp
, build_int_cst (integer_type_node
, kind
));
994 /* Set dim.lower/upper/stride. */
995 field
= gfc_advance_chain (TYPE_FIELDS (type
), 0);
996 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
997 desc
, field
, NULL_TREE
);
998 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), lower
));
1000 field
= gfc_advance_chain (TYPE_FIELDS (type
), 1);
1001 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1002 desc
, field
, NULL_TREE
);
1003 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), upper
));
1005 field
= gfc_advance_chain (TYPE_FIELDS (type
), 2);
1006 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1007 desc
, field
, NULL_TREE
);
1008 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), stride
));
1014 conv_caf_vector_subscript (stmtblock_t
*block
, tree desc
, gfc_array_ref
*ar
)
1017 tree var
, lower
, upper
= NULL_TREE
, stride
= NULL_TREE
, vector
, nvec
;
1018 tree lbound
, ubound
, tmp
;
1021 var
= gfc_create_var (gfc_get_caf_vector_type (ar
->dimen
), "vector");
1023 for (i
= 0; i
< ar
->dimen
; i
++)
1024 switch (ar
->dimen_type
[i
])
1029 gfc_init_se (&argse
, NULL
);
1030 gfc_conv_expr (&argse
, ar
->end
[i
]);
1031 gfc_add_block_to_block (block
, &argse
.pre
);
1032 upper
= gfc_evaluate_now (argse
.expr
, block
);
1035 upper
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[i
]);
1038 gfc_init_se (&argse
, NULL
);
1039 gfc_conv_expr (&argse
, ar
->stride
[i
]);
1040 gfc_add_block_to_block (block
, &argse
.pre
);
1041 stride
= gfc_evaluate_now (argse
.expr
, block
);
1044 stride
= gfc_index_one_node
;
1050 gfc_init_se (&argse
, NULL
);
1051 gfc_conv_expr (&argse
, ar
->start
[i
]);
1052 gfc_add_block_to_block (block
, &argse
.pre
);
1053 lower
= gfc_evaluate_now (argse
.expr
, block
);
1056 lower
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[i
]);
1057 if (ar
->dimen_type
[i
] == DIMEN_ELEMENT
)
1060 stride
= gfc_index_one_node
;
1063 nvec
= size_zero_node
;
1064 conv_caf_vector_subscript_elem (block
, i
, var
, lower
, upper
, stride
,
1069 gfc_init_se (&argse
, NULL
);
1070 argse
.descriptor_only
= 1;
1071 gfc_conv_expr_descriptor (&argse
, ar
->start
[i
]);
1072 gfc_add_block_to_block (block
, &argse
.pre
);
1073 vector
= argse
.expr
;
1074 lbound
= gfc_conv_descriptor_lbound_get (vector
, gfc_rank_cst
[0]);
1075 ubound
= gfc_conv_descriptor_ubound_get (vector
, gfc_rank_cst
[0]);
1076 nvec
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
1077 tmp
= gfc_conv_descriptor_stride_get (vector
, gfc_rank_cst
[0]);
1078 nvec
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
1079 TREE_TYPE (nvec
), nvec
, tmp
);
1080 lower
= gfc_index_zero_node
;
1081 upper
= gfc_index_zero_node
;
1082 stride
= gfc_index_zero_node
;
1083 vector
= gfc_conv_descriptor_data_get (vector
);
1084 conv_caf_vector_subscript_elem (block
, i
, var
, lower
, upper
, stride
,
1085 vector
, ar
->start
[i
]->ts
.kind
, nvec
);
1090 return gfc_build_addr_expr (NULL_TREE
, var
);
1095 compute_component_offset (tree field
, tree type
)
1098 if (DECL_FIELD_BIT_OFFSET (field
) != NULL_TREE
1099 && !integer_zerop (DECL_FIELD_BIT_OFFSET (field
)))
1101 tmp
= fold_build2 (TRUNC_DIV_EXPR
, type
,
1102 DECL_FIELD_BIT_OFFSET (field
),
1104 return fold_build2 (PLUS_EXPR
, type
, DECL_FIELD_OFFSET (field
), tmp
);
1107 return DECL_FIELD_OFFSET (field
);
1112 conv_expr_ref_to_caf_ref (stmtblock_t
*block
, gfc_expr
*expr
)
1114 gfc_ref
*ref
= expr
->ref
, *last_comp_ref
;
1115 tree caf_ref
= NULL_TREE
, prev_caf_ref
= NULL_TREE
, reference_type
, tmp
, tmp2
,
1116 field
, last_type
, inner_struct
, mode
, mode_rhs
, dim_array
, dim
, dim_type
,
1117 start
, end
, stride
, vector
, nvec
;
1119 bool ref_static_array
= false;
1120 tree last_component_ref_tree
= NULL_TREE
;
1125 last_component_ref_tree
= expr
->symtree
->n
.sym
->backend_decl
;
1126 ref_static_array
= !expr
->symtree
->n
.sym
->attr
.allocatable
1127 && !expr
->symtree
->n
.sym
->attr
.pointer
;
1130 /* Prevent uninit-warning. */
1131 reference_type
= NULL_TREE
;
1133 /* Skip refs upto the first coarray-ref. */
1134 last_comp_ref
= NULL
;
1135 while (ref
&& (ref
->type
!= REF_ARRAY
|| ref
->u
.ar
.codimen
== 0))
1137 /* Remember the type of components skipped. */
1138 if (ref
->type
== REF_COMPONENT
)
1139 last_comp_ref
= ref
;
1142 /* When a component was skipped, get the type information of the last
1143 component ref, else get the type from the symbol. */
1146 last_type
= gfc_typenode_for_spec (&last_comp_ref
->u
.c
.component
->ts
);
1147 last_type_n
= last_comp_ref
->u
.c
.component
->ts
.type
;
1151 last_type
= gfc_typenode_for_spec (&expr
->symtree
->n
.sym
->ts
);
1152 last_type_n
= expr
->symtree
->n
.sym
->ts
.type
;
1157 if (ref
->type
== REF_ARRAY
&& ref
->u
.ar
.codimen
> 0
1158 && ref
->u
.ar
.dimen
== 0)
1160 /* Skip pure coindexes. */
1164 tmp
= gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
1165 reference_type
= TREE_TYPE (tmp
);
1167 if (caf_ref
== NULL_TREE
)
1170 /* Construct the chain of refs. */
1171 if (prev_caf_ref
!= NULL_TREE
)
1173 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 0);
1174 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1175 TREE_TYPE (field
), prev_caf_ref
, field
,
1177 gfc_add_modify (block
, tmp2
, gfc_build_addr_expr (TREE_TYPE (field
),
1185 last_type
= gfc_typenode_for_spec (&ref
->u
.c
.component
->ts
);
1186 last_type_n
= ref
->u
.c
.component
->ts
.type
;
1187 /* Set the type of the ref. */
1188 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 1);
1189 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1190 TREE_TYPE (field
), prev_caf_ref
, field
,
1192 gfc_add_modify (block
, tmp
, build_int_cst (integer_type_node
,
1193 GFC_CAF_REF_COMPONENT
));
1195 /* Ref the c in union u. */
1196 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 3);
1197 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1198 TREE_TYPE (field
), prev_caf_ref
, field
,
1200 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field
)), 0);
1201 inner_struct
= fold_build3_loc (input_location
, COMPONENT_REF
,
1202 TREE_TYPE (field
), tmp
, field
,
1205 /* Set the offset. */
1206 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)), 0);
1207 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1208 TREE_TYPE (field
), inner_struct
, field
,
1210 /* Computing the offset is somewhat harder. The bit_offset has to be
1211 taken into account. When the bit_offset in the field_decl is non-
1212 null, divide it by the bitsize_unit and add it to the regular
1214 tmp2
= compute_component_offset (ref
->u
.c
.component
->backend_decl
,
1216 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (tmp
), tmp2
));
1218 /* Set caf_token_offset. */
1219 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)), 1);
1220 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1221 TREE_TYPE (field
), inner_struct
, field
,
1223 if ((ref
->u
.c
.component
->attr
.allocatable
1224 || ref
->u
.c
.component
->attr
.pointer
)
1225 && ref
->u
.c
.component
->attr
.dimension
)
1227 tree arr_desc_token_offset
;
1228 /* Get the token field from the descriptor. */
1229 arr_desc_token_offset
= TREE_OPERAND (
1230 gfc_conv_descriptor_token (ref
->u
.c
.component
->backend_decl
), 1);
1231 arr_desc_token_offset
1232 = compute_component_offset (arr_desc_token_offset
,
1234 tmp2
= fold_build2_loc (input_location
, PLUS_EXPR
,
1235 TREE_TYPE (tmp2
), tmp2
,
1236 arr_desc_token_offset
);
1238 else if (ref
->u
.c
.component
->caf_token
)
1239 tmp2
= compute_component_offset (ref
->u
.c
.component
->caf_token
,
1242 tmp2
= integer_zero_node
;
1243 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (tmp
), tmp2
));
1245 /* Remember whether this ref was to a non-allocatable/non-pointer
1246 component so the next array ref can be tailored correctly. */
1247 ref_static_array
= !ref
->u
.c
.component
->attr
.allocatable
1248 && !ref
->u
.c
.component
->attr
.pointer
;
1249 last_component_ref_tree
= ref_static_array
1250 ? ref
->u
.c
.component
->backend_decl
: NULL_TREE
;
1253 if (ref_static_array
&& ref
->u
.ar
.as
->type
== AS_DEFERRED
)
1254 ref_static_array
= false;
1255 /* Set the type of the ref. */
1256 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 1);
1257 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1258 TREE_TYPE (field
), prev_caf_ref
, field
,
1260 gfc_add_modify (block
, tmp
, build_int_cst (integer_type_node
,
1262 ? GFC_CAF_REF_STATIC_ARRAY
1263 : GFC_CAF_REF_ARRAY
));
1265 /* Ref the a in union u. */
1266 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 3);
1267 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1268 TREE_TYPE (field
), prev_caf_ref
, field
,
1270 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field
)), 1);
1271 inner_struct
= fold_build3_loc (input_location
, COMPONENT_REF
,
1272 TREE_TYPE (field
), tmp
, field
,
1275 /* Set the static_array_type in a for static arrays. */
1276 if (ref_static_array
)
1278 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)),
1280 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1281 TREE_TYPE (field
), inner_struct
, field
,
1283 gfc_add_modify (block
, tmp
, build_int_cst (TREE_TYPE (tmp
),
1286 /* Ref the mode in the inner_struct. */
1287 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)), 0);
1288 mode
= fold_build3_loc (input_location
, COMPONENT_REF
,
1289 TREE_TYPE (field
), inner_struct
, field
,
1291 /* Ref the dim in the inner_struct. */
1292 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct
)), 2);
1293 dim_array
= fold_build3_loc (input_location
, COMPONENT_REF
,
1294 TREE_TYPE (field
), inner_struct
, field
,
1296 for (i
= 0; i
< ref
->u
.ar
.dimen
; ++i
)
1299 dim
= gfc_build_array_ref (dim_array
, gfc_rank_cst
[i
], NULL_TREE
);
1300 dim_type
= TREE_TYPE (dim
);
1301 mode_rhs
= start
= end
= stride
= NULL_TREE
;
1302 switch (ref
->u
.ar
.dimen_type
[i
])
1305 if (ref
->u
.ar
.end
[i
])
1307 gfc_init_se (&se
, NULL
);
1308 gfc_conv_expr (&se
, ref
->u
.ar
.end
[i
]);
1309 gfc_add_block_to_block (block
, &se
.pre
);
1310 if (ref_static_array
)
1312 /* Make the index zero-based, when reffing a static
1315 gfc_init_se (&se
, NULL
);
1316 gfc_conv_expr (&se
, ref
->u
.ar
.as
->lower
[i
]);
1317 gfc_add_block_to_block (block
, &se
.pre
);
1318 se
.expr
= fold_build2 (MINUS_EXPR
,
1319 gfc_array_index_type
,
1321 gfc_array_index_type
,
1324 end
= gfc_evaluate_now (fold_convert (
1325 gfc_array_index_type
,
1329 else if (ref_static_array
)
1330 end
= fold_build2 (MINUS_EXPR
,
1331 gfc_array_index_type
,
1332 gfc_conv_array_ubound (
1333 last_component_ref_tree
, i
),
1334 gfc_conv_array_lbound (
1335 last_component_ref_tree
, i
));
1339 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1340 GFC_CAF_ARR_REF_OPEN_END
);
1342 if (ref
->u
.ar
.stride
[i
])
1344 gfc_init_se (&se
, NULL
);
1345 gfc_conv_expr (&se
, ref
->u
.ar
.stride
[i
]);
1346 gfc_add_block_to_block (block
, &se
.pre
);
1347 stride
= gfc_evaluate_now (fold_convert (
1348 gfc_array_index_type
,
1351 if (ref_static_array
)
1353 /* Make the index zero-based, when reffing a static
1355 stride
= fold_build2 (MULT_EXPR
,
1356 gfc_array_index_type
,
1357 gfc_conv_array_stride (
1358 last_component_ref_tree
,
1361 gcc_assert (end
!= NULL_TREE
);
1362 /* Multiply with the product of array's stride and
1363 the step of the ref to a virtual upper bound.
1364 We can not compute the actual upper bound here or
1365 the caflib would compute the extend
1367 end
= fold_build2 (MULT_EXPR
, gfc_array_index_type
,
1368 end
, gfc_conv_array_stride (
1369 last_component_ref_tree
,
1371 end
= gfc_evaluate_now (end
, block
);
1372 stride
= gfc_evaluate_now (stride
, block
);
1375 else if (ref_static_array
)
1377 stride
= gfc_conv_array_stride (last_component_ref_tree
,
1379 end
= fold_build2 (MULT_EXPR
, gfc_array_index_type
,
1381 end
= gfc_evaluate_now (end
, block
);
1384 /* Always set a ref stride of one to make caflib's
1386 stride
= gfc_index_one_node
;
1390 if (ref
->u
.ar
.start
[i
])
1392 gfc_init_se (&se
, NULL
);
1393 gfc_conv_expr (&se
, ref
->u
.ar
.start
[i
]);
1394 gfc_add_block_to_block (block
, &se
.pre
);
1395 if (ref_static_array
)
1397 /* Make the index zero-based, when reffing a static
1399 start
= fold_convert (gfc_array_index_type
, se
.expr
);
1400 gfc_init_se (&se
, NULL
);
1401 gfc_conv_expr (&se
, ref
->u
.ar
.as
->lower
[i
]);
1402 gfc_add_block_to_block (block
, &se
.pre
);
1403 se
.expr
= fold_build2 (MINUS_EXPR
,
1404 gfc_array_index_type
,
1405 start
, fold_convert (
1406 gfc_array_index_type
,
1408 /* Multiply with the stride. */
1409 se
.expr
= fold_build2 (MULT_EXPR
,
1410 gfc_array_index_type
,
1412 gfc_conv_array_stride (
1413 last_component_ref_tree
,
1416 start
= gfc_evaluate_now (fold_convert (
1417 gfc_array_index_type
,
1420 if (mode_rhs
== NULL_TREE
)
1421 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1422 ref
->u
.ar
.dimen_type
[i
]
1424 ? GFC_CAF_ARR_REF_SINGLE
1425 : GFC_CAF_ARR_REF_RANGE
);
1427 else if (ref_static_array
)
1429 start
= integer_zero_node
;
1430 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1431 ref
->u
.ar
.start
[i
] == NULL
1432 ? GFC_CAF_ARR_REF_FULL
1433 : GFC_CAF_ARR_REF_RANGE
);
1435 else if (end
== NULL_TREE
)
1436 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1437 GFC_CAF_ARR_REF_FULL
);
1439 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1440 GFC_CAF_ARR_REF_OPEN_START
);
1442 /* Ref the s in dim. */
1443 field
= gfc_advance_chain (TYPE_FIELDS (dim_type
), 0);
1444 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1445 TREE_TYPE (field
), dim
, field
,
1448 /* Set start in s. */
1449 if (start
!= NULL_TREE
)
1451 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)),
1453 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1454 TREE_TYPE (field
), tmp
, field
,
1456 gfc_add_modify (block
, tmp2
,
1457 fold_convert (TREE_TYPE (tmp2
), start
));
1461 if (end
!= NULL_TREE
)
1463 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)),
1465 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1466 TREE_TYPE (field
), tmp
, field
,
1468 gfc_add_modify (block
, tmp2
,
1469 fold_convert (TREE_TYPE (tmp2
), end
));
1473 if (stride
!= NULL_TREE
)
1475 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)),
1477 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1478 TREE_TYPE (field
), tmp
, field
,
1480 gfc_add_modify (block
, tmp2
,
1481 fold_convert (TREE_TYPE (tmp2
), stride
));
1485 /* TODO: In case of static array. */
1486 gcc_assert (!ref_static_array
);
1487 mode_rhs
= build_int_cst (unsigned_char_type_node
,
1488 GFC_CAF_ARR_REF_VECTOR
);
1489 gfc_init_se (&se
, NULL
);
1490 se
.descriptor_only
= 1;
1491 gfc_conv_expr_descriptor (&se
, ref
->u
.ar
.start
[i
]);
1492 gfc_add_block_to_block (block
, &se
.pre
);
1494 tmp
= gfc_conv_descriptor_lbound_get (vector
,
1496 tmp2
= gfc_conv_descriptor_ubound_get (vector
,
1498 nvec
= gfc_conv_array_extent_dim (tmp
, tmp2
, NULL
);
1499 tmp
= gfc_conv_descriptor_stride_get (vector
,
1501 nvec
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
1502 TREE_TYPE (nvec
), nvec
, tmp
);
1503 vector
= gfc_conv_descriptor_data_get (vector
);
1505 /* Ref the v in dim. */
1506 field
= gfc_advance_chain (TYPE_FIELDS (dim_type
), 1);
1507 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
,
1508 TREE_TYPE (field
), dim
, field
,
1511 /* Set vector in v. */
1512 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)), 0);
1513 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1514 TREE_TYPE (field
), tmp
, field
,
1516 gfc_add_modify (block
, tmp2
, fold_convert (TREE_TYPE (tmp2
),
1519 /* Set nvec in v. */
1520 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)), 1);
1521 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1522 TREE_TYPE (field
), tmp
, field
,
1524 gfc_add_modify (block
, tmp2
, fold_convert (TREE_TYPE (tmp2
),
1527 /* Set kind in v. */
1528 field
= gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp
)), 2);
1529 tmp2
= fold_build3_loc (input_location
, COMPONENT_REF
,
1530 TREE_TYPE (field
), tmp
, field
,
1532 gfc_add_modify (block
, tmp2
, build_int_cst (integer_type_node
,
1533 ref
->u
.ar
.start
[i
]->ts
.kind
));
1538 /* Set the mode for dim i. */
1539 tmp
= gfc_build_array_ref (mode
, gfc_rank_cst
[i
], NULL_TREE
);
1540 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (tmp
),
1544 /* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
1545 if (i
< GFC_MAX_DIMENSIONS
)
1547 tmp
= gfc_build_array_ref (mode
, gfc_rank_cst
[i
], NULL_TREE
);
1548 gfc_add_modify (block
, tmp
,
1549 build_int_cst (unsigned_char_type_node
,
1550 GFC_CAF_ARR_REF_NONE
));
1557 /* Set the size of the current type. */
1558 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 2);
1559 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1560 prev_caf_ref
, field
, NULL_TREE
);
1561 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
),
1562 TYPE_SIZE_UNIT (last_type
)));
1567 if (prev_caf_ref
!= NULL_TREE
)
1569 field
= gfc_advance_chain (TYPE_FIELDS (reference_type
), 0);
1570 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1571 prev_caf_ref
, field
, NULL_TREE
);
1572 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
),
1573 null_pointer_node
));
1575 return caf_ref
!= NULL_TREE
? gfc_build_addr_expr (NULL_TREE
, caf_ref
)
1579 /* Get data from a remote coarray. */
1582 gfc_conv_intrinsic_caf_get (gfc_se
*se
, gfc_expr
*expr
, tree lhs
, tree lhs_kind
,
1583 tree may_require_tmp
, bool may_realloc
,
1584 symbol_attribute
*caf_attr
)
1586 gfc_expr
*array_expr
, *tmp_stat
;
1588 tree caf_decl
, token
, offset
, image_index
, tmp
;
1589 tree res_var
, dst_var
, type
, kind
, vec
, stat
;
1591 symbol_attribute caf_attr_store
;
1593 gcc_assert (flag_coarray
== GFC_FCOARRAY_LIB
);
1595 if (se
->ss
&& se
->ss
->info
->useflags
)
1597 /* Access the previously obtained result. */
1598 gfc_conv_tmp_array_ref (se
);
1602 /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1603 array_expr
= (lhs
== NULL_TREE
) ? expr
->value
.function
.actual
->expr
: expr
;
1604 type
= gfc_typenode_for_spec (&array_expr
->ts
);
1606 if (caf_attr
== NULL
)
1608 caf_attr_store
= gfc_caf_attr (array_expr
);
1609 caf_attr
= &caf_attr_store
;
1615 vec
= null_pointer_node
;
1616 tmp_stat
= gfc_find_stat_co (expr
);
1621 gfc_init_se (&stat_se
, NULL
);
1622 gfc_conv_expr_reference (&stat_se
, tmp_stat
);
1623 stat
= stat_se
.expr
;
1624 gfc_add_block_to_block (&se
->pre
, &stat_se
.pre
);
1625 gfc_add_block_to_block (&se
->post
, &stat_se
.post
);
1628 stat
= null_pointer_node
;
1630 /* Only use the new get_by_ref () where it is necessary. I.e., when the lhs
1631 is reallocatable or the right-hand side has allocatable components. */
1632 if (caf_attr
->alloc_comp
|| caf_attr
->pointer_comp
|| may_realloc
)
1634 /* Get using caf_get_by_ref. */
1635 caf_reference
= conv_expr_ref_to_caf_ref (&se
->pre
, array_expr
);
1637 if (caf_reference
!= NULL_TREE
)
1639 if (lhs
== NULL_TREE
)
1641 if (array_expr
->ts
.type
== BT_CHARACTER
)
1642 gfc_init_se (&argse
, NULL
);
1643 if (array_expr
->rank
== 0)
1645 symbol_attribute attr
;
1646 gfc_clear_attr (&attr
);
1647 if (array_expr
->ts
.type
== BT_CHARACTER
)
1649 res_var
= gfc_conv_string_tmp (se
,
1650 build_pointer_type (type
),
1651 array_expr
->ts
.u
.cl
->backend_decl
);
1652 argse
.string_length
= array_expr
->ts
.u
.cl
->backend_decl
;
1655 res_var
= gfc_create_var (type
, "caf_res");
1656 dst_var
= gfc_conv_scalar_to_descriptor (se
, res_var
, attr
);
1657 dst_var
= gfc_build_addr_expr (NULL_TREE
, dst_var
);
1661 /* Create temporary. */
1662 if (array_expr
->ts
.type
== BT_CHARACTER
)
1663 gfc_conv_expr_descriptor (&argse
, array_expr
);
1664 may_realloc
= gfc_trans_create_temp_array (&se
->pre
,
1671 res_var
= se
->ss
->info
->data
.array
.descriptor
;
1672 dst_var
= gfc_build_addr_expr (NULL_TREE
, res_var
);
1675 tmp
= gfc_conv_descriptor_data_get (res_var
);
1676 tmp
= gfc_deallocate_with_status (tmp
, NULL_TREE
,
1677 NULL_TREE
, NULL_TREE
,
1680 GFC_CAF_COARRAY_NOCOARRAY
);
1681 gfc_add_expr_to_block (&se
->post
, tmp
);
1686 kind
= build_int_cst (integer_type_node
, expr
->ts
.kind
);
1687 if (lhs_kind
== NULL_TREE
)
1690 caf_decl
= gfc_get_tree_for_caf_expr (array_expr
);
1691 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
1692 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
1693 image_index
= gfc_caf_get_image_index (&se
->pre
, array_expr
,
1695 gfc_get_caf_token_offset (se
, &token
, NULL
, caf_decl
, NULL
,
1698 /* No overlap possible as we have generated a temporary. */
1699 if (lhs
== NULL_TREE
)
1700 may_require_tmp
= boolean_false_node
;
1702 /* It guarantees memory consistency within the same segment. */
1703 tmp
= gfc_build_string_const (strlen ("memory") + 1, "memory");
1704 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
1705 gfc_build_string_const (1, ""), NULL_TREE
,
1706 NULL_TREE
, tree_cons (NULL_TREE
, tmp
, NULL_TREE
),
1708 ASM_VOLATILE_P (tmp
) = 1;
1709 gfc_add_expr_to_block (&se
->pre
, tmp
);
1711 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_get_by_ref
,
1712 10, token
, image_index
, dst_var
,
1713 caf_reference
, lhs_kind
, kind
,
1715 may_realloc
? boolean_true_node
:
1717 stat
, build_int_cst (integer_type_node
,
1718 array_expr
->ts
.type
));
1720 gfc_add_expr_to_block (&se
->pre
, tmp
);
1723 gfc_advance_se_ss_chain (se
);
1726 if (array_expr
->ts
.type
== BT_CHARACTER
)
1727 se
->string_length
= argse
.string_length
;
1733 gfc_init_se (&argse
, NULL
);
1734 if (array_expr
->rank
== 0)
1736 symbol_attribute attr
;
1738 gfc_clear_attr (&attr
);
1739 gfc_conv_expr (&argse
, array_expr
);
1741 if (lhs
== NULL_TREE
)
1743 gfc_clear_attr (&attr
);
1744 if (array_expr
->ts
.type
== BT_CHARACTER
)
1745 res_var
= gfc_conv_string_tmp (se
, build_pointer_type (type
),
1746 argse
.string_length
);
1748 res_var
= gfc_create_var (type
, "caf_res");
1749 dst_var
= gfc_conv_scalar_to_descriptor (&argse
, res_var
, attr
);
1750 dst_var
= gfc_build_addr_expr (NULL_TREE
, dst_var
);
1752 argse
.expr
= gfc_conv_scalar_to_descriptor (&argse
, argse
.expr
, attr
);
1753 argse
.expr
= gfc_build_addr_expr (NULL_TREE
, argse
.expr
);
1757 /* If has_vector, pass descriptor for whole array and the
1758 vector bounds separately. */
1759 gfc_array_ref
*ar
, ar2
;
1760 bool has_vector
= false;
1762 if (gfc_is_coindexed (expr
) && gfc_has_vector_subscript (expr
))
1765 ar
= gfc_find_array_ref (expr
);
1767 memset (ar
, '\0', sizeof (*ar
));
1771 // TODO: Check whether argse.want_coarray = 1 can help with the below.
1772 gfc_conv_expr_descriptor (&argse
, array_expr
);
1773 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1774 has the wrong type if component references are done. */
1775 gfc_add_modify (&argse
.pre
, gfc_conv_descriptor_dtype (argse
.expr
),
1776 gfc_get_dtype_rank_type (has_vector
? ar2
.dimen
1781 vec
= conv_caf_vector_subscript (&argse
.pre
, argse
.expr
, &ar2
);
1785 if (lhs
== NULL_TREE
)
1787 /* Create temporary. */
1788 for (int n
= 0; n
< se
->ss
->loop
->dimen
; n
++)
1789 if (se
->loop
->to
[n
] == NULL_TREE
)
1791 se
->loop
->from
[n
] = gfc_conv_descriptor_lbound_get (argse
.expr
,
1793 se
->loop
->to
[n
] = gfc_conv_descriptor_ubound_get (argse
.expr
,
1796 gfc_trans_create_temp_array (&argse
.pre
, &argse
.post
, se
->ss
, type
,
1797 NULL_TREE
, false, true, false,
1798 &array_expr
->where
);
1799 res_var
= se
->ss
->info
->data
.array
.descriptor
;
1800 dst_var
= gfc_build_addr_expr (NULL_TREE
, res_var
);
1802 argse
.expr
= gfc_build_addr_expr (NULL_TREE
, argse
.expr
);
1805 kind
= build_int_cst (integer_type_node
, expr
->ts
.kind
);
1806 if (lhs_kind
== NULL_TREE
)
1809 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1810 gfc_add_block_to_block (&se
->post
, &argse
.post
);
1812 caf_decl
= gfc_get_tree_for_caf_expr (array_expr
);
1813 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
1814 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
1815 image_index
= gfc_caf_get_image_index (&se
->pre
, array_expr
, caf_decl
);
1816 gfc_get_caf_token_offset (se
, &token
, &offset
, caf_decl
, argse
.expr
,
1819 /* No overlap possible as we have generated a temporary. */
1820 if (lhs
== NULL_TREE
)
1821 may_require_tmp
= boolean_false_node
;
1823 /* It guarantees memory consistency within the same segment. */
1824 tmp
= gfc_build_string_const (strlen ("memory") + 1, "memory");
1825 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
1826 gfc_build_string_const (1, ""), NULL_TREE
, NULL_TREE
,
1827 tree_cons (NULL_TREE
, tmp
, NULL_TREE
), NULL_TREE
);
1828 ASM_VOLATILE_P (tmp
) = 1;
1829 gfc_add_expr_to_block (&se
->pre
, tmp
);
1831 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_get
, 10,
1832 token
, offset
, image_index
, argse
.expr
, vec
,
1833 dst_var
, kind
, lhs_kind
, may_require_tmp
, stat
);
1835 gfc_add_expr_to_block (&se
->pre
, tmp
);
1838 gfc_advance_se_ss_chain (se
);
1841 if (array_expr
->ts
.type
== BT_CHARACTER
)
1842 se
->string_length
= argse
.string_length
;
1846 /* Send data to a remote coarray. */
1849 conv_caf_send (gfc_code
*code
) {
1850 gfc_expr
*lhs_expr
, *rhs_expr
, *tmp_stat
, *tmp_team
;
1851 gfc_se lhs_se
, rhs_se
;
1853 tree caf_decl
, token
, offset
, image_index
, tmp
, lhs_kind
, rhs_kind
;
1854 tree may_require_tmp
, src_stat
, dst_stat
, dst_team
;
1855 tree lhs_type
= NULL_TREE
;
1856 tree vec
= null_pointer_node
, rhs_vec
= null_pointer_node
;
1857 symbol_attribute lhs_caf_attr
, rhs_caf_attr
;
1859 gcc_assert (flag_coarray
== GFC_FCOARRAY_LIB
);
1861 lhs_expr
= code
->ext
.actual
->expr
;
1862 rhs_expr
= code
->ext
.actual
->next
->expr
;
1863 may_require_tmp
= gfc_check_dependency (lhs_expr
, rhs_expr
, true) == 0
1864 ? boolean_false_node
: boolean_true_node
;
1865 gfc_init_block (&block
);
1867 lhs_caf_attr
= gfc_caf_attr (lhs_expr
);
1868 rhs_caf_attr
= gfc_caf_attr (rhs_expr
);
1869 src_stat
= dst_stat
= null_pointer_node
;
1870 dst_team
= null_pointer_node
;
1873 gfc_init_se (&lhs_se
, NULL
);
1874 if (lhs_expr
->rank
== 0)
1876 if (lhs_expr
->ts
.type
== BT_CHARACTER
&& lhs_expr
->ts
.deferred
)
1878 lhs_se
.expr
= gfc_get_tree_for_caf_expr (lhs_expr
);
1879 lhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, lhs_se
.expr
);
1883 symbol_attribute attr
;
1884 gfc_clear_attr (&attr
);
1885 gfc_conv_expr (&lhs_se
, lhs_expr
);
1886 lhs_type
= TREE_TYPE (lhs_se
.expr
);
1887 lhs_se
.expr
= gfc_conv_scalar_to_descriptor (&lhs_se
, lhs_se
.expr
,
1889 lhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, lhs_se
.expr
);
1892 else if ((lhs_caf_attr
.alloc_comp
|| lhs_caf_attr
.pointer_comp
)
1893 && lhs_caf_attr
.codimension
)
1895 lhs_se
.want_pointer
= 1;
1896 gfc_conv_expr_descriptor (&lhs_se
, lhs_expr
);
1897 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1898 has the wrong type if component references are done. */
1899 lhs_type
= gfc_typenode_for_spec (&lhs_expr
->ts
);
1900 tmp
= build_fold_indirect_ref_loc (input_location
, lhs_se
.expr
);
1901 gfc_add_modify (&lhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
1902 gfc_get_dtype_rank_type (
1903 gfc_has_vector_subscript (lhs_expr
)
1904 ? gfc_find_array_ref (lhs_expr
)->dimen
1910 bool has_vector
= gfc_has_vector_subscript (lhs_expr
);
1912 if (gfc_is_coindexed (lhs_expr
) || !has_vector
)
1914 /* If has_vector, pass descriptor for whole array and the
1915 vector bounds separately. */
1916 gfc_array_ref
*ar
, ar2
;
1917 bool has_tmp_lhs_array
= false;
1920 has_tmp_lhs_array
= true;
1921 ar
= gfc_find_array_ref (lhs_expr
);
1923 memset (ar
, '\0', sizeof (*ar
));
1927 lhs_se
.want_pointer
= 1;
1928 gfc_conv_expr_descriptor (&lhs_se
, lhs_expr
);
1929 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but
1930 that has the wrong type if component references are done. */
1931 lhs_type
= gfc_typenode_for_spec (&lhs_expr
->ts
);
1932 tmp
= build_fold_indirect_ref_loc (input_location
, lhs_se
.expr
);
1933 gfc_add_modify (&lhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
1934 gfc_get_dtype_rank_type (has_vector
? ar2
.dimen
1937 if (has_tmp_lhs_array
)
1939 vec
= conv_caf_vector_subscript (&block
, lhs_se
.expr
, &ar2
);
1945 /* Special casing for arr1 ([...]) = arr2[...], i.e. caf_get to
1946 indexed array expression. This is rewritten to:
1948 tmp_array = arr2[...]
1949 arr1 ([...]) = tmp_array
1951 because using the standard gfc_conv_expr (lhs_expr) did the
1952 assignment with lhs and rhs exchanged. */
1954 gfc_ss
*lss_for_tmparray
, *lss_real
;
1958 tree tmparr_desc
, src
;
1959 tree index
= gfc_index_zero_node
;
1960 tree stride
= gfc_index_zero_node
;
1963 /* Walk both sides of the assignment, once to get the shape of the
1964 temporary array to create right. */
1965 lss_for_tmparray
= gfc_walk_expr (lhs_expr
);
1966 /* And a second time to be able to create an assignment of the
1967 temporary to the lhs_expr. gfc_trans_create_temp_array replaces
1968 the tree in the descriptor with the one for the temporary
1970 lss_real
= gfc_walk_expr (lhs_expr
);
1971 gfc_init_loopinfo (&loop
);
1972 gfc_add_ss_to_loop (&loop
, lss_for_tmparray
);
1973 gfc_add_ss_to_loop (&loop
, lss_real
);
1974 gfc_conv_ss_startstride (&loop
);
1975 gfc_conv_loop_setup (&loop
, &lhs_expr
->where
);
1976 lhs_type
= gfc_typenode_for_spec (&lhs_expr
->ts
);
1977 gfc_trans_create_temp_array (&lhs_se
.pre
, &lhs_se
.post
,
1978 lss_for_tmparray
, lhs_type
, NULL_TREE
,
1981 tmparr_desc
= lss_for_tmparray
->info
->data
.array
.descriptor
;
1982 gfc_start_scalarized_body (&loop
, &body
);
1983 gfc_init_se (&se
, NULL
);
1984 gfc_copy_loopinfo_to_se (&se
, &loop
);
1986 gfc_conv_expr (&se
, lhs_expr
);
1987 gfc_add_block_to_block (&body
, &se
.pre
);
1989 /* Walk over all indexes of the loop. */
1990 for (n
= loop
.dimen
- 1; n
> 0; --n
)
1992 tmp
= loop
.loopvar
[n
];
1993 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
1994 gfc_array_index_type
, tmp
, loop
.from
[n
]);
1995 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
1996 gfc_array_index_type
, tmp
, index
);
1998 stride
= fold_build2_loc (input_location
, MINUS_EXPR
,
1999 gfc_array_index_type
,
2000 loop
.to
[n
- 1], loop
.from
[n
- 1]);
2001 stride
= fold_build2_loc (input_location
, PLUS_EXPR
,
2002 gfc_array_index_type
,
2003 stride
, gfc_index_one_node
);
2005 index
= fold_build2_loc (input_location
, MULT_EXPR
,
2006 gfc_array_index_type
, tmp
, stride
);
2009 index
= fold_build2_loc (input_location
, MINUS_EXPR
,
2010 gfc_array_index_type
,
2011 index
, loop
.from
[0]);
2013 index
= fold_build2_loc (input_location
, PLUS_EXPR
,
2014 gfc_array_index_type
,
2015 loop
.loopvar
[0], index
);
2017 src
= build_fold_indirect_ref (gfc_conv_array_data (tmparr_desc
));
2018 src
= gfc_build_array_ref (src
, index
, NULL
);
2019 /* Now create the assignment of lhs_expr = tmp_array. */
2020 gfc_add_modify (&body
, se
.expr
, src
);
2021 gfc_add_block_to_block (&body
, &se
.post
);
2022 lhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, tmparr_desc
);
2023 gfc_trans_scalarizing_loops (&loop
, &body
);
2024 gfc_add_block_to_block (&loop
.pre
, &loop
.post
);
2025 gfc_add_expr_to_block (&lhs_se
.post
, gfc_finish_block (&loop
.pre
));
2026 gfc_free_ss (lss_for_tmparray
);
2027 gfc_free_ss (lss_real
);
2031 lhs_kind
= build_int_cst (integer_type_node
, lhs_expr
->ts
.kind
);
2033 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
2034 temporary and a loop. */
2035 if (!gfc_is_coindexed (lhs_expr
)
2036 && (!lhs_caf_attr
.codimension
2037 || !(lhs_expr
->rank
> 0
2038 && (lhs_caf_attr
.allocatable
|| lhs_caf_attr
.pointer
))))
2040 bool lhs_may_realloc
= lhs_expr
->rank
> 0 && lhs_caf_attr
.allocatable
;
2041 gcc_assert (gfc_is_coindexed (rhs_expr
));
2042 gfc_init_se (&rhs_se
, NULL
);
2043 if (lhs_expr
->rank
== 0 && lhs_caf_attr
.allocatable
)
2046 gfc_init_se (&scal_se
, NULL
);
2047 scal_se
.want_pointer
= 1;
2048 gfc_conv_expr (&scal_se
, lhs_expr
);
2049 /* Ensure scalar on lhs is allocated. */
2050 gfc_add_block_to_block (&block
, &scal_se
.pre
);
2052 gfc_allocate_using_malloc (&scal_se
.pre
, scal_se
.expr
,
2054 gfc_typenode_for_spec (&lhs_expr
->ts
)),
2056 tmp
= fold_build2 (EQ_EXPR
, logical_type_node
, scal_se
.expr
,
2058 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
2059 tmp
, gfc_finish_block (&scal_se
.pre
),
2060 build_empty_stmt (input_location
));
2061 gfc_add_expr_to_block (&block
, tmp
);
2064 lhs_may_realloc
= lhs_may_realloc
2065 && gfc_full_array_ref_p (lhs_expr
->ref
, NULL
);
2066 gfc_add_block_to_block (&block
, &lhs_se
.pre
);
2067 gfc_conv_intrinsic_caf_get (&rhs_se
, rhs_expr
, lhs_se
.expr
, lhs_kind
,
2068 may_require_tmp
, lhs_may_realloc
,
2070 gfc_add_block_to_block (&block
, &rhs_se
.pre
);
2071 gfc_add_block_to_block (&block
, &rhs_se
.post
);
2072 gfc_add_block_to_block (&block
, &lhs_se
.post
);
2073 return gfc_finish_block (&block
);
2076 gfc_add_block_to_block (&block
, &lhs_se
.pre
);
2078 /* Obtain token, offset and image index for the LHS. */
2079 caf_decl
= gfc_get_tree_for_caf_expr (lhs_expr
);
2080 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
2081 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
2082 image_index
= gfc_caf_get_image_index (&block
, lhs_expr
, caf_decl
);
2084 if (lhs_caf_attr
.alloc_comp
)
2085 gfc_get_caf_token_offset (&lhs_se
, &token
, NULL
, caf_decl
, NULL_TREE
,
2088 gfc_get_caf_token_offset (&lhs_se
, &token
, &offset
, caf_decl
, tmp
,
2093 gfc_init_se (&rhs_se
, NULL
);
2094 if (rhs_expr
->expr_type
== EXPR_FUNCTION
&& rhs_expr
->value
.function
.isym
2095 && rhs_expr
->value
.function
.isym
->id
== GFC_ISYM_CONVERSION
)
2096 rhs_expr
= rhs_expr
->value
.function
.actual
->expr
;
2097 if (rhs_expr
->rank
== 0)
2099 symbol_attribute attr
;
2100 gfc_clear_attr (&attr
);
2101 gfc_conv_expr (&rhs_se
, rhs_expr
);
2102 rhs_se
.expr
= gfc_conv_scalar_to_descriptor (&rhs_se
, rhs_se
.expr
, attr
);
2103 rhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, rhs_se
.expr
);
2105 else if ((rhs_caf_attr
.alloc_comp
|| rhs_caf_attr
.pointer_comp
)
2106 && rhs_caf_attr
.codimension
)
2109 rhs_se
.want_pointer
= 1;
2110 gfc_conv_expr_descriptor (&rhs_se
, rhs_expr
);
2111 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2112 has the wrong type if component references are done. */
2113 tmp2
= gfc_typenode_for_spec (&rhs_expr
->ts
);
2114 tmp
= build_fold_indirect_ref_loc (input_location
, rhs_se
.expr
);
2115 gfc_add_modify (&rhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
2116 gfc_get_dtype_rank_type (
2117 gfc_has_vector_subscript (rhs_expr
)
2118 ? gfc_find_array_ref (rhs_expr
)->dimen
2124 /* If has_vector, pass descriptor for whole array and the
2125 vector bounds separately. */
2126 gfc_array_ref
*ar
, ar2
;
2127 bool has_vector
= false;
2130 if (gfc_is_coindexed (rhs_expr
) && gfc_has_vector_subscript (rhs_expr
))
2133 ar
= gfc_find_array_ref (rhs_expr
);
2135 memset (ar
, '\0', sizeof (*ar
));
2139 rhs_se
.want_pointer
= 1;
2140 gfc_conv_expr_descriptor (&rhs_se
, rhs_expr
);
2141 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
2142 has the wrong type if component references are done. */
2143 tmp
= build_fold_indirect_ref_loc (input_location
, rhs_se
.expr
);
2144 tmp2
= gfc_typenode_for_spec (&rhs_expr
->ts
);
2145 gfc_add_modify (&rhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
2146 gfc_get_dtype_rank_type (has_vector
? ar2
.dimen
2151 rhs_vec
= conv_caf_vector_subscript (&block
, rhs_se
.expr
, &ar2
);
2156 gfc_add_block_to_block (&block
, &rhs_se
.pre
);
2158 rhs_kind
= build_int_cst (integer_type_node
, rhs_expr
->ts
.kind
);
2160 tmp_stat
= gfc_find_stat_co (lhs_expr
);
2165 gfc_init_se (&stat_se
, NULL
);
2166 gfc_conv_expr_reference (&stat_se
, tmp_stat
);
2167 dst_stat
= stat_se
.expr
;
2168 gfc_add_block_to_block (&block
, &stat_se
.pre
);
2169 gfc_add_block_to_block (&block
, &stat_se
.post
);
2172 tmp_team
= gfc_find_team_co (lhs_expr
);
2177 gfc_init_se (&team_se
, NULL
);
2178 gfc_conv_expr_reference (&team_se
, tmp_team
);
2179 dst_team
= team_se
.expr
;
2180 gfc_add_block_to_block (&block
, &team_se
.pre
);
2181 gfc_add_block_to_block (&block
, &team_se
.post
);
2184 if (!gfc_is_coindexed (rhs_expr
))
2186 if (lhs_caf_attr
.alloc_comp
|| lhs_caf_attr
.pointer_comp
)
2188 tree reference
, dst_realloc
;
2189 reference
= conv_expr_ref_to_caf_ref (&block
, lhs_expr
);
2190 dst_realloc
= lhs_caf_attr
.allocatable
? boolean_true_node
2191 : boolean_false_node
;
2192 tmp
= build_call_expr_loc (input_location
,
2193 gfor_fndecl_caf_send_by_ref
,
2194 10, token
, image_index
, rhs_se
.expr
,
2195 reference
, lhs_kind
, rhs_kind
,
2196 may_require_tmp
, dst_realloc
, src_stat
,
2197 build_int_cst (integer_type_node
,
2198 lhs_expr
->ts
.type
));
2201 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_send
, 11,
2202 token
, offset
, image_index
, lhs_se
.expr
, vec
,
2203 rhs_se
.expr
, lhs_kind
, rhs_kind
,
2204 may_require_tmp
, src_stat
, dst_team
);
2208 tree rhs_token
, rhs_offset
, rhs_image_index
;
2210 /* It guarantees memory consistency within the same segment. */
2211 tmp
= gfc_build_string_const (strlen ("memory") + 1, "memory");
2212 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
2213 gfc_build_string_const (1, ""), NULL_TREE
, NULL_TREE
,
2214 tree_cons (NULL_TREE
, tmp
, NULL_TREE
), NULL_TREE
);
2215 ASM_VOLATILE_P (tmp
) = 1;
2216 gfc_add_expr_to_block (&block
, tmp
);
2218 caf_decl
= gfc_get_tree_for_caf_expr (rhs_expr
);
2219 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
2220 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
2221 rhs_image_index
= gfc_caf_get_image_index (&block
, rhs_expr
, caf_decl
);
2223 if (rhs_caf_attr
.alloc_comp
|| rhs_caf_attr
.pointer_comp
)
2225 tmp_stat
= gfc_find_stat_co (lhs_expr
);
2230 gfc_init_se (&stat_se
, NULL
);
2231 gfc_conv_expr_reference (&stat_se
, tmp_stat
);
2232 src_stat
= stat_se
.expr
;
2233 gfc_add_block_to_block (&block
, &stat_se
.pre
);
2234 gfc_add_block_to_block (&block
, &stat_se
.post
);
2237 gfc_get_caf_token_offset (&rhs_se
, &rhs_token
, NULL
, caf_decl
,
2239 tree lhs_reference
, rhs_reference
;
2240 lhs_reference
= conv_expr_ref_to_caf_ref (&block
, lhs_expr
);
2241 rhs_reference
= conv_expr_ref_to_caf_ref (&block
, rhs_expr
);
2242 tmp
= build_call_expr_loc (input_location
,
2243 gfor_fndecl_caf_sendget_by_ref
, 13,
2244 token
, image_index
, lhs_reference
,
2245 rhs_token
, rhs_image_index
, rhs_reference
,
2246 lhs_kind
, rhs_kind
, may_require_tmp
,
2248 build_int_cst (integer_type_node
,
2250 build_int_cst (integer_type_node
,
2251 rhs_expr
->ts
.type
));
2255 gfc_get_caf_token_offset (&rhs_se
, &rhs_token
, &rhs_offset
, caf_decl
,
2257 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_sendget
,
2258 14, token
, offset
, image_index
,
2259 lhs_se
.expr
, vec
, rhs_token
, rhs_offset
,
2260 rhs_image_index
, tmp
, rhs_vec
, lhs_kind
,
2261 rhs_kind
, may_require_tmp
, src_stat
);
2264 gfc_add_expr_to_block (&block
, tmp
);
2265 gfc_add_block_to_block (&block
, &lhs_se
.post
);
2266 gfc_add_block_to_block (&block
, &rhs_se
.post
);
2268 /* It guarantees memory consistency within the same segment. */
2269 tmp
= gfc_build_string_const (strlen ("memory") + 1, "memory");
2270 tmp
= build5_loc (input_location
, ASM_EXPR
, void_type_node
,
2271 gfc_build_string_const (1, ""), NULL_TREE
, NULL_TREE
,
2272 tree_cons (NULL_TREE
, tmp
, NULL_TREE
), NULL_TREE
);
2273 ASM_VOLATILE_P (tmp
) = 1;
2274 gfc_add_expr_to_block (&block
, tmp
);
2276 return gfc_finish_block (&block
);
2281 trans_this_image (gfc_se
* se
, gfc_expr
*expr
)
2284 tree type
, desc
, dim_arg
, cond
, tmp
, m
, loop_var
, exit_label
, min_var
,
2285 lbound
, ubound
, extent
, ml
;
2288 gfc_expr
*distance
= expr
->value
.function
.actual
->next
->next
->expr
;
2290 if (expr
->value
.function
.actual
->expr
2291 && !gfc_is_coarray (expr
->value
.function
.actual
->expr
))
2292 distance
= expr
->value
.function
.actual
->expr
;
2294 /* The case -fcoarray=single is handled elsewhere. */
2295 gcc_assert (flag_coarray
!= GFC_FCOARRAY_SINGLE
);
2297 /* Argument-free version: THIS_IMAGE(). */
2298 if (distance
|| expr
->value
.function
.actual
->expr
== NULL
)
2302 gfc_init_se (&argse
, NULL
);
2303 gfc_conv_expr_val (&argse
, distance
);
2304 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2305 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2306 tmp
= fold_convert (integer_type_node
, argse
.expr
);
2309 tmp
= integer_zero_node
;
2310 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_this_image
, 1,
2312 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
),
2317 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
2319 type
= gfc_get_int_type (gfc_default_integer_kind
);
2320 corank
= gfc_get_corank (expr
->value
.function
.actual
->expr
);
2321 rank
= expr
->value
.function
.actual
->expr
->rank
;
2323 /* Obtain the descriptor of the COARRAY. */
2324 gfc_init_se (&argse
, NULL
);
2325 argse
.want_coarray
= 1;
2326 gfc_conv_expr_descriptor (&argse
, expr
->value
.function
.actual
->expr
);
2327 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2328 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2333 /* Create an implicit second parameter from the loop variable. */
2334 gcc_assert (!expr
->value
.function
.actual
->next
->expr
);
2335 gcc_assert (corank
> 0);
2336 gcc_assert (se
->loop
->dimen
== 1);
2337 gcc_assert (se
->ss
->info
->expr
== expr
);
2339 dim_arg
= se
->loop
->loopvar
[0];
2340 dim_arg
= fold_build2_loc (input_location
, PLUS_EXPR
,
2341 gfc_array_index_type
, dim_arg
,
2342 build_int_cst (TREE_TYPE (dim_arg
), 1));
2343 gfc_advance_se_ss_chain (se
);
2347 /* Use the passed DIM= argument. */
2348 gcc_assert (expr
->value
.function
.actual
->next
->expr
);
2349 gfc_init_se (&argse
, NULL
);
2350 gfc_conv_expr_type (&argse
, expr
->value
.function
.actual
->next
->expr
,
2351 gfc_array_index_type
);
2352 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2353 dim_arg
= argse
.expr
;
2355 if (INTEGER_CST_P (dim_arg
))
2357 if (wi::ltu_p (wi::to_wide (dim_arg
), 1)
2358 || wi::gtu_p (wi::to_wide (dim_arg
),
2359 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))))
2360 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2361 "dimension index", expr
->value
.function
.isym
->name
,
2364 else if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
2366 dim_arg
= gfc_evaluate_now (dim_arg
, &se
->pre
);
2367 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
2369 build_int_cst (TREE_TYPE (dim_arg
), 1));
2370 tmp
= gfc_rank_cst
[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))];
2371 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
2373 cond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
2374 logical_type_node
, cond
, tmp
);
2375 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
2380 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
2381 one always has a dim_arg argument.
2383 m = this_image() - 1
2386 sub(1) = m + lcobound(corank)
2390 min_var = min (rank + corank - 2, rank + dim_arg - 1)
2393 extent = gfc_extent(i)
2401 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
2402 : m + lcobound(corank)
2405 /* this_image () - 1. */
2406 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_this_image
, 1,
2408 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, type
,
2409 fold_convert (type
, tmp
), build_int_cst (type
, 1));
2412 /* sub(1) = m + lcobound(corank). */
2413 lbound
= gfc_conv_descriptor_lbound_get (desc
,
2414 build_int_cst (TREE_TYPE (gfc_array_index_type
),
2416 lbound
= fold_convert (type
, lbound
);
2417 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, tmp
, lbound
);
2423 m
= gfc_create_var (type
, NULL
);
2424 ml
= gfc_create_var (type
, NULL
);
2425 loop_var
= gfc_create_var (integer_type_node
, NULL
);
2426 min_var
= gfc_create_var (integer_type_node
, NULL
);
2428 /* m = this_image () - 1. */
2429 gfc_add_modify (&se
->pre
, m
, tmp
);
2431 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
2432 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, integer_type_node
,
2433 fold_convert (integer_type_node
, dim_arg
),
2434 build_int_cst (integer_type_node
, rank
- 1));
2435 tmp
= fold_build2_loc (input_location
, MIN_EXPR
, integer_type_node
,
2436 build_int_cst (integer_type_node
, rank
+ corank
- 2),
2438 gfc_add_modify (&se
->pre
, min_var
, tmp
);
2441 tmp
= build_int_cst (integer_type_node
, rank
);
2442 gfc_add_modify (&se
->pre
, loop_var
, tmp
);
2444 exit_label
= gfc_build_label_decl (NULL_TREE
);
2445 TREE_USED (exit_label
) = 1;
2448 gfc_init_block (&loop
);
2451 gfc_add_modify (&loop
, ml
, m
);
2454 lbound
= gfc_conv_descriptor_lbound_get (desc
, loop_var
);
2455 ubound
= gfc_conv_descriptor_ubound_get (desc
, loop_var
);
2456 extent
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
2457 extent
= fold_convert (type
, extent
);
2460 gfc_add_modify (&loop
, m
,
2461 fold_build2_loc (input_location
, TRUNC_DIV_EXPR
, type
,
2464 /* Exit condition: if (i >= min_var) goto exit_label. */
2465 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, loop_var
,
2467 tmp
= build1_v (GOTO_EXPR
, exit_label
);
2468 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
, tmp
,
2469 build_empty_stmt (input_location
));
2470 gfc_add_expr_to_block (&loop
, tmp
);
2472 /* Increment loop variable: i++. */
2473 gfc_add_modify (&loop
, loop_var
,
2474 fold_build2_loc (input_location
, PLUS_EXPR
, integer_type_node
,
2476 build_int_cst (integer_type_node
, 1)));
2478 /* Making the loop... actually loop! */
2479 tmp
= gfc_finish_block (&loop
);
2480 tmp
= build1_v (LOOP_EXPR
, tmp
);
2481 gfc_add_expr_to_block (&se
->pre
, tmp
);
2483 /* The exit label. */
2484 tmp
= build1_v (LABEL_EXPR
, exit_label
);
2485 gfc_add_expr_to_block (&se
->pre
, tmp
);
2487 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
2488 : m + lcobound(corank) */
2490 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
, dim_arg
,
2491 build_int_cst (TREE_TYPE (dim_arg
), corank
));
2493 lbound
= gfc_conv_descriptor_lbound_get (desc
,
2494 fold_build2_loc (input_location
, PLUS_EXPR
,
2495 gfc_array_index_type
, dim_arg
,
2496 build_int_cst (TREE_TYPE (dim_arg
), rank
-1)));
2497 lbound
= fold_convert (type
, lbound
);
2499 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, type
, ml
,
2500 fold_build2_loc (input_location
, MULT_EXPR
, type
,
2502 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, tmp
, lbound
);
2504 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
, tmp
,
2505 fold_build2_loc (input_location
, PLUS_EXPR
, type
,
2510 /* Convert a call to image_status. */
2513 conv_intrinsic_image_status (gfc_se
*se
, gfc_expr
*expr
)
2515 unsigned int num_args
;
2518 num_args
= gfc_intrinsic_argument_list_length (expr
);
2519 args
= XALLOCAVEC (tree
, num_args
);
2520 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
2521 /* In args[0] the number of the image the status is desired for has to be
2524 if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
2527 arg
= gfc_evaluate_now (args
[0], &se
->pre
);
2528 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
2529 fold_convert (integer_type_node
, arg
),
2531 tmp
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
2532 tmp
, integer_zero_node
,
2533 build_int_cst (integer_type_node
,
2534 GFC_STAT_STOPPED_IMAGE
));
2536 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
2537 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_image_status
, 2,
2538 args
[0], build_int_cst (integer_type_node
, -1));
2546 conv_intrinsic_team_number (gfc_se
*se
, gfc_expr
*expr
)
2548 unsigned int num_args
;
2552 num_args
= gfc_intrinsic_argument_list_length (expr
);
2553 args
= XALLOCAVEC (tree
, num_args
);
2554 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
2557 GFC_FCOARRAY_SINGLE
&& expr
->value
.function
.actual
->expr
)
2561 arg
= gfc_evaluate_now (args
[0], &se
->pre
);
2562 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
2563 fold_convert (integer_type_node
, arg
),
2565 tmp
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
2566 tmp
, integer_zero_node
,
2567 build_int_cst (integer_type_node
,
2568 GFC_STAT_STOPPED_IMAGE
));
2570 else if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
2572 // the value -1 represents that no team has been created yet
2573 tmp
= build_int_cst (integer_type_node
, -1);
2575 else if (flag_coarray
== GFC_FCOARRAY_LIB
&& expr
->value
.function
.actual
->expr
)
2576 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_team_number
, 1,
2577 args
[0], build_int_cst (integer_type_node
, -1));
2578 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
2579 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_team_number
, 1,
2580 integer_zero_node
, build_int_cst (integer_type_node
, -1));
2589 trans_image_index (gfc_se
* se
, gfc_expr
*expr
)
2591 tree num_images
, cond
, coindex
, type
, lbound
, ubound
, desc
, subdesc
,
2593 gfc_se argse
, subse
;
2594 int rank
, corank
, codim
;
2596 type
= gfc_get_int_type (gfc_default_integer_kind
);
2597 corank
= gfc_get_corank (expr
->value
.function
.actual
->expr
);
2598 rank
= expr
->value
.function
.actual
->expr
->rank
;
2600 /* Obtain the descriptor of the COARRAY. */
2601 gfc_init_se (&argse
, NULL
);
2602 argse
.want_coarray
= 1;
2603 gfc_conv_expr_descriptor (&argse
, expr
->value
.function
.actual
->expr
);
2604 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2605 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2608 /* Obtain a handle to the SUB argument. */
2609 gfc_init_se (&subse
, NULL
);
2610 gfc_conv_expr_descriptor (&subse
, expr
->value
.function
.actual
->next
->expr
);
2611 gfc_add_block_to_block (&se
->pre
, &subse
.pre
);
2612 gfc_add_block_to_block (&se
->post
, &subse
.post
);
2613 subdesc
= build_fold_indirect_ref_loc (input_location
,
2614 gfc_conv_descriptor_data_get (subse
.expr
));
2616 /* Fortran 2008 does not require that the values remain in the cobounds,
2617 thus we need explicitly check this - and return 0 if they are exceeded. */
2619 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[rank
+corank
-1]);
2620 tmp
= gfc_build_array_ref (subdesc
, gfc_rank_cst
[corank
-1], NULL
);
2621 invalid_bound
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
2622 fold_convert (gfc_array_index_type
, tmp
),
2625 for (codim
= corank
+ rank
- 2; codim
>= rank
; codim
--)
2627 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[codim
]);
2628 ubound
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[codim
]);
2629 tmp
= gfc_build_array_ref (subdesc
, gfc_rank_cst
[codim
-rank
], NULL
);
2630 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
2631 fold_convert (gfc_array_index_type
, tmp
),
2633 invalid_bound
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
2634 logical_type_node
, invalid_bound
, cond
);
2635 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
2636 fold_convert (gfc_array_index_type
, tmp
),
2638 invalid_bound
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
2639 logical_type_node
, invalid_bound
, cond
);
2642 invalid_bound
= gfc_unlikely (invalid_bound
, PRED_FORTRAN_INVALID_BOUND
);
2644 /* See Fortran 2008, C.10 for the following algorithm. */
2646 /* coindex = sub(corank) - lcobound(n). */
2647 coindex
= fold_convert (gfc_array_index_type
,
2648 gfc_build_array_ref (subdesc
, gfc_rank_cst
[corank
-1],
2650 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[rank
+corank
-1]);
2651 coindex
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
2652 fold_convert (gfc_array_index_type
, coindex
),
2655 for (codim
= corank
+ rank
- 2; codim
>= rank
; codim
--)
2657 tree extent
, ubound
;
2659 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
2660 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[codim
]);
2661 ubound
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[codim
]);
2662 extent
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
2664 /* coindex *= extent. */
2665 coindex
= fold_build2_loc (input_location
, MULT_EXPR
,
2666 gfc_array_index_type
, coindex
, extent
);
2668 /* coindex += sub(codim). */
2669 tmp
= gfc_build_array_ref (subdesc
, gfc_rank_cst
[codim
-rank
], NULL
);
2670 coindex
= fold_build2_loc (input_location
, PLUS_EXPR
,
2671 gfc_array_index_type
, coindex
,
2672 fold_convert (gfc_array_index_type
, tmp
));
2674 /* coindex -= lbound(codim). */
2675 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[codim
]);
2676 coindex
= fold_build2_loc (input_location
, MINUS_EXPR
,
2677 gfc_array_index_type
, coindex
, lbound
);
2680 coindex
= fold_build2_loc (input_location
, PLUS_EXPR
, type
,
2681 fold_convert(type
, coindex
),
2682 build_int_cst (type
, 1));
2684 /* Return 0 if "coindex" exceeds num_images(). */
2686 if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
2687 num_images
= build_int_cst (type
, 1);
2690 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
, 2,
2692 build_int_cst (integer_type_node
, -1));
2693 num_images
= fold_convert (type
, tmp
);
2696 tmp
= gfc_create_var (type
, NULL
);
2697 gfc_add_modify (&se
->pre
, tmp
, coindex
);
2699 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
, tmp
,
2701 cond
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
, logical_type_node
,
2703 fold_convert (logical_type_node
, invalid_bound
));
2704 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
2705 build_int_cst (type
, 0), tmp
);
2709 trans_num_images (gfc_se
* se
, gfc_expr
*expr
)
2711 tree tmp
, distance
, failed
;
2714 if (expr
->value
.function
.actual
->expr
)
2716 gfc_init_se (&argse
, NULL
);
2717 gfc_conv_expr_val (&argse
, expr
->value
.function
.actual
->expr
);
2718 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2719 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2720 distance
= fold_convert (integer_type_node
, argse
.expr
);
2723 distance
= integer_zero_node
;
2725 if (expr
->value
.function
.actual
->next
->expr
)
2727 gfc_init_se (&argse
, NULL
);
2728 gfc_conv_expr_val (&argse
, expr
->value
.function
.actual
->next
->expr
);
2729 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2730 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2731 failed
= fold_convert (integer_type_node
, argse
.expr
);
2734 failed
= build_int_cst (integer_type_node
, -1);
2735 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
, 2,
2737 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
), tmp
);
2742 gfc_conv_intrinsic_rank (gfc_se
*se
, gfc_expr
*expr
)
2746 gfc_init_se (&argse
, NULL
);
2747 argse
.data_not_needed
= 1;
2748 argse
.descriptor_only
= 1;
2750 gfc_conv_expr_descriptor (&argse
, expr
->value
.function
.actual
->expr
);
2751 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2752 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2754 se
->expr
= gfc_conv_descriptor_rank (argse
.expr
);
2755 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
),
2760 /* Evaluate a single upper or lower bound. */
2761 /* TODO: bound intrinsic generates way too much unnecessary code. */
2764 gfc_conv_intrinsic_bound (gfc_se
* se
, gfc_expr
* expr
, int upper
)
2766 gfc_actual_arglist
*arg
;
2767 gfc_actual_arglist
*arg2
;
2772 tree cond
, cond1
, cond3
, cond4
, size
;
2776 gfc_array_spec
* as
;
2777 bool assumed_rank_lb_one
;
2779 arg
= expr
->value
.function
.actual
;
2784 /* Create an implicit second parameter from the loop variable. */
2785 gcc_assert (!arg2
->expr
);
2786 gcc_assert (se
->loop
->dimen
== 1);
2787 gcc_assert (se
->ss
->info
->expr
== expr
);
2788 gfc_advance_se_ss_chain (se
);
2789 bound
= se
->loop
->loopvar
[0];
2790 bound
= fold_build2_loc (input_location
, MINUS_EXPR
,
2791 gfc_array_index_type
, bound
,
2796 /* use the passed argument. */
2797 gcc_assert (arg2
->expr
);
2798 gfc_init_se (&argse
, NULL
);
2799 gfc_conv_expr_type (&argse
, arg2
->expr
, gfc_array_index_type
);
2800 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2802 /* Convert from one based to zero based. */
2803 bound
= fold_build2_loc (input_location
, MINUS_EXPR
,
2804 gfc_array_index_type
, bound
,
2805 gfc_index_one_node
);
2808 /* TODO: don't re-evaluate the descriptor on each iteration. */
2809 /* Get a descriptor for the first parameter. */
2810 gfc_init_se (&argse
, NULL
);
2811 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
2812 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2813 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2817 as
= gfc_get_full_arrayspec_from_expr (arg
->expr
);
2819 if (INTEGER_CST_P (bound
))
2821 if (((!as
|| as
->type
!= AS_ASSUMED_RANK
)
2822 && wi::geu_p (wi::to_wide (bound
),
2823 GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc
))))
2824 || wi::gtu_p (wi::to_wide (bound
), GFC_MAX_DIMENSIONS
))
2825 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2826 "dimension index", upper
? "UBOUND" : "LBOUND",
2830 if (!INTEGER_CST_P (bound
) || (as
&& as
->type
== AS_ASSUMED_RANK
))
2832 if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
2834 bound
= gfc_evaluate_now (bound
, &se
->pre
);
2835 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
2836 bound
, build_int_cst (TREE_TYPE (bound
), 0));
2837 if (as
&& as
->type
== AS_ASSUMED_RANK
)
2838 tmp
= gfc_conv_descriptor_rank (desc
);
2840 tmp
= gfc_rank_cst
[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc
))];
2841 tmp
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
2842 bound
, fold_convert(TREE_TYPE (bound
), tmp
));
2843 cond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
2844 logical_type_node
, cond
, tmp
);
2845 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
2850 /* Take care of the lbound shift for assumed-rank arrays, which are
2851 nonallocatable and nonpointers. Those has a lbound of 1. */
2852 assumed_rank_lb_one
= as
&& as
->type
== AS_ASSUMED_RANK
2853 && ((arg
->expr
->ts
.type
!= BT_CLASS
2854 && !arg
->expr
->symtree
->n
.sym
->attr
.allocatable
2855 && !arg
->expr
->symtree
->n
.sym
->attr
.pointer
)
2856 || (arg
->expr
->ts
.type
== BT_CLASS
2857 && !CLASS_DATA (arg
->expr
)->attr
.allocatable
2858 && !CLASS_DATA (arg
->expr
)->attr
.class_pointer
));
2860 ubound
= gfc_conv_descriptor_ubound_get (desc
, bound
);
2861 lbound
= gfc_conv_descriptor_lbound_get (desc
, bound
);
2863 /* 13.14.53: Result value for LBOUND
2865 Case (i): For an array section or for an array expression other than a
2866 whole array or array structure component, LBOUND(ARRAY, DIM)
2867 has the value 1. For a whole array or array structure
2868 component, LBOUND(ARRAY, DIM) has the value:
2869 (a) equal to the lower bound for subscript DIM of ARRAY if
2870 dimension DIM of ARRAY does not have extent zero
2871 or if ARRAY is an assumed-size array of rank DIM,
2874 13.14.113: Result value for UBOUND
2876 Case (i): For an array section or for an array expression other than a
2877 whole array or array structure component, UBOUND(ARRAY, DIM)
2878 has the value equal to the number of elements in the given
2879 dimension; otherwise, it has a value equal to the upper bound
2880 for subscript DIM of ARRAY if dimension DIM of ARRAY does
2881 not have size zero and has value zero if dimension DIM has
2884 if (!upper
&& assumed_rank_lb_one
)
2885 se
->expr
= gfc_index_one_node
;
2888 tree stride
= gfc_conv_descriptor_stride_get (desc
, bound
);
2890 cond1
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
2892 cond3
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
2893 stride
, gfc_index_zero_node
);
2894 cond3
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
2895 logical_type_node
, cond3
, cond1
);
2896 cond4
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
2897 stride
, gfc_index_zero_node
);
2902 cond
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
2903 logical_type_node
, cond3
, cond4
);
2904 cond5
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
2905 gfc_index_one_node
, lbound
);
2906 cond5
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
2907 logical_type_node
, cond4
, cond5
);
2909 cond
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
2910 logical_type_node
, cond
, cond5
);
2912 if (assumed_rank_lb_one
)
2914 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
2915 gfc_array_index_type
, ubound
, lbound
);
2916 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
2917 gfc_array_index_type
, tmp
, gfc_index_one_node
);
2922 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
2923 gfc_array_index_type
, cond
,
2924 tmp
, gfc_index_zero_node
);
2928 if (as
->type
== AS_ASSUMED_SIZE
)
2929 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
2930 bound
, build_int_cst (TREE_TYPE (bound
),
2931 arg
->expr
->rank
- 1));
2933 cond
= logical_false_node
;
2935 cond1
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
2936 logical_type_node
, cond3
, cond4
);
2937 cond
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
2938 logical_type_node
, cond
, cond1
);
2940 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
2941 gfc_array_index_type
, cond
,
2942 lbound
, gfc_index_one_node
);
2949 size
= fold_build2_loc (input_location
, MINUS_EXPR
,
2950 gfc_array_index_type
, ubound
, lbound
);
2951 se
->expr
= fold_build2_loc (input_location
, PLUS_EXPR
,
2952 gfc_array_index_type
, size
,
2953 gfc_index_one_node
);
2954 se
->expr
= fold_build2_loc (input_location
, MAX_EXPR
,
2955 gfc_array_index_type
, se
->expr
,
2956 gfc_index_zero_node
);
2959 se
->expr
= gfc_index_one_node
;
2962 type
= gfc_typenode_for_spec (&expr
->ts
);
2963 se
->expr
= convert (type
, se
->expr
);
2968 conv_intrinsic_cobound (gfc_se
* se
, gfc_expr
* expr
)
2970 gfc_actual_arglist
*arg
;
2971 gfc_actual_arglist
*arg2
;
2973 tree bound
, resbound
, resbound2
, desc
, cond
, tmp
;
2977 gcc_assert (expr
->value
.function
.isym
->id
== GFC_ISYM_LCOBOUND
2978 || expr
->value
.function
.isym
->id
== GFC_ISYM_UCOBOUND
2979 || expr
->value
.function
.isym
->id
== GFC_ISYM_THIS_IMAGE
);
2981 arg
= expr
->value
.function
.actual
;
2984 gcc_assert (arg
->expr
->expr_type
== EXPR_VARIABLE
);
2985 corank
= gfc_get_corank (arg
->expr
);
2987 gfc_init_se (&argse
, NULL
);
2988 argse
.want_coarray
= 1;
2990 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
2991 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2992 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2997 /* Create an implicit second parameter from the loop variable. */
2998 gcc_assert (!arg2
->expr
);
2999 gcc_assert (corank
> 0);
3000 gcc_assert (se
->loop
->dimen
== 1);
3001 gcc_assert (se
->ss
->info
->expr
== expr
);
3003 bound
= se
->loop
->loopvar
[0];
3004 bound
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
3005 bound
, gfc_rank_cst
[arg
->expr
->rank
]);
3006 gfc_advance_se_ss_chain (se
);
3010 /* use the passed argument. */
3011 gcc_assert (arg2
->expr
);
3012 gfc_init_se (&argse
, NULL
);
3013 gfc_conv_expr_type (&argse
, arg2
->expr
, gfc_array_index_type
);
3014 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3017 if (INTEGER_CST_P (bound
))
3019 if (wi::ltu_p (wi::to_wide (bound
), 1)
3020 || wi::gtu_p (wi::to_wide (bound
),
3021 GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))))
3022 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
3023 "dimension index", expr
->value
.function
.isym
->name
,
3026 else if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
3028 bound
= gfc_evaluate_now (bound
, &se
->pre
);
3029 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3030 bound
, build_int_cst (TREE_TYPE (bound
), 1));
3031 tmp
= gfc_rank_cst
[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))];
3032 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3034 cond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
3035 logical_type_node
, cond
, tmp
);
3036 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
3041 /* Subtract 1 to get to zero based and add dimensions. */
3042 switch (arg
->expr
->rank
)
3045 bound
= fold_build2_loc (input_location
, MINUS_EXPR
,
3046 gfc_array_index_type
, bound
,
3047 gfc_index_one_node
);
3051 bound
= fold_build2_loc (input_location
, PLUS_EXPR
,
3052 gfc_array_index_type
, bound
,
3053 gfc_rank_cst
[arg
->expr
->rank
- 1]);
3057 resbound
= gfc_conv_descriptor_lbound_get (desc
, bound
);
3059 /* Handle UCOBOUND with special handling of the last codimension. */
3060 if (expr
->value
.function
.isym
->id
== GFC_ISYM_UCOBOUND
)
3062 /* Last codimension: For -fcoarray=single just return
3063 the lcobound - otherwise add
3064 ceiling (real (num_images ()) / real (size)) - 1
3065 = (num_images () + size - 1) / size - 1
3066 = (num_images - 1) / size(),
3067 where size is the product of the extent of all but the last
3070 if (flag_coarray
!= GFC_FCOARRAY_SINGLE
&& corank
> 1)
3074 cosize
= gfc_conv_descriptor_cosize (desc
, arg
->expr
->rank
, corank
);
3075 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
,
3076 2, integer_zero_node
,
3077 build_int_cst (integer_type_node
, -1));
3078 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
3079 gfc_array_index_type
,
3080 fold_convert (gfc_array_index_type
, tmp
),
3081 build_int_cst (gfc_array_index_type
, 1));
3082 tmp
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
3083 gfc_array_index_type
, tmp
,
3084 fold_convert (gfc_array_index_type
, cosize
));
3085 resbound
= fold_build2_loc (input_location
, PLUS_EXPR
,
3086 gfc_array_index_type
, resbound
, tmp
);
3088 else if (flag_coarray
!= GFC_FCOARRAY_SINGLE
)
3090 /* ubound = lbound + num_images() - 1. */
3091 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
,
3092 2, integer_zero_node
,
3093 build_int_cst (integer_type_node
, -1));
3094 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
3095 gfc_array_index_type
,
3096 fold_convert (gfc_array_index_type
, tmp
),
3097 build_int_cst (gfc_array_index_type
, 1));
3098 resbound
= fold_build2_loc (input_location
, PLUS_EXPR
,
3099 gfc_array_index_type
, resbound
, tmp
);
3104 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
3106 build_int_cst (TREE_TYPE (bound
),
3107 arg
->expr
->rank
+ corank
- 1));
3109 resbound2
= gfc_conv_descriptor_ubound_get (desc
, bound
);
3110 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
3111 gfc_array_index_type
, cond
,
3112 resbound
, resbound2
);
3115 se
->expr
= resbound
;
3118 se
->expr
= resbound
;
3120 type
= gfc_typenode_for_spec (&expr
->ts
);
3121 se
->expr
= convert (type
, se
->expr
);
3126 conv_intrinsic_stride (gfc_se
* se
, gfc_expr
* expr
)
3128 gfc_actual_arglist
*array_arg
;
3129 gfc_actual_arglist
*dim_arg
;
3133 array_arg
= expr
->value
.function
.actual
;
3134 dim_arg
= array_arg
->next
;
3136 gcc_assert (array_arg
->expr
->expr_type
== EXPR_VARIABLE
);
3138 gfc_init_se (&argse
, NULL
);
3139 gfc_conv_expr_descriptor (&argse
, array_arg
->expr
);
3140 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3141 gfc_add_block_to_block (&se
->post
, &argse
.post
);
3144 gcc_assert (dim_arg
->expr
);
3145 gfc_init_se (&argse
, NULL
);
3146 gfc_conv_expr_type (&argse
, dim_arg
->expr
, gfc_array_index_type
);
3147 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
3148 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
3149 argse
.expr
, gfc_index_one_node
);
3150 se
->expr
= gfc_conv_descriptor_stride_get (desc
, tmp
);
3154 gfc_conv_intrinsic_abs (gfc_se
* se
, gfc_expr
* expr
)
3158 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
3160 switch (expr
->value
.function
.actual
->expr
->ts
.type
)
3164 se
->expr
= fold_build1_loc (input_location
, ABS_EXPR
, TREE_TYPE (arg
),
3169 cabs
= gfc_builtin_decl_for_float_kind (BUILT_IN_CABS
, expr
->ts
.kind
);
3170 se
->expr
= build_call_expr_loc (input_location
, cabs
, 1, arg
);
3179 /* Create a complex value from one or two real components. */
3182 gfc_conv_intrinsic_cmplx (gfc_se
* se
, gfc_expr
* expr
, int both
)
3188 unsigned int num_args
;
3190 num_args
= gfc_intrinsic_argument_list_length (expr
);
3191 args
= XALLOCAVEC (tree
, num_args
);
3193 type
= gfc_typenode_for_spec (&expr
->ts
);
3194 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
3195 real
= convert (TREE_TYPE (type
), args
[0]);
3197 imag
= convert (TREE_TYPE (type
), args
[1]);
3198 else if (TREE_CODE (TREE_TYPE (args
[0])) == COMPLEX_TYPE
)
3200 imag
= fold_build1_loc (input_location
, IMAGPART_EXPR
,
3201 TREE_TYPE (TREE_TYPE (args
[0])), args
[0]);
3202 imag
= convert (TREE_TYPE (type
), imag
);
3205 imag
= build_real_from_int_cst (TREE_TYPE (type
), integer_zero_node
);
3207 se
->expr
= fold_build2_loc (input_location
, COMPLEX_EXPR
, type
, real
, imag
);
3211 /* Remainder function MOD(A, P) = A - INT(A / P) * P
3212 MODULO(A, P) = A - FLOOR (A / P) * P
3214 The obvious algorithms above are numerically instable for large
3215 arguments, hence these intrinsics are instead implemented via calls
3216 to the fmod family of functions. It is the responsibility of the
3217 user to ensure that the second argument is non-zero. */
3220 gfc_conv_intrinsic_mod (gfc_se
* se
, gfc_expr
* expr
, int modulo
)
3230 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
3232 switch (expr
->ts
.type
)
3235 /* Integer case is easy, we've got a builtin op. */
3236 type
= TREE_TYPE (args
[0]);
3239 se
->expr
= fold_build2_loc (input_location
, FLOOR_MOD_EXPR
, type
,
3242 se
->expr
= fold_build2_loc (input_location
, TRUNC_MOD_EXPR
, type
,
3248 /* Check if we have a builtin fmod. */
3249 fmod
= gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD
, expr
->ts
.kind
);
3251 /* The builtin should always be available. */
3252 gcc_assert (fmod
!= NULL_TREE
);
3254 tmp
= build_addr (fmod
);
3255 se
->expr
= build_call_array_loc (input_location
,
3256 TREE_TYPE (TREE_TYPE (fmod
)),
3261 type
= TREE_TYPE (args
[0]);
3263 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
3264 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
3267 modulo = arg - floor (arg/arg2) * arg2
3269 In order to calculate the result accurately, we use the fmod
3270 function as follows.
3272 res = fmod (arg, arg2);
3275 if ((arg < 0) xor (arg2 < 0))
3279 res = copysign (0., arg2);
3281 => As two nested ternary exprs:
3283 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
3284 : copysign (0., arg2);
3288 zero
= gfc_build_const (type
, integer_zero_node
);
3289 tmp
= gfc_evaluate_now (se
->expr
, &se
->pre
);
3290 if (!flag_signed_zeros
)
3292 test
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3294 test2
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3296 test2
= fold_build2_loc (input_location
, TRUTH_XOR_EXPR
,
3297 logical_type_node
, test
, test2
);
3298 test
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
3300 test
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
3301 logical_type_node
, test
, test2
);
3302 test
= gfc_evaluate_now (test
, &se
->pre
);
3303 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, test
,
3304 fold_build2_loc (input_location
,
3306 type
, tmp
, args
[1]),
3311 tree expr1
, copysign
, cscall
;
3312 copysign
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
,
3314 test
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3316 test2
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
,
3318 test2
= fold_build2_loc (input_location
, TRUTH_XOR_EXPR
,
3319 logical_type_node
, test
, test2
);
3320 expr1
= fold_build3_loc (input_location
, COND_EXPR
, type
, test2
,
3321 fold_build2_loc (input_location
,
3323 type
, tmp
, args
[1]),
3325 test
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
3327 cscall
= build_call_expr_loc (input_location
, copysign
, 2, zero
,
3329 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, test
,
3339 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
3340 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
3341 where the right shifts are logical (i.e. 0's are shifted in).
3342 Because SHIFT_EXPR's want shifts strictly smaller than the integral
3343 type width, we have to special-case both S == 0 and S == BITSIZE(J):
3345 DSHIFTL(I,J,BITSIZE) = J
3347 DSHIFTR(I,J,BITSIZE) = I. */
3350 gfc_conv_intrinsic_dshift (gfc_se
* se
, gfc_expr
* expr
, bool dshiftl
)
3352 tree type
, utype
, stype
, arg1
, arg2
, shift
, res
, left
, right
;
3353 tree args
[3], cond
, tmp
;
3356 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
3358 gcc_assert (TREE_TYPE (args
[0]) == TREE_TYPE (args
[1]));
3359 type
= TREE_TYPE (args
[0]);
3360 bitsize
= TYPE_PRECISION (type
);
3361 utype
= unsigned_type_for (type
);
3362 stype
= TREE_TYPE (args
[2]);
3364 arg1
= gfc_evaluate_now (args
[0], &se
->pre
);
3365 arg2
= gfc_evaluate_now (args
[1], &se
->pre
);
3366 shift
= gfc_evaluate_now (args
[2], &se
->pre
);
3368 /* The generic case. */
3369 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, stype
,
3370 build_int_cst (stype
, bitsize
), shift
);
3371 left
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
3372 arg1
, dshiftl
? shift
: tmp
);
3374 right
= fold_build2_loc (input_location
, RSHIFT_EXPR
, utype
,
3375 fold_convert (utype
, arg2
), dshiftl
? tmp
: shift
);
3376 right
= fold_convert (type
, right
);
3378 res
= fold_build2_loc (input_location
, BIT_IOR_EXPR
, type
, left
, right
);
3380 /* Special cases. */
3381 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, shift
,
3382 build_int_cst (stype
, 0));
3383 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
3384 dshiftl
? arg1
: arg2
, res
);
3386 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, shift
,
3387 build_int_cst (stype
, bitsize
));
3388 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
3389 dshiftl
? arg2
: arg1
, res
);
3395 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
3398 gfc_conv_intrinsic_dim (gfc_se
* se
, gfc_expr
* expr
)
3406 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
3407 type
= TREE_TYPE (args
[0]);
3409 val
= fold_build2_loc (input_location
, MINUS_EXPR
, type
, args
[0], args
[1]);
3410 val
= gfc_evaluate_now (val
, &se
->pre
);
3412 zero
= gfc_build_const (type
, integer_zero_node
);
3413 tmp
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
, val
, zero
);
3414 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, zero
, val
);
3418 /* SIGN(A, B) is absolute value of A times sign of B.
3419 The real value versions use library functions to ensure the correct
3420 handling of negative zero. Integer case implemented as:
3421 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
3425 gfc_conv_intrinsic_sign (gfc_se
* se
, gfc_expr
* expr
)
3431 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
3432 if (expr
->ts
.type
== BT_REAL
)
3436 tmp
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
, expr
->ts
.kind
);
3437 abs
= gfc_builtin_decl_for_float_kind (BUILT_IN_FABS
, expr
->ts
.kind
);
3439 /* We explicitly have to ignore the minus sign. We do so by using
3440 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
3442 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args
[1]))))
3445 zero
= build_real_from_int_cst (TREE_TYPE (args
[1]), integer_zero_node
);
3446 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
3448 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
3449 TREE_TYPE (args
[0]), cond
,
3450 build_call_expr_loc (input_location
, abs
, 1,
3452 build_call_expr_loc (input_location
, tmp
, 2,
3456 se
->expr
= build_call_expr_loc (input_location
, tmp
, 2,
3461 /* Having excluded floating point types, we know we are now dealing
3462 with signed integer types. */
3463 type
= TREE_TYPE (args
[0]);
3465 /* Args[0] is used multiple times below. */
3466 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
3468 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
3469 the signs of A and B are the same, and of all ones if they differ. */
3470 tmp
= fold_build2_loc (input_location
, BIT_XOR_EXPR
, type
, args
[0], args
[1]);
3471 tmp
= fold_build2_loc (input_location
, RSHIFT_EXPR
, type
, tmp
,
3472 build_int_cst (type
, TYPE_PRECISION (type
) - 1));
3473 tmp
= gfc_evaluate_now (tmp
, &se
->pre
);
3475 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
3476 is all ones (i.e. -1). */
3477 se
->expr
= fold_build2_loc (input_location
, BIT_XOR_EXPR
, type
,
3478 fold_build2_loc (input_location
, PLUS_EXPR
,
3479 type
, args
[0], tmp
), tmp
);
3483 /* Test for the presence of an optional argument. */
3486 gfc_conv_intrinsic_present (gfc_se
* se
, gfc_expr
* expr
)
3490 arg
= expr
->value
.function
.actual
->expr
;
3491 gcc_assert (arg
->expr_type
== EXPR_VARIABLE
);
3492 se
->expr
= gfc_conv_expr_present (arg
->symtree
->n
.sym
);
3493 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
3497 /* Calculate the double precision product of two single precision values. */
3500 gfc_conv_intrinsic_dprod (gfc_se
* se
, gfc_expr
* expr
)
3505 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
3507 /* Convert the args to double precision before multiplying. */
3508 type
= gfc_typenode_for_spec (&expr
->ts
);
3509 args
[0] = convert (type
, args
[0]);
3510 args
[1] = convert (type
, args
[1]);
3511 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, type
, args
[0],
3516 /* Return a length one character string containing an ascii character. */
3519 gfc_conv_intrinsic_char (gfc_se
* se
, gfc_expr
* expr
)
3524 unsigned int num_args
;
3526 num_args
= gfc_intrinsic_argument_list_length (expr
);
3527 gfc_conv_intrinsic_function_args (se
, expr
, arg
, num_args
);
3529 type
= gfc_get_char_type (expr
->ts
.kind
);
3530 var
= gfc_create_var (type
, "char");
3532 arg
[0] = fold_build1_loc (input_location
, NOP_EXPR
, type
, arg
[0]);
3533 gfc_add_modify (&se
->pre
, var
, arg
[0]);
3534 se
->expr
= gfc_build_addr_expr (build_pointer_type (type
), var
);
3535 se
->string_length
= build_int_cst (gfc_charlen_type_node
, 1);
3540 gfc_conv_intrinsic_ctime (gfc_se
* se
, gfc_expr
* expr
)
3548 unsigned int num_args
;
3550 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
3551 args
= XALLOCAVEC (tree
, num_args
);
3553 var
= gfc_create_var (pchar_type_node
, "pstr");
3554 len
= gfc_create_var (gfc_charlen_type_node
, "len");
3556 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
3557 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
3558 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
3560 fndecl
= build_addr (gfor_fndecl_ctime
);
3561 tmp
= build_call_array_loc (input_location
,
3562 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime
)),
3563 fndecl
, num_args
, args
);
3564 gfc_add_expr_to_block (&se
->pre
, tmp
);
3566 /* Free the temporary afterwards, if necessary. */
3567 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3568 len
, build_int_cst (TREE_TYPE (len
), 0));
3569 tmp
= gfc_call_free (var
);
3570 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
3571 gfc_add_expr_to_block (&se
->post
, tmp
);
3574 se
->string_length
= len
;
3579 gfc_conv_intrinsic_fdate (gfc_se
* se
, gfc_expr
* expr
)
3587 unsigned int num_args
;
3589 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
3590 args
= XALLOCAVEC (tree
, num_args
);
3592 var
= gfc_create_var (pchar_type_node
, "pstr");
3593 len
= gfc_create_var (gfc_charlen_type_node
, "len");
3595 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
3596 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
3597 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
3599 fndecl
= build_addr (gfor_fndecl_fdate
);
3600 tmp
= build_call_array_loc (input_location
,
3601 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate
)),
3602 fndecl
, num_args
, args
);
3603 gfc_add_expr_to_block (&se
->pre
, tmp
);
3605 /* Free the temporary afterwards, if necessary. */
3606 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3607 len
, build_int_cst (TREE_TYPE (len
), 0));
3608 tmp
= gfc_call_free (var
);
3609 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
3610 gfc_add_expr_to_block (&se
->post
, tmp
);
3613 se
->string_length
= len
;
3617 /* Generate a direct call to free() for the FREE subroutine. */
3620 conv_intrinsic_free (gfc_code
*code
)
3626 gfc_init_se (&argse
, NULL
);
3627 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
3628 arg
= fold_convert (ptr_type_node
, argse
.expr
);
3630 gfc_init_block (&block
);
3631 call
= build_call_expr_loc (input_location
,
3632 builtin_decl_explicit (BUILT_IN_FREE
), 1, arg
);
3633 gfc_add_expr_to_block (&block
, call
);
3634 return gfc_finish_block (&block
);
3638 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3642 conv_intrinsic_system_clock (gfc_code
*code
)
3645 gfc_se count_se
, count_rate_se
, count_max_se
;
3646 tree arg1
= NULL_TREE
, arg2
= NULL_TREE
, arg3
= NULL_TREE
;
3650 gfc_expr
*count
= code
->ext
.actual
->expr
;
3651 gfc_expr
*count_rate
= code
->ext
.actual
->next
->expr
;
3652 gfc_expr
*count_max
= code
->ext
.actual
->next
->next
->expr
;
3654 /* Evaluate our arguments. */
3657 gfc_init_se (&count_se
, NULL
);
3658 gfc_conv_expr (&count_se
, count
);
3663 gfc_init_se (&count_rate_se
, NULL
);
3664 gfc_conv_expr (&count_rate_se
, count_rate
);
3669 gfc_init_se (&count_max_se
, NULL
);
3670 gfc_conv_expr (&count_max_se
, count_max
);
3673 /* Find the smallest kind found of the arguments. */
3675 least
= (count
&& count
->ts
.kind
< least
) ? count
->ts
.kind
: least
;
3676 least
= (count_rate
&& count_rate
->ts
.kind
< least
) ? count_rate
->ts
.kind
3678 least
= (count_max
&& count_max
->ts
.kind
< least
) ? count_max
->ts
.kind
3681 /* Prepare temporary variables. */
3686 arg1
= gfc_create_var (gfc_get_int_type (8), "count");
3687 else if (least
== 4)
3688 arg1
= gfc_create_var (gfc_get_int_type (4), "count");
3689 else if (count
->ts
.kind
== 1)
3690 arg1
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[0].pedantic_min_int
,
3693 arg1
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[1].pedantic_min_int
,
3700 arg2
= gfc_create_var (gfc_get_int_type (8), "count_rate");
3701 else if (least
== 4)
3702 arg2
= gfc_create_var (gfc_get_int_type (4), "count_rate");
3704 arg2
= integer_zero_node
;
3710 arg3
= gfc_create_var (gfc_get_int_type (8), "count_max");
3711 else if (least
== 4)
3712 arg3
= gfc_create_var (gfc_get_int_type (4), "count_max");
3714 arg3
= integer_zero_node
;
3717 /* Make the function call. */
3718 gfc_init_block (&block
);
3724 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
3725 : null_pointer_node
;
3726 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
3727 : null_pointer_node
;
3728 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
3729 : null_pointer_node
;
3734 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
3735 : null_pointer_node
;
3736 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
3737 : null_pointer_node
;
3738 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
3739 : null_pointer_node
;
3746 tmp
= build_call_expr_loc (input_location
,
3747 gfor_fndecl_system_clock4
, 3,
3748 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
3749 : null_pointer_node
,
3750 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
3751 : null_pointer_node
,
3752 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
3753 : null_pointer_node
);
3754 gfc_add_expr_to_block (&block
, tmp
);
3756 /* Handle kind>=8, 10, or 16 arguments */
3759 tmp
= build_call_expr_loc (input_location
,
3760 gfor_fndecl_system_clock8
, 3,
3761 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
3762 : null_pointer_node
,
3763 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
3764 : null_pointer_node
,
3765 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
3766 : null_pointer_node
);
3767 gfc_add_expr_to_block (&block
, tmp
);
3771 /* And store values back if needed. */
3772 if (arg1
&& arg1
!= count_se
.expr
)
3773 gfc_add_modify (&block
, count_se
.expr
,
3774 fold_convert (TREE_TYPE (count_se
.expr
), arg1
));
3775 if (arg2
&& arg2
!= count_rate_se
.expr
)
3776 gfc_add_modify (&block
, count_rate_se
.expr
,
3777 fold_convert (TREE_TYPE (count_rate_se
.expr
), arg2
));
3778 if (arg3
&& arg3
!= count_max_se
.expr
)
3779 gfc_add_modify (&block
, count_max_se
.expr
,
3780 fold_convert (TREE_TYPE (count_max_se
.expr
), arg3
));
3782 return gfc_finish_block (&block
);
3786 /* Return a character string containing the tty name. */
3789 gfc_conv_intrinsic_ttynam (gfc_se
* se
, gfc_expr
* expr
)
3797 unsigned int num_args
;
3799 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
3800 args
= XALLOCAVEC (tree
, num_args
);
3802 var
= gfc_create_var (pchar_type_node
, "pstr");
3803 len
= gfc_create_var (gfc_charlen_type_node
, "len");
3805 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
3806 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
3807 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
3809 fndecl
= build_addr (gfor_fndecl_ttynam
);
3810 tmp
= build_call_array_loc (input_location
,
3811 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam
)),
3812 fndecl
, num_args
, args
);
3813 gfc_add_expr_to_block (&se
->pre
, tmp
);
3815 /* Free the temporary afterwards, if necessary. */
3816 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3817 len
, build_int_cst (TREE_TYPE (len
), 0));
3818 tmp
= gfc_call_free (var
);
3819 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
3820 gfc_add_expr_to_block (&se
->post
, tmp
);
3823 se
->string_length
= len
;
3827 /* Get the minimum/maximum value of all the parameters.
3828 minmax (a1, a2, a3, ...)
3831 if (a2 .op. mvar || isnan (mvar))
3833 if (a3 .op. mvar || isnan (mvar))
3840 /* TODO: Mismatching types can occur when specific names are used.
3841 These should be handled during resolution. */
3843 gfc_conv_intrinsic_minmax (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
3851 gfc_actual_arglist
*argexpr
;
3852 unsigned int i
, nargs
;
3854 nargs
= gfc_intrinsic_argument_list_length (expr
);
3855 args
= XALLOCAVEC (tree
, nargs
);
3857 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
3858 type
= gfc_typenode_for_spec (&expr
->ts
);
3860 argexpr
= expr
->value
.function
.actual
;
3861 if (TREE_TYPE (args
[0]) != type
)
3862 args
[0] = convert (type
, args
[0]);
3863 /* Only evaluate the argument once. */
3864 if (!VAR_P (args
[0]) && !TREE_CONSTANT (args
[0]))
3865 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
3867 mvar
= gfc_create_var (type
, "M");
3868 gfc_add_modify (&se
->pre
, mvar
, args
[0]);
3869 for (i
= 1, argexpr
= argexpr
->next
; i
< nargs
; i
++)
3875 /* Handle absent optional arguments by ignoring the comparison. */
3876 if (argexpr
->expr
->expr_type
== EXPR_VARIABLE
3877 && argexpr
->expr
->symtree
->n
.sym
->attr
.optional
3878 && TREE_CODE (val
) == INDIRECT_REF
)
3879 cond
= fold_build2_loc (input_location
,
3880 NE_EXPR
, logical_type_node
,
3881 TREE_OPERAND (val
, 0),
3882 build_int_cst (TREE_TYPE (TREE_OPERAND (val
, 0)), 0));
3887 /* Only evaluate the argument once. */
3888 if (!VAR_P (val
) && !TREE_CONSTANT (val
))
3889 val
= gfc_evaluate_now (val
, &se
->pre
);
3892 thencase
= build2_v (MODIFY_EXPR
, mvar
, convert (type
, val
));
3894 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
,
3895 convert (type
, val
), mvar
);
3897 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
3898 __builtin_isnan might be made dependent on that module being loaded,
3899 to help performance of programs that don't rely on IEEE semantics. */
3900 if (FLOAT_TYPE_P (TREE_TYPE (mvar
)))
3902 isnan
= build_call_expr_loc (input_location
,
3903 builtin_decl_explicit (BUILT_IN_ISNAN
),
3905 tmp
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
3906 logical_type_node
, tmp
,
3907 fold_convert (logical_type_node
, isnan
));
3909 tmp
= build3_v (COND_EXPR
, tmp
, thencase
,
3910 build_empty_stmt (input_location
));
3912 if (cond
!= NULL_TREE
)
3913 tmp
= build3_v (COND_EXPR
, cond
, tmp
,
3914 build_empty_stmt (input_location
));
3916 gfc_add_expr_to_block (&se
->pre
, tmp
);
3917 argexpr
= argexpr
->next
;
3923 /* Generate library calls for MIN and MAX intrinsics for character
3926 gfc_conv_intrinsic_minmax_char (gfc_se
* se
, gfc_expr
* expr
, int op
)
3929 tree var
, len
, fndecl
, tmp
, cond
, function
;
3932 nargs
= gfc_intrinsic_argument_list_length (expr
);
3933 args
= XALLOCAVEC (tree
, nargs
+ 4);
3934 gfc_conv_intrinsic_function_args (se
, expr
, &args
[4], nargs
);
3936 /* Create the result variables. */
3937 len
= gfc_create_var (gfc_charlen_type_node
, "len");
3938 args
[0] = gfc_build_addr_expr (NULL_TREE
, len
);
3939 var
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
), "pstr");
3940 args
[1] = gfc_build_addr_expr (ppvoid_type_node
, var
);
3941 args
[2] = build_int_cst (integer_type_node
, op
);
3942 args
[3] = build_int_cst (integer_type_node
, nargs
/ 2);
3944 if (expr
->ts
.kind
== 1)
3945 function
= gfor_fndecl_string_minmax
;
3946 else if (expr
->ts
.kind
== 4)
3947 function
= gfor_fndecl_string_minmax_char4
;
3951 /* Make the function call. */
3952 fndecl
= build_addr (function
);
3953 tmp
= build_call_array_loc (input_location
,
3954 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
3956 gfc_add_expr_to_block (&se
->pre
, tmp
);
3958 /* Free the temporary afterwards, if necessary. */
3959 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3960 len
, build_int_cst (TREE_TYPE (len
), 0));
3961 tmp
= gfc_call_free (var
);
3962 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
3963 gfc_add_expr_to_block (&se
->post
, tmp
);
3966 se
->string_length
= len
;
3970 /* Create a symbol node for this intrinsic. The symbol from the frontend
3971 has the generic name. */
3974 gfc_get_symbol_for_expr (gfc_expr
* expr
, bool ignore_optional
)
3978 /* TODO: Add symbols for intrinsic function to the global namespace. */
3979 gcc_assert (strlen (expr
->value
.function
.name
) <= GFC_MAX_SYMBOL_LEN
- 5);
3980 sym
= gfc_new_symbol (expr
->value
.function
.name
, NULL
);
3983 sym
->attr
.external
= 1;
3984 sym
->attr
.function
= 1;
3985 sym
->attr
.always_explicit
= 1;
3986 sym
->attr
.proc
= PROC_INTRINSIC
;
3987 sym
->attr
.flavor
= FL_PROCEDURE
;
3991 sym
->attr
.dimension
= 1;
3992 sym
->as
= gfc_get_array_spec ();
3993 sym
->as
->type
= AS_ASSUMED_SHAPE
;
3994 sym
->as
->rank
= expr
->rank
;
3997 gfc_copy_formal_args_intr (sym
, expr
->value
.function
.isym
,
3998 ignore_optional
? expr
->value
.function
.actual
4004 /* Generate a call to an external intrinsic function. */
4006 gfc_conv_intrinsic_funcall (gfc_se
* se
, gfc_expr
* expr
)
4009 vec
<tree
, va_gc
> *append_args
;
4011 gcc_assert (!se
->ss
|| se
->ss
->info
->expr
== expr
);
4014 gcc_assert (expr
->rank
> 0);
4016 gcc_assert (expr
->rank
== 0);
4018 sym
= gfc_get_symbol_for_expr (expr
, se
->ignore_optional
);
4020 /* Calls to libgfortran_matmul need to be appended special arguments,
4021 to be able to call the BLAS ?gemm functions if required and possible. */
4023 if (expr
->value
.function
.isym
->id
== GFC_ISYM_MATMUL
4024 && sym
->ts
.type
!= BT_LOGICAL
)
4026 tree cint
= gfc_get_int_type (gfc_c_int_kind
);
4028 if (flag_external_blas
4029 && (sym
->ts
.type
== BT_REAL
|| sym
->ts
.type
== BT_COMPLEX
)
4030 && (sym
->ts
.kind
== 4 || sym
->ts
.kind
== 8))
4034 if (sym
->ts
.type
== BT_REAL
)
4036 if (sym
->ts
.kind
== 4)
4037 gemm_fndecl
= gfor_fndecl_sgemm
;
4039 gemm_fndecl
= gfor_fndecl_dgemm
;
4043 if (sym
->ts
.kind
== 4)
4044 gemm_fndecl
= gfor_fndecl_cgemm
;
4046 gemm_fndecl
= gfor_fndecl_zgemm
;
4049 vec_alloc (append_args
, 3);
4050 append_args
->quick_push (build_int_cst (cint
, 1));
4051 append_args
->quick_push (build_int_cst (cint
,
4052 flag_blas_matmul_limit
));
4053 append_args
->quick_push (gfc_build_addr_expr (NULL_TREE
,
4058 vec_alloc (append_args
, 3);
4059 append_args
->quick_push (build_int_cst (cint
, 0));
4060 append_args
->quick_push (build_int_cst (cint
, 0));
4061 append_args
->quick_push (null_pointer_node
);
4065 gfc_conv_procedure_call (se
, sym
, expr
->value
.function
.actual
, expr
,
4067 gfc_free_symbol (sym
);
4070 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4090 gfc_conv_intrinsic_anyall (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
4099 gfc_actual_arglist
*actual
;
4106 gfc_conv_intrinsic_funcall (se
, expr
);
4110 actual
= expr
->value
.function
.actual
;
4111 type
= gfc_typenode_for_spec (&expr
->ts
);
4112 /* Initialize the result. */
4113 resvar
= gfc_create_var (type
, "test");
4115 tmp
= convert (type
, boolean_true_node
);
4117 tmp
= convert (type
, boolean_false_node
);
4118 gfc_add_modify (&se
->pre
, resvar
, tmp
);
4120 /* Walk the arguments. */
4121 arrayss
= gfc_walk_expr (actual
->expr
);
4122 gcc_assert (arrayss
!= gfc_ss_terminator
);
4124 /* Initialize the scalarizer. */
4125 gfc_init_loopinfo (&loop
);
4126 exit_label
= gfc_build_label_decl (NULL_TREE
);
4127 TREE_USED (exit_label
) = 1;
4128 gfc_add_ss_to_loop (&loop
, arrayss
);
4130 /* Initialize the loop. */
4131 gfc_conv_ss_startstride (&loop
);
4132 gfc_conv_loop_setup (&loop
, &expr
->where
);
4134 gfc_mark_ss_chain_used (arrayss
, 1);
4135 /* Generate the loop body. */
4136 gfc_start_scalarized_body (&loop
, &body
);
4138 /* If the condition matches then set the return value. */
4139 gfc_start_block (&block
);
4141 tmp
= convert (type
, boolean_false_node
);
4143 tmp
= convert (type
, boolean_true_node
);
4144 gfc_add_modify (&block
, resvar
, tmp
);
4146 /* And break out of the loop. */
4147 tmp
= build1_v (GOTO_EXPR
, exit_label
);
4148 gfc_add_expr_to_block (&block
, tmp
);
4150 found
= gfc_finish_block (&block
);
4152 /* Check this element. */
4153 gfc_init_se (&arrayse
, NULL
);
4154 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
4155 arrayse
.ss
= arrayss
;
4156 gfc_conv_expr_val (&arrayse
, actual
->expr
);
4158 gfc_add_block_to_block (&body
, &arrayse
.pre
);
4159 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
, arrayse
.expr
,
4160 build_int_cst (TREE_TYPE (arrayse
.expr
), 0));
4161 tmp
= build3_v (COND_EXPR
, tmp
, found
, build_empty_stmt (input_location
));
4162 gfc_add_expr_to_block (&body
, tmp
);
4163 gfc_add_block_to_block (&body
, &arrayse
.post
);
4165 gfc_trans_scalarizing_loops (&loop
, &body
);
4167 /* Add the exit label. */
4168 tmp
= build1_v (LABEL_EXPR
, exit_label
);
4169 gfc_add_expr_to_block (&loop
.pre
, tmp
);
4171 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
4172 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
4173 gfc_cleanup_loop (&loop
);
4178 /* COUNT(A) = Number of true elements in A. */
4180 gfc_conv_intrinsic_count (gfc_se
* se
, gfc_expr
* expr
)
4187 gfc_actual_arglist
*actual
;
4193 gfc_conv_intrinsic_funcall (se
, expr
);
4197 actual
= expr
->value
.function
.actual
;
4199 type
= gfc_typenode_for_spec (&expr
->ts
);
4200 /* Initialize the result. */
4201 resvar
= gfc_create_var (type
, "count");
4202 gfc_add_modify (&se
->pre
, resvar
, build_int_cst (type
, 0));
4204 /* Walk the arguments. */
4205 arrayss
= gfc_walk_expr (actual
->expr
);
4206 gcc_assert (arrayss
!= gfc_ss_terminator
);
4208 /* Initialize the scalarizer. */
4209 gfc_init_loopinfo (&loop
);
4210 gfc_add_ss_to_loop (&loop
, arrayss
);
4212 /* Initialize the loop. */
4213 gfc_conv_ss_startstride (&loop
);
4214 gfc_conv_loop_setup (&loop
, &expr
->where
);
4216 gfc_mark_ss_chain_used (arrayss
, 1);
4217 /* Generate the loop body. */
4218 gfc_start_scalarized_body (&loop
, &body
);
4220 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (resvar
),
4221 resvar
, build_int_cst (TREE_TYPE (resvar
), 1));
4222 tmp
= build2_v (MODIFY_EXPR
, resvar
, tmp
);
4224 gfc_init_se (&arrayse
, NULL
);
4225 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
4226 arrayse
.ss
= arrayss
;
4227 gfc_conv_expr_val (&arrayse
, actual
->expr
);
4228 tmp
= build3_v (COND_EXPR
, arrayse
.expr
, tmp
,
4229 build_empty_stmt (input_location
));
4231 gfc_add_block_to_block (&body
, &arrayse
.pre
);
4232 gfc_add_expr_to_block (&body
, tmp
);
4233 gfc_add_block_to_block (&body
, &arrayse
.post
);
4235 gfc_trans_scalarizing_loops (&loop
, &body
);
4237 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
4238 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
4239 gfc_cleanup_loop (&loop
);
4245 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4246 struct and return the corresponding loopinfo. */
4248 static gfc_loopinfo
*
4249 enter_nested_loop (gfc_se
*se
)
4251 se
->ss
= se
->ss
->nested_ss
;
4252 gcc_assert (se
->ss
== se
->ss
->loop
->ss
);
4254 return se
->ss
->loop
;
4258 /* Inline implementation of the sum and product intrinsics. */
4260 gfc_conv_intrinsic_arith (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
,
4264 tree scale
= NULL_TREE
;
4269 gfc_loopinfo loop
, *ploop
;
4270 gfc_actual_arglist
*arg_array
, *arg_mask
;
4271 gfc_ss
*arrayss
= NULL
;
4272 gfc_ss
*maskss
= NULL
;
4276 gfc_expr
*arrayexpr
;
4281 gcc_assert (gfc_inline_intrinsic_function_p (expr
));
4287 type
= gfc_typenode_for_spec (&expr
->ts
);
4288 /* Initialize the result. */
4289 resvar
= gfc_create_var (type
, "val");
4294 scale
= gfc_create_var (type
, "scale");
4295 gfc_add_modify (&se
->pre
, scale
,
4296 gfc_build_const (type
, integer_one_node
));
4297 tmp
= gfc_build_const (type
, integer_zero_node
);
4299 else if (op
== PLUS_EXPR
|| op
== BIT_IOR_EXPR
|| op
== BIT_XOR_EXPR
)
4300 tmp
= gfc_build_const (type
, integer_zero_node
);
4301 else if (op
== NE_EXPR
)
4303 tmp
= convert (type
, boolean_false_node
);
4304 else if (op
== BIT_AND_EXPR
)
4305 tmp
= gfc_build_const (type
, fold_build1_loc (input_location
, NEGATE_EXPR
,
4306 type
, integer_one_node
));
4308 tmp
= gfc_build_const (type
, integer_one_node
);
4310 gfc_add_modify (&se
->pre
, resvar
, tmp
);
4312 arg_array
= expr
->value
.function
.actual
;
4314 arrayexpr
= arg_array
->expr
;
4316 if (op
== NE_EXPR
|| norm2
)
4317 /* PARITY and NORM2. */
4321 arg_mask
= arg_array
->next
->next
;
4322 gcc_assert (arg_mask
!= NULL
);
4323 maskexpr
= arg_mask
->expr
;
4326 if (expr
->rank
== 0)
4328 /* Walk the arguments. */
4329 arrayss
= gfc_walk_expr (arrayexpr
);
4330 gcc_assert (arrayss
!= gfc_ss_terminator
);
4332 if (maskexpr
&& maskexpr
->rank
> 0)
4334 maskss
= gfc_walk_expr (maskexpr
);
4335 gcc_assert (maskss
!= gfc_ss_terminator
);
4340 /* Initialize the scalarizer. */
4341 gfc_init_loopinfo (&loop
);
4342 gfc_add_ss_to_loop (&loop
, arrayss
);
4343 if (maskexpr
&& maskexpr
->rank
> 0)
4344 gfc_add_ss_to_loop (&loop
, maskss
);
4346 /* Initialize the loop. */
4347 gfc_conv_ss_startstride (&loop
);
4348 gfc_conv_loop_setup (&loop
, &expr
->where
);
4350 gfc_mark_ss_chain_used (arrayss
, 1);
4351 if (maskexpr
&& maskexpr
->rank
> 0)
4352 gfc_mark_ss_chain_used (maskss
, 1);
4357 /* All the work has been done in the parent loops. */
4358 ploop
= enter_nested_loop (se
);
4362 /* Generate the loop body. */
4363 gfc_start_scalarized_body (ploop
, &body
);
4365 /* If we have a mask, only add this element if the mask is set. */
4366 if (maskexpr
&& maskexpr
->rank
> 0)
4368 gfc_init_se (&maskse
, parent_se
);
4369 gfc_copy_loopinfo_to_se (&maskse
, ploop
);
4370 if (expr
->rank
== 0)
4372 gfc_conv_expr_val (&maskse
, maskexpr
);
4373 gfc_add_block_to_block (&body
, &maskse
.pre
);
4375 gfc_start_block (&block
);
4378 gfc_init_block (&block
);
4380 /* Do the actual summation/product. */
4381 gfc_init_se (&arrayse
, parent_se
);
4382 gfc_copy_loopinfo_to_se (&arrayse
, ploop
);
4383 if (expr
->rank
== 0)
4384 arrayse
.ss
= arrayss
;
4385 gfc_conv_expr_val (&arrayse
, arrayexpr
);
4386 gfc_add_block_to_block (&block
, &arrayse
.pre
);
4390 /* if (x (i) != 0.0)
4396 result = 1.0 + result * val * val;
4402 result += val * val;
4405 tree res1
, res2
, cond
, absX
, val
;
4406 stmtblock_t ifblock1
, ifblock2
, ifblock3
;
4408 gfc_init_block (&ifblock1
);
4410 absX
= gfc_create_var (type
, "absX");
4411 gfc_add_modify (&ifblock1
, absX
,
4412 fold_build1_loc (input_location
, ABS_EXPR
, type
,
4414 val
= gfc_create_var (type
, "val");
4415 gfc_add_expr_to_block (&ifblock1
, val
);
4417 gfc_init_block (&ifblock2
);
4418 gfc_add_modify (&ifblock2
, val
,
4419 fold_build2_loc (input_location
, RDIV_EXPR
, type
, scale
,
4421 res1
= fold_build2_loc (input_location
, MULT_EXPR
, type
, val
, val
);
4422 res1
= fold_build2_loc (input_location
, MULT_EXPR
, type
, resvar
, res1
);
4423 res1
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, res1
,
4424 gfc_build_const (type
, integer_one_node
));
4425 gfc_add_modify (&ifblock2
, resvar
, res1
);
4426 gfc_add_modify (&ifblock2
, scale
, absX
);
4427 res1
= gfc_finish_block (&ifblock2
);
4429 gfc_init_block (&ifblock3
);
4430 gfc_add_modify (&ifblock3
, val
,
4431 fold_build2_loc (input_location
, RDIV_EXPR
, type
, absX
,
4433 res2
= fold_build2_loc (input_location
, MULT_EXPR
, type
, val
, val
);
4434 res2
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, resvar
, res2
);
4435 gfc_add_modify (&ifblock3
, resvar
, res2
);
4436 res2
= gfc_finish_block (&ifblock3
);
4438 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
4440 tmp
= build3_v (COND_EXPR
, cond
, res1
, res2
);
4441 gfc_add_expr_to_block (&ifblock1
, tmp
);
4442 tmp
= gfc_finish_block (&ifblock1
);
4444 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
4446 gfc_build_const (type
, integer_zero_node
));
4448 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
4449 gfc_add_expr_to_block (&block
, tmp
);
4453 tmp
= fold_build2_loc (input_location
, op
, type
, resvar
, arrayse
.expr
);
4454 gfc_add_modify (&block
, resvar
, tmp
);
4457 gfc_add_block_to_block (&block
, &arrayse
.post
);
4459 if (maskexpr
&& maskexpr
->rank
> 0)
4461 /* We enclose the above in if (mask) {...} . */
4463 tmp
= gfc_finish_block (&block
);
4464 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
4465 build_empty_stmt (input_location
));
4468 tmp
= gfc_finish_block (&block
);
4469 gfc_add_expr_to_block (&body
, tmp
);
4471 gfc_trans_scalarizing_loops (ploop
, &body
);
4473 /* For a scalar mask, enclose the loop in an if statement. */
4474 if (maskexpr
&& maskexpr
->rank
== 0)
4476 gfc_init_block (&block
);
4477 gfc_add_block_to_block (&block
, &ploop
->pre
);
4478 gfc_add_block_to_block (&block
, &ploop
->post
);
4479 tmp
= gfc_finish_block (&block
);
4483 tmp
= build3_v (COND_EXPR
, se
->ss
->info
->data
.scalar
.value
, tmp
,
4484 build_empty_stmt (input_location
));
4485 gfc_advance_se_ss_chain (se
);
4489 gcc_assert (expr
->rank
== 0);
4490 gfc_init_se (&maskse
, NULL
);
4491 gfc_conv_expr_val (&maskse
, maskexpr
);
4492 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
4493 build_empty_stmt (input_location
));
4496 gfc_add_expr_to_block (&block
, tmp
);
4497 gfc_add_block_to_block (&se
->pre
, &block
);
4498 gcc_assert (se
->post
.head
== NULL
);
4502 gfc_add_block_to_block (&se
->pre
, &ploop
->pre
);
4503 gfc_add_block_to_block (&se
->pre
, &ploop
->post
);
4506 if (expr
->rank
== 0)
4507 gfc_cleanup_loop (ploop
);
4511 /* result = scale * sqrt(result). */
4513 sqrt
= gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT
, expr
->ts
.kind
);
4514 resvar
= build_call_expr_loc (input_location
,
4516 resvar
= fold_build2_loc (input_location
, MULT_EXPR
, type
, scale
, resvar
);
4523 /* Inline implementation of the dot_product intrinsic. This function
4524 is based on gfc_conv_intrinsic_arith (the previous function). */
4526 gfc_conv_intrinsic_dot_product (gfc_se
* se
, gfc_expr
* expr
)
4534 gfc_actual_arglist
*actual
;
4535 gfc_ss
*arrayss1
, *arrayss2
;
4536 gfc_se arrayse1
, arrayse2
;
4537 gfc_expr
*arrayexpr1
, *arrayexpr2
;
4539 type
= gfc_typenode_for_spec (&expr
->ts
);
4541 /* Initialize the result. */
4542 resvar
= gfc_create_var (type
, "val");
4543 if (expr
->ts
.type
== BT_LOGICAL
)
4544 tmp
= build_int_cst (type
, 0);
4546 tmp
= gfc_build_const (type
, integer_zero_node
);
4548 gfc_add_modify (&se
->pre
, resvar
, tmp
);
4550 /* Walk argument #1. */
4551 actual
= expr
->value
.function
.actual
;
4552 arrayexpr1
= actual
->expr
;
4553 arrayss1
= gfc_walk_expr (arrayexpr1
);
4554 gcc_assert (arrayss1
!= gfc_ss_terminator
);
4556 /* Walk argument #2. */
4557 actual
= actual
->next
;
4558 arrayexpr2
= actual
->expr
;
4559 arrayss2
= gfc_walk_expr (arrayexpr2
);
4560 gcc_assert (arrayss2
!= gfc_ss_terminator
);
4562 /* Initialize the scalarizer. */
4563 gfc_init_loopinfo (&loop
);
4564 gfc_add_ss_to_loop (&loop
, arrayss1
);
4565 gfc_add_ss_to_loop (&loop
, arrayss2
);
4567 /* Initialize the loop. */
4568 gfc_conv_ss_startstride (&loop
);
4569 gfc_conv_loop_setup (&loop
, &expr
->where
);
4571 gfc_mark_ss_chain_used (arrayss1
, 1);
4572 gfc_mark_ss_chain_used (arrayss2
, 1);
4574 /* Generate the loop body. */
4575 gfc_start_scalarized_body (&loop
, &body
);
4576 gfc_init_block (&block
);
4578 /* Make the tree expression for [conjg(]array1[)]. */
4579 gfc_init_se (&arrayse1
, NULL
);
4580 gfc_copy_loopinfo_to_se (&arrayse1
, &loop
);
4581 arrayse1
.ss
= arrayss1
;
4582 gfc_conv_expr_val (&arrayse1
, arrayexpr1
);
4583 if (expr
->ts
.type
== BT_COMPLEX
)
4584 arrayse1
.expr
= fold_build1_loc (input_location
, CONJ_EXPR
, type
,
4586 gfc_add_block_to_block (&block
, &arrayse1
.pre
);
4588 /* Make the tree expression for array2. */
4589 gfc_init_se (&arrayse2
, NULL
);
4590 gfc_copy_loopinfo_to_se (&arrayse2
, &loop
);
4591 arrayse2
.ss
= arrayss2
;
4592 gfc_conv_expr_val (&arrayse2
, arrayexpr2
);
4593 gfc_add_block_to_block (&block
, &arrayse2
.pre
);
4595 /* Do the actual product and sum. */
4596 if (expr
->ts
.type
== BT_LOGICAL
)
4598 tmp
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
, type
,
4599 arrayse1
.expr
, arrayse2
.expr
);
4600 tmp
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
, type
, resvar
, tmp
);
4604 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, type
, arrayse1
.expr
,
4606 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, resvar
, tmp
);
4608 gfc_add_modify (&block
, resvar
, tmp
);
4610 /* Finish up the loop block and the loop. */
4611 tmp
= gfc_finish_block (&block
);
4612 gfc_add_expr_to_block (&body
, tmp
);
4614 gfc_trans_scalarizing_loops (&loop
, &body
);
4615 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
4616 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
4617 gfc_cleanup_loop (&loop
);
4623 /* Emit code for minloc or maxloc intrinsic. There are many different cases
4624 we need to handle. For performance reasons we sometimes create two
4625 loops instead of one, where the second one is much simpler.
4626 Examples for minloc intrinsic:
4627 1) Result is an array, a call is generated
4628 2) Array mask is used and NaNs need to be supported:
4634 if (pos == 0) pos = S + (1 - from);
4635 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4642 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4646 3) NaNs need to be supported, but it is known at compile time or cheaply
4647 at runtime whether array is nonempty or not:
4652 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4655 if (from <= to) pos = 1;
4659 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4663 4) NaNs aren't supported, array mask is used:
4664 limit = infinities_supported ? Infinity : huge (limit);
4668 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4674 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4678 5) Same without array mask:
4679 limit = infinities_supported ? Infinity : huge (limit);
4680 pos = (from <= to) ? 1 : 0;
4683 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4686 For 3) and 5), if mask is scalar, this all goes into a conditional,
4687 setting pos = 0; in the else branch. */
4690 gfc_conv_intrinsic_minmaxloc (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
4694 stmtblock_t ifblock
;
4695 stmtblock_t elseblock
;
4706 gfc_actual_arglist
*actual
;
4711 gfc_expr
*arrayexpr
;
4716 actual
= expr
->value
.function
.actual
;
4718 /* The last argument, BACK, is passed by value. Ensure that
4719 by setting its name to %VAL. */
4720 for (gfc_actual_arglist
*a
= actual
; a
; a
= a
->next
)
4722 if (a
->next
== NULL
)
4728 gfc_conv_intrinsic_funcall (se
, expr
);
4732 arrayexpr
= actual
->expr
;
4734 /* Special case for character maxloc. Remove unneeded actual
4735 arguments, then call a library function. */
4737 if (arrayexpr
->ts
.type
== BT_CHARACTER
)
4739 gfc_actual_arglist
*a
, *b
;
4744 if (b
->expr
== NULL
|| strcmp (b
->name
, "dim") == 0)
4748 gfc_free_actual_arglist (b
);
4753 gfc_conv_intrinsic_funcall (se
, expr
);
4757 /* Initialize the result. */
4758 pos
= gfc_create_var (gfc_array_index_type
, "pos");
4759 offset
= gfc_create_var (gfc_array_index_type
, "offset");
4760 type
= gfc_typenode_for_spec (&expr
->ts
);
4762 /* Walk the arguments. */
4763 arrayss
= gfc_walk_expr (arrayexpr
);
4764 gcc_assert (arrayss
!= gfc_ss_terminator
);
4766 actual
= actual
->next
->next
;
4767 gcc_assert (actual
);
4768 maskexpr
= actual
->expr
;
4770 if (maskexpr
&& maskexpr
->rank
!= 0)
4772 maskss
= gfc_walk_expr (maskexpr
);
4773 gcc_assert (maskss
!= gfc_ss_terminator
);
4778 if (gfc_array_size (arrayexpr
, &asize
))
4780 nonempty
= gfc_conv_mpz_to_tree (asize
, gfc_index_integer_kind
);
4782 nonempty
= fold_build2_loc (input_location
, GT_EXPR
,
4783 logical_type_node
, nonempty
,
4784 gfc_index_zero_node
);
4789 limit
= gfc_create_var (gfc_typenode_for_spec (&arrayexpr
->ts
), "limit");
4790 switch (arrayexpr
->ts
.type
)
4793 tmp
= gfc_build_inf_or_huge (TREE_TYPE (limit
), arrayexpr
->ts
.kind
);
4797 n
= gfc_validate_kind (arrayexpr
->ts
.type
, arrayexpr
->ts
.kind
, false);
4798 tmp
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
,
4799 arrayexpr
->ts
.kind
);
4806 /* We start with the most negative possible value for MAXLOC, and the most
4807 positive possible value for MINLOC. The most negative possible value is
4808 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
4809 possible value is HUGE in both cases. */
4811 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (tmp
), tmp
);
4812 if (op
== GT_EXPR
&& arrayexpr
->ts
.type
== BT_INTEGER
)
4813 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (tmp
), tmp
,
4814 build_int_cst (TREE_TYPE (tmp
), 1));
4816 gfc_add_modify (&se
->pre
, limit
, tmp
);
4818 /* Initialize the scalarizer. */
4819 gfc_init_loopinfo (&loop
);
4820 gfc_add_ss_to_loop (&loop
, arrayss
);
4822 gfc_add_ss_to_loop (&loop
, maskss
);
4824 /* Initialize the loop. */
4825 gfc_conv_ss_startstride (&loop
);
4827 /* The code generated can have more than one loop in sequence (see the
4828 comment at the function header). This doesn't work well with the
4829 scalarizer, which changes arrays' offset when the scalarization loops
4830 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
4831 are currently inlined in the scalar case only (for which loop is of rank
4832 one). As there is no dependency to care about in that case, there is no
4833 temporary, so that we can use the scalarizer temporary code to handle
4834 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
4835 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
4837 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
4838 should eventually go away. We could either create two loops properly,
4839 or find another way to save/restore the array offsets between the two
4840 loops (without conflicting with temporary management), or use a single
4841 loop minmaxloc implementation. See PR 31067. */
4842 loop
.temp_dim
= loop
.dimen
;
4843 gfc_conv_loop_setup (&loop
, &expr
->where
);
4845 gcc_assert (loop
.dimen
== 1);
4846 if (nonempty
== NULL
&& maskss
== NULL
&& loop
.from
[0] && loop
.to
[0])
4847 nonempty
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
,
4848 loop
.from
[0], loop
.to
[0]);
4852 /* Initialize the position to zero, following Fortran 2003. We are free
4853 to do this because Fortran 95 allows the result of an entirely false
4854 mask to be processor dependent. If we know at compile time the array
4855 is non-empty and no MASK is used, we can initialize to 1 to simplify
4857 if (nonempty
!= NULL
&& !HONOR_NANS (DECL_MODE (limit
)))
4858 gfc_add_modify (&loop
.pre
, pos
,
4859 fold_build3_loc (input_location
, COND_EXPR
,
4860 gfc_array_index_type
,
4861 nonempty
, gfc_index_one_node
,
4862 gfc_index_zero_node
));
4865 gfc_add_modify (&loop
.pre
, pos
, gfc_index_zero_node
);
4866 lab1
= gfc_build_label_decl (NULL_TREE
);
4867 TREE_USED (lab1
) = 1;
4868 lab2
= gfc_build_label_decl (NULL_TREE
);
4869 TREE_USED (lab2
) = 1;
4872 /* An offset must be added to the loop
4873 counter to obtain the required position. */
4874 gcc_assert (loop
.from
[0]);
4876 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
4877 gfc_index_one_node
, loop
.from
[0]);
4878 gfc_add_modify (&loop
.pre
, offset
, tmp
);
4880 gfc_mark_ss_chain_used (arrayss
, lab1
? 3 : 1);
4882 gfc_mark_ss_chain_used (maskss
, lab1
? 3 : 1);
4883 /* Generate the loop body. */
4884 gfc_start_scalarized_body (&loop
, &body
);
4886 /* If we have a mask, only check this element if the mask is set. */
4889 gfc_init_se (&maskse
, NULL
);
4890 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
4892 gfc_conv_expr_val (&maskse
, maskexpr
);
4893 gfc_add_block_to_block (&body
, &maskse
.pre
);
4895 gfc_start_block (&block
);
4898 gfc_init_block (&block
);
4900 /* Compare with the current limit. */
4901 gfc_init_se (&arrayse
, NULL
);
4902 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
4903 arrayse
.ss
= arrayss
;
4904 gfc_conv_expr_val (&arrayse
, arrayexpr
);
4905 gfc_add_block_to_block (&block
, &arrayse
.pre
);
4907 /* We do the following if this is a more extreme value. */
4908 gfc_start_block (&ifblock
);
4910 /* Assign the value to the limit... */
4911 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
4913 if (nonempty
== NULL
&& HONOR_NANS (DECL_MODE (limit
)))
4915 stmtblock_t ifblock2
;
4918 gfc_start_block (&ifblock2
);
4919 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
),
4920 loop
.loopvar
[0], offset
);
4921 gfc_add_modify (&ifblock2
, pos
, tmp
);
4922 ifbody2
= gfc_finish_block (&ifblock2
);
4923 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, pos
,
4924 gfc_index_zero_node
);
4925 tmp
= build3_v (COND_EXPR
, cond
, ifbody2
,
4926 build_empty_stmt (input_location
));
4927 gfc_add_expr_to_block (&block
, tmp
);
4930 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
),
4931 loop
.loopvar
[0], offset
);
4932 gfc_add_modify (&ifblock
, pos
, tmp
);
4935 gfc_add_expr_to_block (&ifblock
, build1_v (GOTO_EXPR
, lab1
));
4937 ifbody
= gfc_finish_block (&ifblock
);
4939 if (!lab1
|| HONOR_NANS (DECL_MODE (limit
)))
4942 cond
= fold_build2_loc (input_location
,
4943 op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
4944 logical_type_node
, arrayse
.expr
, limit
);
4946 cond
= fold_build2_loc (input_location
, op
, logical_type_node
,
4947 arrayse
.expr
, limit
);
4949 ifbody
= build3_v (COND_EXPR
, cond
, ifbody
,
4950 build_empty_stmt (input_location
));
4952 gfc_add_expr_to_block (&block
, ifbody
);
4956 /* We enclose the above in if (mask) {...}. */
4957 tmp
= gfc_finish_block (&block
);
4959 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
4960 build_empty_stmt (input_location
));
4963 tmp
= gfc_finish_block (&block
);
4964 gfc_add_expr_to_block (&body
, tmp
);
4968 gfc_trans_scalarized_loop_boundary (&loop
, &body
);
4970 if (HONOR_NANS (DECL_MODE (limit
)))
4972 if (nonempty
!= NULL
)
4974 ifbody
= build2_v (MODIFY_EXPR
, pos
, gfc_index_one_node
);
4975 tmp
= build3_v (COND_EXPR
, nonempty
, ifbody
,
4976 build_empty_stmt (input_location
));
4977 gfc_add_expr_to_block (&loop
.code
[0], tmp
);
4981 gfc_add_expr_to_block (&loop
.code
[0], build1_v (GOTO_EXPR
, lab2
));
4982 gfc_add_expr_to_block (&loop
.code
[0], build1_v (LABEL_EXPR
, lab1
));
4984 /* If we have a mask, only check this element if the mask is set. */
4987 gfc_init_se (&maskse
, NULL
);
4988 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
4990 gfc_conv_expr_val (&maskse
, maskexpr
);
4991 gfc_add_block_to_block (&body
, &maskse
.pre
);
4993 gfc_start_block (&block
);
4996 gfc_init_block (&block
);
4998 /* Compare with the current limit. */
4999 gfc_init_se (&arrayse
, NULL
);
5000 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
5001 arrayse
.ss
= arrayss
;
5002 gfc_conv_expr_val (&arrayse
, arrayexpr
);
5003 gfc_add_block_to_block (&block
, &arrayse
.pre
);
5005 /* We do the following if this is a more extreme value. */
5006 gfc_start_block (&ifblock
);
5008 /* Assign the value to the limit... */
5009 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
5011 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
),
5012 loop
.loopvar
[0], offset
);
5013 gfc_add_modify (&ifblock
, pos
, tmp
);
5015 ifbody
= gfc_finish_block (&ifblock
);
5017 cond
= fold_build2_loc (input_location
, op
, logical_type_node
,
5018 arrayse
.expr
, limit
);
5020 tmp
= build3_v (COND_EXPR
, cond
, ifbody
,
5021 build_empty_stmt (input_location
));
5022 gfc_add_expr_to_block (&block
, tmp
);
5026 /* We enclose the above in if (mask) {...}. */
5027 tmp
= gfc_finish_block (&block
);
5029 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
5030 build_empty_stmt (input_location
));
5033 tmp
= gfc_finish_block (&block
);
5034 gfc_add_expr_to_block (&body
, tmp
);
5035 /* Avoid initializing loopvar[0] again, it should be left where
5036 it finished by the first loop. */
5037 loop
.from
[0] = loop
.loopvar
[0];
5040 gfc_trans_scalarizing_loops (&loop
, &body
);
5043 gfc_add_expr_to_block (&loop
.pre
, build1_v (LABEL_EXPR
, lab2
));
5045 /* For a scalar mask, enclose the loop in an if statement. */
5046 if (maskexpr
&& maskss
== NULL
)
5048 gfc_init_se (&maskse
, NULL
);
5049 gfc_conv_expr_val (&maskse
, maskexpr
);
5050 gfc_init_block (&block
);
5051 gfc_add_block_to_block (&block
, &loop
.pre
);
5052 gfc_add_block_to_block (&block
, &loop
.post
);
5053 tmp
= gfc_finish_block (&block
);
5055 /* For the else part of the scalar mask, just initialize
5056 the pos variable the same way as above. */
5058 gfc_init_block (&elseblock
);
5059 gfc_add_modify (&elseblock
, pos
, gfc_index_zero_node
);
5060 elsetmp
= gfc_finish_block (&elseblock
);
5062 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
, elsetmp
);
5063 gfc_add_expr_to_block (&block
, tmp
);
5064 gfc_add_block_to_block (&se
->pre
, &block
);
5068 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
5069 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
5071 gfc_cleanup_loop (&loop
);
5073 se
->expr
= convert (type
, pos
);
5076 /* Emit code for minval or maxval intrinsic. There are many different cases
5077 we need to handle. For performance reasons we sometimes create two
5078 loops instead of one, where the second one is much simpler.
5079 Examples for minval intrinsic:
5080 1) Result is an array, a call is generated
5081 2) Array mask is used and NaNs need to be supported, rank 1:
5086 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
5089 limit = nonempty ? NaN : huge (limit);
5091 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
5092 3) NaNs need to be supported, but it is known at compile time or cheaply
5093 at runtime whether array is nonempty or not, rank 1:
5096 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
5097 limit = (from <= to) ? NaN : huge (limit);
5099 while (S <= to) { limit = min (a[S], limit); S++; }
5100 4) Array mask is used and NaNs need to be supported, rank > 1:
5109 if (fast) limit = min (a[S1][S2], limit);
5112 if (a[S1][S2] <= limit) {
5123 limit = nonempty ? NaN : huge (limit);
5124 5) NaNs need to be supported, but it is known at compile time or cheaply
5125 at runtime whether array is nonempty or not, rank > 1:
5132 if (fast) limit = min (a[S1][S2], limit);
5134 if (a[S1][S2] <= limit) {
5144 limit = (nonempty_array) ? NaN : huge (limit);
5145 6) NaNs aren't supported, but infinities are. Array mask is used:
5150 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
5153 limit = nonempty ? limit : huge (limit);
5154 7) Same without array mask:
5157 while (S <= to) { limit = min (a[S], limit); S++; }
5158 limit = (from <= to) ? limit : huge (limit);
5159 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
5160 limit = huge (limit);
5162 while (S <= to) { limit = min (a[S], limit); S++); }
5164 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
5165 with array mask instead).
5166 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
5167 setting limit = huge (limit); in the else branch. */
5170 gfc_conv_intrinsic_minmaxval (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
5180 tree huge_cst
= NULL
, nan_cst
= NULL
;
5182 stmtblock_t block
, block2
;
5184 gfc_actual_arglist
*actual
;
5189 gfc_expr
*arrayexpr
;
5195 gfc_conv_intrinsic_funcall (se
, expr
);
5199 actual
= expr
->value
.function
.actual
;
5200 arrayexpr
= actual
->expr
;
5202 if (arrayexpr
->ts
.type
== BT_CHARACTER
)
5204 gfc_actual_arglist
*a2
, *a3
;
5205 a2
= actual
->next
; /* dim */
5206 a3
= a2
->next
; /* mask */
5207 if (a2
->expr
== NULL
|| expr
->rank
== 0)
5209 if (a3
->expr
== NULL
)
5210 actual
->next
= NULL
;
5216 gfc_free_actual_arglist (a2
);
5219 if (a3
->expr
== NULL
)
5222 gfc_free_actual_arglist (a3
);
5224 gfc_conv_intrinsic_funcall (se
, expr
);
5227 type
= gfc_typenode_for_spec (&expr
->ts
);
5228 /* Initialize the result. */
5229 limit
= gfc_create_var (type
, "limit");
5230 n
= gfc_validate_kind (expr
->ts
.type
, expr
->ts
.kind
, false);
5231 switch (expr
->ts
.type
)
5234 huge_cst
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[n
].huge
,
5236 if (HONOR_INFINITIES (DECL_MODE (limit
)))
5238 REAL_VALUE_TYPE real
;
5240 tmp
= build_real (type
, real
);
5244 if (HONOR_NANS (DECL_MODE (limit
)))
5245 nan_cst
= gfc_build_nan (type
, "");
5249 tmp
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
, expr
->ts
.kind
);
5256 /* We start with the most negative possible value for MAXVAL, and the most
5257 positive possible value for MINVAL. The most negative possible value is
5258 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5259 possible value is HUGE in both cases. */
5262 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (tmp
), tmp
);
5264 huge_cst
= fold_build1_loc (input_location
, NEGATE_EXPR
,
5265 TREE_TYPE (huge_cst
), huge_cst
);
5268 if (op
== GT_EXPR
&& expr
->ts
.type
== BT_INTEGER
)
5269 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (tmp
),
5270 tmp
, build_int_cst (type
, 1));
5272 gfc_add_modify (&se
->pre
, limit
, tmp
);
5274 /* Walk the arguments. */
5275 arrayss
= gfc_walk_expr (arrayexpr
);
5276 gcc_assert (arrayss
!= gfc_ss_terminator
);
5278 actual
= actual
->next
->next
;
5279 gcc_assert (actual
);
5280 maskexpr
= actual
->expr
;
5282 if (maskexpr
&& maskexpr
->rank
!= 0)
5284 maskss
= gfc_walk_expr (maskexpr
);
5285 gcc_assert (maskss
!= gfc_ss_terminator
);
5290 if (gfc_array_size (arrayexpr
, &asize
))
5292 nonempty
= gfc_conv_mpz_to_tree (asize
, gfc_index_integer_kind
);
5294 nonempty
= fold_build2_loc (input_location
, GT_EXPR
,
5295 logical_type_node
, nonempty
,
5296 gfc_index_zero_node
);
5301 /* Initialize the scalarizer. */
5302 gfc_init_loopinfo (&loop
);
5303 gfc_add_ss_to_loop (&loop
, arrayss
);
5305 gfc_add_ss_to_loop (&loop
, maskss
);
5307 /* Initialize the loop. */
5308 gfc_conv_ss_startstride (&loop
);
5310 /* The code generated can have more than one loop in sequence (see the
5311 comment at the function header). This doesn't work well with the
5312 scalarizer, which changes arrays' offset when the scalarization loops
5313 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
5314 are currently inlined in the scalar case only. As there is no dependency
5315 to care about in that case, there is no temporary, so that we can use the
5316 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
5317 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
5318 gfc_trans_scalarized_loop_boundary even later to restore offset.
5319 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
5320 should eventually go away. We could either create two loops properly,
5321 or find another way to save/restore the array offsets between the two
5322 loops (without conflicting with temporary management), or use a single
5323 loop minmaxval implementation. See PR 31067. */
5324 loop
.temp_dim
= loop
.dimen
;
5325 gfc_conv_loop_setup (&loop
, &expr
->where
);
5327 if (nonempty
== NULL
&& maskss
== NULL
5328 && loop
.dimen
== 1 && loop
.from
[0] && loop
.to
[0])
5329 nonempty
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
,
5330 loop
.from
[0], loop
.to
[0]);
5331 nonempty_var
= NULL
;
5332 if (nonempty
== NULL
5333 && (HONOR_INFINITIES (DECL_MODE (limit
))
5334 || HONOR_NANS (DECL_MODE (limit
))))
5336 nonempty_var
= gfc_create_var (logical_type_node
, "nonempty");
5337 gfc_add_modify (&se
->pre
, nonempty_var
, logical_false_node
);
5338 nonempty
= nonempty_var
;
5342 if (HONOR_NANS (DECL_MODE (limit
)))
5344 if (loop
.dimen
== 1)
5346 lab
= gfc_build_label_decl (NULL_TREE
);
5347 TREE_USED (lab
) = 1;
5351 fast
= gfc_create_var (logical_type_node
, "fast");
5352 gfc_add_modify (&se
->pre
, fast
, logical_false_node
);
5356 gfc_mark_ss_chain_used (arrayss
, lab
? 3 : 1);
5358 gfc_mark_ss_chain_used (maskss
, lab
? 3 : 1);
5359 /* Generate the loop body. */
5360 gfc_start_scalarized_body (&loop
, &body
);
5362 /* If we have a mask, only add this element if the mask is set. */
5365 gfc_init_se (&maskse
, NULL
);
5366 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
5368 gfc_conv_expr_val (&maskse
, maskexpr
);
5369 gfc_add_block_to_block (&body
, &maskse
.pre
);
5371 gfc_start_block (&block
);
5374 gfc_init_block (&block
);
5376 /* Compare with the current limit. */
5377 gfc_init_se (&arrayse
, NULL
);
5378 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
5379 arrayse
.ss
= arrayss
;
5380 gfc_conv_expr_val (&arrayse
, arrayexpr
);
5381 gfc_add_block_to_block (&block
, &arrayse
.pre
);
5383 gfc_init_block (&block2
);
5386 gfc_add_modify (&block2
, nonempty_var
, logical_true_node
);
5388 if (HONOR_NANS (DECL_MODE (limit
)))
5390 tmp
= fold_build2_loc (input_location
, op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
5391 logical_type_node
, arrayse
.expr
, limit
);
5393 ifbody
= build1_v (GOTO_EXPR
, lab
);
5396 stmtblock_t ifblock
;
5398 gfc_init_block (&ifblock
);
5399 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
5400 gfc_add_modify (&ifblock
, fast
, logical_true_node
);
5401 ifbody
= gfc_finish_block (&ifblock
);
5403 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
5404 build_empty_stmt (input_location
));
5405 gfc_add_expr_to_block (&block2
, tmp
);
5409 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5411 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit
)))
5413 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
,
5414 arrayse
.expr
, limit
);
5415 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
5416 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
5417 build_empty_stmt (input_location
));
5418 gfc_add_expr_to_block (&block2
, tmp
);
5422 tmp
= fold_build2_loc (input_location
,
5423 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
5424 type
, arrayse
.expr
, limit
);
5425 gfc_add_modify (&block2
, limit
, tmp
);
5431 tree elsebody
= gfc_finish_block (&block2
);
5433 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5435 if (HONOR_NANS (DECL_MODE (limit
))
5436 || HONOR_SIGNED_ZEROS (DECL_MODE (limit
)))
5438 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
,
5439 arrayse
.expr
, limit
);
5440 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
5441 ifbody
= build3_v (COND_EXPR
, tmp
, ifbody
,
5442 build_empty_stmt (input_location
));
5446 tmp
= fold_build2_loc (input_location
,
5447 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
5448 type
, arrayse
.expr
, limit
);
5449 ifbody
= build2_v (MODIFY_EXPR
, limit
, tmp
);
5451 tmp
= build3_v (COND_EXPR
, fast
, ifbody
, elsebody
);
5452 gfc_add_expr_to_block (&block
, tmp
);
5455 gfc_add_block_to_block (&block
, &block2
);
5457 gfc_add_block_to_block (&block
, &arrayse
.post
);
5459 tmp
= gfc_finish_block (&block
);
5461 /* We enclose the above in if (mask) {...}. */
5462 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
5463 build_empty_stmt (input_location
));
5464 gfc_add_expr_to_block (&body
, tmp
);
5468 gfc_trans_scalarized_loop_boundary (&loop
, &body
);
5470 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
,
5472 gfc_add_modify (&loop
.code
[0], limit
, tmp
);
5473 gfc_add_expr_to_block (&loop
.code
[0], build1_v (LABEL_EXPR
, lab
));
5475 /* If we have a mask, only add this element if the mask is set. */
5478 gfc_init_se (&maskse
, NULL
);
5479 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
5481 gfc_conv_expr_val (&maskse
, maskexpr
);
5482 gfc_add_block_to_block (&body
, &maskse
.pre
);
5484 gfc_start_block (&block
);
5487 gfc_init_block (&block
);
5489 /* Compare with the current limit. */
5490 gfc_init_se (&arrayse
, NULL
);
5491 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
5492 arrayse
.ss
= arrayss
;
5493 gfc_conv_expr_val (&arrayse
, arrayexpr
);
5494 gfc_add_block_to_block (&block
, &arrayse
.pre
);
5496 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5498 if (HONOR_NANS (DECL_MODE (limit
))
5499 || HONOR_SIGNED_ZEROS (DECL_MODE (limit
)))
5501 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
,
5502 arrayse
.expr
, limit
);
5503 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
5504 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
5505 build_empty_stmt (input_location
));
5506 gfc_add_expr_to_block (&block
, tmp
);
5510 tmp
= fold_build2_loc (input_location
,
5511 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
5512 type
, arrayse
.expr
, limit
);
5513 gfc_add_modify (&block
, limit
, tmp
);
5516 gfc_add_block_to_block (&block
, &arrayse
.post
);
5518 tmp
= gfc_finish_block (&block
);
5520 /* We enclose the above in if (mask) {...}. */
5521 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
5522 build_empty_stmt (input_location
));
5523 gfc_add_expr_to_block (&body
, tmp
);
5524 /* Avoid initializing loopvar[0] again, it should be left where
5525 it finished by the first loop. */
5526 loop
.from
[0] = loop
.loopvar
[0];
5528 gfc_trans_scalarizing_loops (&loop
, &body
);
5532 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
,
5534 ifbody
= build2_v (MODIFY_EXPR
, limit
, tmp
);
5535 tmp
= build3_v (COND_EXPR
, fast
, build_empty_stmt (input_location
),
5537 gfc_add_expr_to_block (&loop
.pre
, tmp
);
5539 else if (HONOR_INFINITIES (DECL_MODE (limit
)) && !lab
)
5541 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
, limit
,
5543 gfc_add_modify (&loop
.pre
, limit
, tmp
);
5546 /* For a scalar mask, enclose the loop in an if statement. */
5547 if (maskexpr
&& maskss
== NULL
)
5551 gfc_init_se (&maskse
, NULL
);
5552 gfc_conv_expr_val (&maskse
, maskexpr
);
5553 gfc_init_block (&block
);
5554 gfc_add_block_to_block (&block
, &loop
.pre
);
5555 gfc_add_block_to_block (&block
, &loop
.post
);
5556 tmp
= gfc_finish_block (&block
);
5558 if (HONOR_INFINITIES (DECL_MODE (limit
)))
5559 else_stmt
= build2_v (MODIFY_EXPR
, limit
, huge_cst
);
5561 else_stmt
= build_empty_stmt (input_location
);
5562 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
, else_stmt
);
5563 gfc_add_expr_to_block (&block
, tmp
);
5564 gfc_add_block_to_block (&se
->pre
, &block
);
5568 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
5569 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
5572 gfc_cleanup_loop (&loop
);
5577 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
5579 gfc_conv_intrinsic_btest (gfc_se
* se
, gfc_expr
* expr
)
5585 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5586 type
= TREE_TYPE (args
[0]);
5588 tmp
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
5589 build_int_cst (type
, 1), args
[1]);
5590 tmp
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[0], tmp
);
5591 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, tmp
,
5592 build_int_cst (type
, 0));
5593 type
= gfc_typenode_for_spec (&expr
->ts
);
5594 se
->expr
= convert (type
, tmp
);
5598 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
5600 gfc_conv_intrinsic_bitcomp (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
5604 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5606 /* Convert both arguments to the unsigned type of the same size. */
5607 args
[0] = fold_convert (unsigned_type_for (TREE_TYPE (args
[0])), args
[0]);
5608 args
[1] = fold_convert (unsigned_type_for (TREE_TYPE (args
[1])), args
[1]);
5610 /* If they have unequal type size, convert to the larger one. */
5611 if (TYPE_PRECISION (TREE_TYPE (args
[0]))
5612 > TYPE_PRECISION (TREE_TYPE (args
[1])))
5613 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
5614 else if (TYPE_PRECISION (TREE_TYPE (args
[1]))
5615 > TYPE_PRECISION (TREE_TYPE (args
[0])))
5616 args
[0] = fold_convert (TREE_TYPE (args
[1]), args
[0]);
5618 /* Now, we compare them. */
5619 se
->expr
= fold_build2_loc (input_location
, op
, logical_type_node
,
5624 /* Generate code to perform the specified operation. */
5626 gfc_conv_intrinsic_bitop (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
5630 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5631 se
->expr
= fold_build2_loc (input_location
, op
, TREE_TYPE (args
[0]),
5637 gfc_conv_intrinsic_not (gfc_se
* se
, gfc_expr
* expr
)
5641 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
5642 se
->expr
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
5643 TREE_TYPE (arg
), arg
);
5646 /* Set or clear a single bit. */
5648 gfc_conv_intrinsic_singlebitop (gfc_se
* se
, gfc_expr
* expr
, int set
)
5655 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5656 type
= TREE_TYPE (args
[0]);
5658 tmp
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
5659 build_int_cst (type
, 1), args
[1]);
5665 tmp
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, type
, tmp
);
5667 se
->expr
= fold_build2_loc (input_location
, op
, type
, args
[0], tmp
);
5670 /* Extract a sequence of bits.
5671 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
5673 gfc_conv_intrinsic_ibits (gfc_se
* se
, gfc_expr
* expr
)
5680 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
5681 type
= TREE_TYPE (args
[0]);
5683 mask
= build_int_cst (type
, -1);
5684 mask
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
, mask
, args
[2]);
5685 mask
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, type
, mask
);
5687 tmp
= fold_build2_loc (input_location
, RSHIFT_EXPR
, type
, args
[0], args
[1]);
5689 se
->expr
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, tmp
, mask
);
5693 gfc_conv_intrinsic_shape (gfc_se
*se
, gfc_expr
*expr
)
5695 gfc_actual_arglist
*s
, *k
;
5698 /* Remove the KIND argument, if present. */
5699 s
= expr
->value
.function
.actual
;
5705 gfc_conv_intrinsic_funcall (se
, expr
);
5709 gfc_conv_intrinsic_shift (gfc_se
* se
, gfc_expr
* expr
, bool right_shift
,
5712 tree args
[2], type
, num_bits
, cond
;
5714 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5716 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
5717 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
5718 type
= TREE_TYPE (args
[0]);
5721 args
[0] = fold_convert (unsigned_type_for (type
), args
[0]);
5723 gcc_assert (right_shift
);
5725 se
->expr
= fold_build2_loc (input_location
,
5726 right_shift
? RSHIFT_EXPR
: LSHIFT_EXPR
,
5727 TREE_TYPE (args
[0]), args
[0], args
[1]);
5730 se
->expr
= fold_convert (type
, se
->expr
);
5732 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5733 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5735 num_bits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
5736 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
5739 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
5740 build_int_cst (type
, 0), se
->expr
);
5743 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
5745 : ((shift >= 0) ? i << shift : i >> -shift)
5746 where all shifts are logical shifts. */
5748 gfc_conv_intrinsic_ishft (gfc_se
* se
, gfc_expr
* expr
)
5760 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5762 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
5763 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
5765 type
= TREE_TYPE (args
[0]);
5766 utype
= unsigned_type_for (type
);
5768 width
= fold_build1_loc (input_location
, ABS_EXPR
, TREE_TYPE (args
[1]),
5771 /* Left shift if positive. */
5772 lshift
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
, args
[0], width
);
5774 /* Right shift if negative.
5775 We convert to an unsigned type because we want a logical shift.
5776 The standard doesn't define the case of shifting negative
5777 numbers, and we try to be compatible with other compilers, most
5778 notably g77, here. */
5779 rshift
= fold_convert (type
, fold_build2_loc (input_location
, RSHIFT_EXPR
,
5780 utype
, convert (utype
, args
[0]), width
));
5782 tmp
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, args
[1],
5783 build_int_cst (TREE_TYPE (args
[1]), 0));
5784 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, lshift
, rshift
);
5786 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5787 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5789 num_bits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
5790 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, width
,
5792 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
5793 build_int_cst (type
, 0), tmp
);
5797 /* Circular shift. AKA rotate or barrel shift. */
5800 gfc_conv_intrinsic_ishftc (gfc_se
* se
, gfc_expr
* expr
)
5808 unsigned int num_args
;
5810 num_args
= gfc_intrinsic_argument_list_length (expr
);
5811 args
= XALLOCAVEC (tree
, num_args
);
5813 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
5817 /* Use a library function for the 3 parameter version. */
5818 tree int4type
= gfc_get_int_type (4);
5820 type
= TREE_TYPE (args
[0]);
5821 /* We convert the first argument to at least 4 bytes, and
5822 convert back afterwards. This removes the need for library
5823 functions for all argument sizes, and function will be
5824 aligned to at least 32 bits, so there's no loss. */
5825 if (expr
->ts
.kind
< 4)
5826 args
[0] = convert (int4type
, args
[0]);
5828 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
5829 need loads of library functions. They cannot have values >
5830 BIT_SIZE (I) so the conversion is safe. */
5831 args
[1] = convert (int4type
, args
[1]);
5832 args
[2] = convert (int4type
, args
[2]);
5834 switch (expr
->ts
.kind
)
5839 tmp
= gfor_fndecl_math_ishftc4
;
5842 tmp
= gfor_fndecl_math_ishftc8
;
5845 tmp
= gfor_fndecl_math_ishftc16
;
5850 se
->expr
= build_call_expr_loc (input_location
,
5851 tmp
, 3, args
[0], args
[1], args
[2]);
5852 /* Convert the result back to the original type, if we extended
5853 the first argument's width above. */
5854 if (expr
->ts
.kind
< 4)
5855 se
->expr
= convert (type
, se
->expr
);
5859 type
= TREE_TYPE (args
[0]);
5861 /* Evaluate arguments only once. */
5862 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
5863 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
5865 /* Rotate left if positive. */
5866 lrot
= fold_build2_loc (input_location
, LROTATE_EXPR
, type
, args
[0], args
[1]);
5868 /* Rotate right if negative. */
5869 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (args
[1]),
5871 rrot
= fold_build2_loc (input_location
,RROTATE_EXPR
, type
, args
[0], tmp
);
5873 zero
= build_int_cst (TREE_TYPE (args
[1]), 0);
5874 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
, args
[1],
5876 rrot
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, lrot
, rrot
);
5878 /* Do nothing if shift == 0. */
5879 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, args
[1],
5881 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, args
[0],
5886 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
5887 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
5889 The conditional expression is necessary because the result of LEADZ(0)
5890 is defined, but the result of __builtin_clz(0) is undefined for most
5893 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
5894 difference in bit size between the argument of LEADZ and the C int. */
5897 gfc_conv_intrinsic_leadz (gfc_se
* se
, gfc_expr
* expr
)
5909 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
5910 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
5912 /* Which variant of __builtin_clz* should we call? */
5913 if (argsize
<= INT_TYPE_SIZE
)
5915 arg_type
= unsigned_type_node
;
5916 func
= builtin_decl_explicit (BUILT_IN_CLZ
);
5918 else if (argsize
<= LONG_TYPE_SIZE
)
5920 arg_type
= long_unsigned_type_node
;
5921 func
= builtin_decl_explicit (BUILT_IN_CLZL
);
5923 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
5925 arg_type
= long_long_unsigned_type_node
;
5926 func
= builtin_decl_explicit (BUILT_IN_CLZLL
);
5930 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
5931 arg_type
= gfc_build_uint_type (argsize
);
5935 /* Convert the actual argument twice: first, to the unsigned type of the
5936 same size; then, to the proper argument type for the built-in
5937 function. But the return type is of the default INTEGER kind. */
5938 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
5939 arg
= fold_convert (arg_type
, arg
);
5940 arg
= gfc_evaluate_now (arg
, &se
->pre
);
5941 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
5943 /* Compute LEADZ for the case i .ne. 0. */
5946 s
= TYPE_PRECISION (arg_type
) - argsize
;
5947 tmp
= fold_convert (result_type
,
5948 build_call_expr_loc (input_location
, func
,
5950 leadz
= fold_build2_loc (input_location
, MINUS_EXPR
, result_type
,
5951 tmp
, build_int_cst (result_type
, s
));
5955 /* We end up here if the argument type is larger than 'long long'.
5956 We generate this code:
5958 if (x & (ULL_MAX << ULL_SIZE) != 0)
5959 return clzll ((unsigned long long) (x >> ULLSIZE));
5961 return ULL_SIZE + clzll ((unsigned long long) x);
5962 where ULL_MAX is the largest value that a ULL_MAX can hold
5963 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
5964 is the bit-size of the long long type (64 in this example). */
5965 tree ullsize
, ullmax
, tmp1
, tmp2
, btmp
;
5967 ullsize
= build_int_cst (result_type
, LONG_LONG_TYPE_SIZE
);
5968 ullmax
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
5969 long_long_unsigned_type_node
,
5970 build_int_cst (long_long_unsigned_type_node
,
5973 cond
= fold_build2_loc (input_location
, LSHIFT_EXPR
, arg_type
,
5974 fold_convert (arg_type
, ullmax
), ullsize
);
5975 cond
= fold_build2_loc (input_location
, BIT_AND_EXPR
, arg_type
,
5977 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
5978 cond
, build_int_cst (arg_type
, 0));
5980 tmp1
= fold_build2_loc (input_location
, RSHIFT_EXPR
, arg_type
,
5982 tmp1
= fold_convert (long_long_unsigned_type_node
, tmp1
);
5983 btmp
= builtin_decl_explicit (BUILT_IN_CLZLL
);
5984 tmp1
= fold_convert (result_type
,
5985 build_call_expr_loc (input_location
, btmp
, 1, tmp1
));
5987 tmp2
= fold_convert (long_long_unsigned_type_node
, arg
);
5988 btmp
= builtin_decl_explicit (BUILT_IN_CLZLL
);
5989 tmp2
= fold_convert (result_type
,
5990 build_call_expr_loc (input_location
, btmp
, 1, tmp2
));
5991 tmp2
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
5994 leadz
= fold_build3_loc (input_location
, COND_EXPR
, result_type
,
5998 /* Build BIT_SIZE. */
5999 bit_size
= build_int_cst (result_type
, argsize
);
6001 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
6002 arg
, build_int_cst (arg_type
, 0));
6003 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, result_type
, cond
,
6008 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
6010 The conditional expression is necessary because the result of TRAILZ(0)
6011 is defined, but the result of __builtin_ctz(0) is undefined for most
6015 gfc_conv_intrinsic_trailz (gfc_se
* se
, gfc_expr
*expr
)
6026 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6027 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
6029 /* Which variant of __builtin_ctz* should we call? */
6030 if (argsize
<= INT_TYPE_SIZE
)
6032 arg_type
= unsigned_type_node
;
6033 func
= builtin_decl_explicit (BUILT_IN_CTZ
);
6035 else if (argsize
<= LONG_TYPE_SIZE
)
6037 arg_type
= long_unsigned_type_node
;
6038 func
= builtin_decl_explicit (BUILT_IN_CTZL
);
6040 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
6042 arg_type
= long_long_unsigned_type_node
;
6043 func
= builtin_decl_explicit (BUILT_IN_CTZLL
);
6047 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
6048 arg_type
= gfc_build_uint_type (argsize
);
6052 /* Convert the actual argument twice: first, to the unsigned type of the
6053 same size; then, to the proper argument type for the built-in
6054 function. But the return type is of the default INTEGER kind. */
6055 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
6056 arg
= fold_convert (arg_type
, arg
);
6057 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6058 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
6060 /* Compute TRAILZ for the case i .ne. 0. */
6062 trailz
= fold_convert (result_type
, build_call_expr_loc (input_location
,
6066 /* We end up here if the argument type is larger than 'long long'.
6067 We generate this code:
6069 if ((x & ULL_MAX) == 0)
6070 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
6072 return ctzll ((unsigned long long) x);
6074 where ULL_MAX is the largest value that a ULL_MAX can hold
6075 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
6076 is the bit-size of the long long type (64 in this example). */
6077 tree ullsize
, ullmax
, tmp1
, tmp2
, btmp
;
6079 ullsize
= build_int_cst (result_type
, LONG_LONG_TYPE_SIZE
);
6080 ullmax
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
6081 long_long_unsigned_type_node
,
6082 build_int_cst (long_long_unsigned_type_node
, 0));
6084 cond
= fold_build2_loc (input_location
, BIT_AND_EXPR
, arg_type
, arg
,
6085 fold_convert (arg_type
, ullmax
));
6086 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, cond
,
6087 build_int_cst (arg_type
, 0));
6089 tmp1
= fold_build2_loc (input_location
, RSHIFT_EXPR
, arg_type
,
6091 tmp1
= fold_convert (long_long_unsigned_type_node
, tmp1
);
6092 btmp
= builtin_decl_explicit (BUILT_IN_CTZLL
);
6093 tmp1
= fold_convert (result_type
,
6094 build_call_expr_loc (input_location
, btmp
, 1, tmp1
));
6095 tmp1
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
6098 tmp2
= fold_convert (long_long_unsigned_type_node
, arg
);
6099 btmp
= builtin_decl_explicit (BUILT_IN_CTZLL
);
6100 tmp2
= fold_convert (result_type
,
6101 build_call_expr_loc (input_location
, btmp
, 1, tmp2
));
6103 trailz
= fold_build3_loc (input_location
, COND_EXPR
, result_type
,
6107 /* Build BIT_SIZE. */
6108 bit_size
= build_int_cst (result_type
, argsize
);
6110 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
6111 arg
, build_int_cst (arg_type
, 0));
6112 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, result_type
, cond
,
6116 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
6117 for types larger than "long long", we call the long long built-in for
6118 the lower and higher bits and combine the result. */
6121 gfc_conv_intrinsic_popcnt_poppar (gfc_se
* se
, gfc_expr
*expr
, int parity
)
6129 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6130 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
6131 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
6133 /* Which variant of the builtin should we call? */
6134 if (argsize
<= INT_TYPE_SIZE
)
6136 arg_type
= unsigned_type_node
;
6137 func
= builtin_decl_explicit (parity
6139 : BUILT_IN_POPCOUNT
);
6141 else if (argsize
<= LONG_TYPE_SIZE
)
6143 arg_type
= long_unsigned_type_node
;
6144 func
= builtin_decl_explicit (parity
6146 : BUILT_IN_POPCOUNTL
);
6148 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
6150 arg_type
= long_long_unsigned_type_node
;
6151 func
= builtin_decl_explicit (parity
6153 : BUILT_IN_POPCOUNTLL
);
6157 /* Our argument type is larger than 'long long', which mean none
6158 of the POPCOUNT builtins covers it. We thus call the 'long long'
6159 variant multiple times, and add the results. */
6160 tree utype
, arg2
, call1
, call2
;
6162 /* For now, we only cover the case where argsize is twice as large
6164 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
6166 func
= builtin_decl_explicit (parity
6168 : BUILT_IN_POPCOUNTLL
);
6170 /* Convert it to an integer, and store into a variable. */
6171 utype
= gfc_build_uint_type (argsize
);
6172 arg
= fold_convert (utype
, arg
);
6173 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6175 /* Call the builtin twice. */
6176 call1
= build_call_expr_loc (input_location
, func
, 1,
6177 fold_convert (long_long_unsigned_type_node
,
6180 arg2
= fold_build2_loc (input_location
, RSHIFT_EXPR
, utype
, arg
,
6181 build_int_cst (utype
, LONG_LONG_TYPE_SIZE
));
6182 call2
= build_call_expr_loc (input_location
, func
, 1,
6183 fold_convert (long_long_unsigned_type_node
,
6186 /* Combine the results. */
6188 se
->expr
= fold_build2_loc (input_location
, BIT_XOR_EXPR
, result_type
,
6191 se
->expr
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
6197 /* Convert the actual argument twice: first, to the unsigned type of the
6198 same size; then, to the proper argument type for the built-in
6200 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
6201 arg
= fold_convert (arg_type
, arg
);
6203 se
->expr
= fold_convert (result_type
,
6204 build_call_expr_loc (input_location
, func
, 1, arg
));
6208 /* Process an intrinsic with unspecified argument-types that has an optional
6209 argument (which could be of type character), e.g. EOSHIFT. For those, we
6210 need to append the string length of the optional argument if it is not
6211 present and the type is really character.
6212 primary specifies the position (starting at 1) of the non-optional argument
6213 specifying the type and optional gives the position of the optional
6214 argument in the arglist. */
6217 conv_generic_with_optional_char_arg (gfc_se
* se
, gfc_expr
* expr
,
6218 unsigned primary
, unsigned optional
)
6220 gfc_actual_arglist
* prim_arg
;
6221 gfc_actual_arglist
* opt_arg
;
6223 gfc_actual_arglist
* arg
;
6225 vec
<tree
, va_gc
> *append_args
;
6227 /* Find the two arguments given as position. */
6231 for (arg
= expr
->value
.function
.actual
; arg
; arg
= arg
->next
)
6235 if (cur_pos
== primary
)
6237 if (cur_pos
== optional
)
6240 if (cur_pos
>= primary
&& cur_pos
>= optional
)
6243 gcc_assert (prim_arg
);
6244 gcc_assert (prim_arg
->expr
);
6245 gcc_assert (opt_arg
);
6247 /* If we do have type CHARACTER and the optional argument is really absent,
6248 append a dummy 0 as string length. */
6250 if (prim_arg
->expr
->ts
.type
== BT_CHARACTER
&& !opt_arg
->expr
)
6254 dummy
= build_int_cst (gfc_charlen_type_node
, 0);
6255 vec_alloc (append_args
, 1);
6256 append_args
->quick_push (dummy
);
6259 /* Build the call itself. */
6260 gcc_assert (!se
->ignore_optional
);
6261 sym
= gfc_get_symbol_for_expr (expr
, false);
6262 gfc_conv_procedure_call (se
, sym
, expr
->value
.function
.actual
, expr
,
6264 gfc_free_symbol (sym
);
6267 /* The length of a character string. */
6269 gfc_conv_intrinsic_len (gfc_se
* se
, gfc_expr
* expr
)
6278 gcc_assert (!se
->ss
);
6280 arg
= expr
->value
.function
.actual
->expr
;
6282 type
= gfc_typenode_for_spec (&expr
->ts
);
6283 switch (arg
->expr_type
)
6286 len
= build_int_cst (gfc_charlen_type_node
, arg
->value
.character
.length
);
6290 /* Obtain the string length from the function used by
6291 trans-array.c(gfc_trans_array_constructor). */
6293 get_array_ctor_strlen (&se
->pre
, arg
->value
.constructor
, &len
);
6297 if (arg
->ref
== NULL
6298 || (arg
->ref
->next
== NULL
&& arg
->ref
->type
== REF_ARRAY
))
6300 /* This doesn't catch all cases.
6301 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
6302 and the surrounding thread. */
6303 sym
= arg
->symtree
->n
.sym
;
6304 decl
= gfc_get_symbol_decl (sym
);
6305 if (decl
== current_function_decl
&& sym
->attr
.function
6306 && (sym
->result
== sym
))
6307 decl
= gfc_get_fake_result_decl (sym
, 0);
6309 len
= sym
->ts
.u
.cl
->backend_decl
;
6317 /* Anybody stupid enough to do this deserves inefficient code. */
6318 gfc_init_se (&argse
, se
);
6320 gfc_conv_expr (&argse
, arg
);
6322 gfc_conv_expr_descriptor (&argse
, arg
);
6323 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6324 gfc_add_block_to_block (&se
->post
, &argse
.post
);
6325 len
= argse
.string_length
;
6328 se
->expr
= convert (type
, len
);
6331 /* The length of a character string not including trailing blanks. */
6333 gfc_conv_intrinsic_len_trim (gfc_se
* se
, gfc_expr
* expr
)
6335 int kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
6336 tree args
[2], type
, fndecl
;
6338 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6339 type
= gfc_typenode_for_spec (&expr
->ts
);
6342 fndecl
= gfor_fndecl_string_len_trim
;
6344 fndecl
= gfor_fndecl_string_len_trim_char4
;
6348 se
->expr
= build_call_expr_loc (input_location
,
6349 fndecl
, 2, args
[0], args
[1]);
6350 se
->expr
= convert (type
, se
->expr
);
6354 /* Returns the starting position of a substring within a string. */
6357 gfc_conv_intrinsic_index_scan_verify (gfc_se
* se
, gfc_expr
* expr
,
6360 tree logical4_type_node
= gfc_get_logical_type (4);
6364 unsigned int num_args
;
6366 args
= XALLOCAVEC (tree
, 5);
6368 /* Get number of arguments; characters count double due to the
6369 string length argument. Kind= is not passed to the library
6370 and thus ignored. */
6371 if (expr
->value
.function
.actual
->next
->next
->expr
== NULL
)
6376 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
6377 type
= gfc_typenode_for_spec (&expr
->ts
);
6380 args
[4] = build_int_cst (logical4_type_node
, 0);
6382 args
[4] = convert (logical4_type_node
, args
[4]);
6384 fndecl
= build_addr (function
);
6385 se
->expr
= build_call_array_loc (input_location
,
6386 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
6388 se
->expr
= convert (type
, se
->expr
);
6392 /* The ascii value for a single character. */
6394 gfc_conv_intrinsic_ichar (gfc_se
* se
, gfc_expr
* expr
)
6396 tree args
[3], type
, pchartype
;
6399 nargs
= gfc_intrinsic_argument_list_length (expr
);
6400 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
6401 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args
[1])));
6402 pchartype
= gfc_get_pchar_type (expr
->value
.function
.actual
->expr
->ts
.kind
);
6403 args
[1] = fold_build1_loc (input_location
, NOP_EXPR
, pchartype
, args
[1]);
6404 type
= gfc_typenode_for_spec (&expr
->ts
);
6406 se
->expr
= build_fold_indirect_ref_loc (input_location
,
6408 se
->expr
= convert (type
, se
->expr
);
6412 /* Intrinsic ISNAN calls __builtin_isnan. */
6415 gfc_conv_intrinsic_isnan (gfc_se
* se
, gfc_expr
* expr
)
6419 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6420 se
->expr
= build_call_expr_loc (input_location
,
6421 builtin_decl_explicit (BUILT_IN_ISNAN
),
6423 STRIP_TYPE_NOPS (se
->expr
);
6424 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
6428 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
6429 their argument against a constant integer value. */
6432 gfc_conv_has_intvalue (gfc_se
* se
, gfc_expr
* expr
, const int value
)
6436 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6437 se
->expr
= fold_build2_loc (input_location
, EQ_EXPR
,
6438 gfc_typenode_for_spec (&expr
->ts
),
6439 arg
, build_int_cst (TREE_TYPE (arg
), value
));
6444 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
6447 gfc_conv_intrinsic_merge (gfc_se
* se
, gfc_expr
* expr
)
6455 unsigned int num_args
;
6457 num_args
= gfc_intrinsic_argument_list_length (expr
);
6458 args
= XALLOCAVEC (tree
, num_args
);
6460 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
6461 if (expr
->ts
.type
!= BT_CHARACTER
)
6469 /* We do the same as in the non-character case, but the argument
6470 list is different because of the string length arguments. We
6471 also have to set the string length for the result. */
6478 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr
->where
, len
, len2
,
6480 se
->string_length
= len
;
6482 type
= TREE_TYPE (tsource
);
6483 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, mask
, tsource
,
6484 fold_convert (type
, fsource
));
6488 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
6491 gfc_conv_intrinsic_merge_bits (gfc_se
* se
, gfc_expr
* expr
)
6493 tree args
[3], mask
, type
;
6495 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
6496 mask
= gfc_evaluate_now (args
[2], &se
->pre
);
6498 type
= TREE_TYPE (args
[0]);
6499 gcc_assert (TREE_TYPE (args
[1]) == type
);
6500 gcc_assert (TREE_TYPE (mask
) == type
);
6502 args
[0] = fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[0], mask
);
6503 args
[1] = fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[1],
6504 fold_build1_loc (input_location
, BIT_NOT_EXPR
,
6506 se
->expr
= fold_build2_loc (input_location
, BIT_IOR_EXPR
, type
,
6511 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
6512 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
6515 gfc_conv_intrinsic_mask (gfc_se
* se
, gfc_expr
* expr
, int left
)
6517 tree arg
, allones
, type
, utype
, res
, cond
, bitsize
;
6520 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6521 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6523 type
= gfc_get_int_type (expr
->ts
.kind
);
6524 utype
= unsigned_type_for (type
);
6526 i
= gfc_validate_kind (BT_INTEGER
, expr
->ts
.kind
, false);
6527 bitsize
= build_int_cst (TREE_TYPE (arg
), gfc_integer_kinds
[i
].bit_size
);
6529 allones
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, utype
,
6530 build_int_cst (utype
, 0));
6534 /* Left-justified mask. */
6535 res
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (arg
),
6537 res
= fold_build2_loc (input_location
, LSHIFT_EXPR
, utype
, allones
,
6538 fold_convert (utype
, res
));
6540 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
6541 smaller than type width. */
6542 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, arg
,
6543 build_int_cst (TREE_TYPE (arg
), 0));
6544 res
= fold_build3_loc (input_location
, COND_EXPR
, utype
, cond
,
6545 build_int_cst (utype
, 0), res
);
6549 /* Right-justified mask. */
6550 res
= fold_build2_loc (input_location
, LSHIFT_EXPR
, utype
, allones
,
6551 fold_convert (utype
, arg
));
6552 res
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, utype
, res
);
6554 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
6555 strictly smaller than type width. */
6556 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
6558 res
= fold_build3_loc (input_location
, COND_EXPR
, utype
,
6559 cond
, allones
, res
);
6562 se
->expr
= fold_convert (type
, res
);
6566 /* FRACTION (s) is translated into:
6567 isfinite (s) ? frexp (s, &dummy_int) : NaN */
6569 gfc_conv_intrinsic_fraction (gfc_se
* se
, gfc_expr
* expr
)
6571 tree arg
, type
, tmp
, res
, frexp
, cond
;
6573 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
6575 type
= gfc_typenode_for_spec (&expr
->ts
);
6576 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6577 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6579 cond
= build_call_expr_loc (input_location
,
6580 builtin_decl_explicit (BUILT_IN_ISFINITE
),
6583 tmp
= gfc_create_var (integer_type_node
, NULL
);
6584 res
= build_call_expr_loc (input_location
, frexp
, 2,
6585 fold_convert (type
, arg
),
6586 gfc_build_addr_expr (NULL_TREE
, tmp
));
6587 res
= fold_convert (type
, res
);
6589 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
,
6590 cond
, res
, gfc_build_nan (type
, ""));
6594 /* NEAREST (s, dir) is translated into
6595 tmp = copysign (HUGE_VAL, dir);
6596 return nextafter (s, tmp);
6599 gfc_conv_intrinsic_nearest (gfc_se
* se
, gfc_expr
* expr
)
6601 tree args
[2], type
, tmp
, nextafter
, copysign
, huge_val
;
6603 nextafter
= gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER
, expr
->ts
.kind
);
6604 copysign
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
, expr
->ts
.kind
);
6606 type
= gfc_typenode_for_spec (&expr
->ts
);
6607 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6609 huge_val
= gfc_build_inf_or_huge (type
, expr
->ts
.kind
);
6610 tmp
= build_call_expr_loc (input_location
, copysign
, 2, huge_val
,
6611 fold_convert (type
, args
[1]));
6612 se
->expr
= build_call_expr_loc (input_location
, nextafter
, 2,
6613 fold_convert (type
, args
[0]), tmp
);
6614 se
->expr
= fold_convert (type
, se
->expr
);
6618 /* SPACING (s) is translated into
6628 e = MAX_EXPR (e, emin);
6629 res = scalbn (1., e);
6633 where prec is the precision of s, gfc_real_kinds[k].digits,
6634 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
6635 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
6638 gfc_conv_intrinsic_spacing (gfc_se
* se
, gfc_expr
* expr
)
6640 tree arg
, type
, prec
, emin
, tiny
, res
, e
;
6641 tree cond
, nan
, tmp
, frexp
, scalbn
;
6645 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
6646 prec
= build_int_cst (integer_type_node
, gfc_real_kinds
[k
].digits
);
6647 emin
= build_int_cst (integer_type_node
, gfc_real_kinds
[k
].min_exponent
- 1);
6648 tiny
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[k
].tiny
, expr
->ts
.kind
, 0);
6650 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
6651 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
6653 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6654 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6656 type
= gfc_typenode_for_spec (&expr
->ts
);
6657 e
= gfc_create_var (integer_type_node
, NULL
);
6658 res
= gfc_create_var (type
, NULL
);
6661 /* Build the block for s /= 0. */
6662 gfc_start_block (&block
);
6663 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
6664 gfc_build_addr_expr (NULL_TREE
, e
));
6665 gfc_add_expr_to_block (&block
, tmp
);
6667 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, integer_type_node
, e
,
6669 gfc_add_modify (&block
, e
, fold_build2_loc (input_location
, MAX_EXPR
,
6670 integer_type_node
, tmp
, emin
));
6672 tmp
= build_call_expr_loc (input_location
, scalbn
, 2,
6673 build_real_from_int_cst (type
, integer_one_node
), e
);
6674 gfc_add_modify (&block
, res
, tmp
);
6676 /* Finish by building the IF statement for value zero. */
6677 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, arg
,
6678 build_real_from_int_cst (type
, integer_zero_node
));
6679 tmp
= build3_v (COND_EXPR
, cond
, build2_v (MODIFY_EXPR
, res
, tiny
),
6680 gfc_finish_block (&block
));
6682 /* And deal with infinities and NaNs. */
6683 cond
= build_call_expr_loc (input_location
,
6684 builtin_decl_explicit (BUILT_IN_ISFINITE
),
6686 nan
= gfc_build_nan (type
, "");
6687 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build2_v (MODIFY_EXPR
, res
, nan
));
6689 gfc_add_expr_to_block (&se
->pre
, tmp
);
6694 /* RRSPACING (s) is translated into
6703 x = scalbn (x, precision - e);
6710 where precision is gfc_real_kinds[k].digits. */
6713 gfc_conv_intrinsic_rrspacing (gfc_se
* se
, gfc_expr
* expr
)
6715 tree arg
, type
, e
, x
, cond
, nan
, stmt
, tmp
, frexp
, scalbn
, fabs
;
6719 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
6720 prec
= gfc_real_kinds
[k
].digits
;
6722 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
6723 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
6724 fabs
= gfc_builtin_decl_for_float_kind (BUILT_IN_FABS
, expr
->ts
.kind
);
6726 type
= gfc_typenode_for_spec (&expr
->ts
);
6727 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6728 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6730 e
= gfc_create_var (integer_type_node
, NULL
);
6731 x
= gfc_create_var (type
, NULL
);
6732 gfc_add_modify (&se
->pre
, x
,
6733 build_call_expr_loc (input_location
, fabs
, 1, arg
));
6736 gfc_start_block (&block
);
6737 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
6738 gfc_build_addr_expr (NULL_TREE
, e
));
6739 gfc_add_expr_to_block (&block
, tmp
);
6741 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, integer_type_node
,
6742 build_int_cst (integer_type_node
, prec
), e
);
6743 tmp
= build_call_expr_loc (input_location
, scalbn
, 2, x
, tmp
);
6744 gfc_add_modify (&block
, x
, tmp
);
6745 stmt
= gfc_finish_block (&block
);
6748 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, x
,
6749 build_real_from_int_cst (type
, integer_zero_node
));
6750 tmp
= build3_v (COND_EXPR
, cond
, stmt
, build_empty_stmt (input_location
));
6752 /* And deal with infinities and NaNs. */
6753 cond
= build_call_expr_loc (input_location
,
6754 builtin_decl_explicit (BUILT_IN_ISFINITE
),
6756 nan
= gfc_build_nan (type
, "");
6757 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build2_v (MODIFY_EXPR
, x
, nan
));
6759 gfc_add_expr_to_block (&se
->pre
, tmp
);
6760 se
->expr
= fold_convert (type
, x
);
6764 /* SCALE (s, i) is translated into scalbn (s, i). */
6766 gfc_conv_intrinsic_scale (gfc_se
* se
, gfc_expr
* expr
)
6768 tree args
[2], type
, scalbn
;
6770 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
6772 type
= gfc_typenode_for_spec (&expr
->ts
);
6773 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6774 se
->expr
= build_call_expr_loc (input_location
, scalbn
, 2,
6775 fold_convert (type
, args
[0]),
6776 fold_convert (integer_type_node
, args
[1]));
6777 se
->expr
= fold_convert (type
, se
->expr
);
6781 /* SET_EXPONENT (s, i) is translated into
6782 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
6784 gfc_conv_intrinsic_set_exponent (gfc_se
* se
, gfc_expr
* expr
)
6786 tree args
[2], type
, tmp
, frexp
, scalbn
, cond
, nan
, res
;
6788 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
6789 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
6791 type
= gfc_typenode_for_spec (&expr
->ts
);
6792 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6793 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
6795 tmp
= gfc_create_var (integer_type_node
, NULL
);
6796 tmp
= build_call_expr_loc (input_location
, frexp
, 2,
6797 fold_convert (type
, args
[0]),
6798 gfc_build_addr_expr (NULL_TREE
, tmp
));
6799 res
= build_call_expr_loc (input_location
, scalbn
, 2, tmp
,
6800 fold_convert (integer_type_node
, args
[1]));
6801 res
= fold_convert (type
, res
);
6803 /* Call to isfinite */
6804 cond
= build_call_expr_loc (input_location
,
6805 builtin_decl_explicit (BUILT_IN_ISFINITE
),
6807 nan
= gfc_build_nan (type
, "");
6809 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
6815 gfc_conv_intrinsic_size (gfc_se
* se
, gfc_expr
* expr
)
6817 gfc_actual_arglist
*actual
;
6824 gfc_init_se (&argse
, NULL
);
6825 actual
= expr
->value
.function
.actual
;
6827 if (actual
->expr
->ts
.type
== BT_CLASS
)
6828 gfc_add_class_array_ref (actual
->expr
);
6830 argse
.data_not_needed
= 1;
6831 if (gfc_is_class_array_function (actual
->expr
))
6833 /* For functions that return a class array conv_expr_descriptor is not
6834 able to get the descriptor right. Therefore this special case. */
6835 gfc_conv_expr_reference (&argse
, actual
->expr
);
6836 argse
.expr
= gfc_build_addr_expr (NULL_TREE
,
6837 gfc_class_data_get (argse
.expr
));
6841 argse
.want_pointer
= 1;
6842 gfc_conv_expr_descriptor (&argse
, actual
->expr
);
6844 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6845 gfc_add_block_to_block (&se
->post
, &argse
.post
);
6846 arg1
= gfc_evaluate_now (argse
.expr
, &se
->pre
);
6848 /* Build the call to size0. */
6849 fncall0
= build_call_expr_loc (input_location
,
6850 gfor_fndecl_size0
, 1, arg1
);
6852 actual
= actual
->next
;
6856 gfc_init_se (&argse
, NULL
);
6857 gfc_conv_expr_type (&argse
, actual
->expr
,
6858 gfc_array_index_type
);
6859 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6861 /* Unusually, for an intrinsic, size does not exclude
6862 an optional arg2, so we must test for it. */
6863 if (actual
->expr
->expr_type
== EXPR_VARIABLE
6864 && actual
->expr
->symtree
->n
.sym
->attr
.dummy
6865 && actual
->expr
->symtree
->n
.sym
->attr
.optional
)
6868 /* Build the call to size1. */
6869 fncall1
= build_call_expr_loc (input_location
,
6870 gfor_fndecl_size1
, 2,
6873 gfc_init_se (&argse
, NULL
);
6874 argse
.want_pointer
= 1;
6875 argse
.data_not_needed
= 1;
6876 gfc_conv_expr (&argse
, actual
->expr
);
6877 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6878 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
6879 argse
.expr
, null_pointer_node
);
6880 tmp
= gfc_evaluate_now (tmp
, &se
->pre
);
6881 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
6882 pvoid_type_node
, tmp
, fncall1
, fncall0
);
6886 se
->expr
= NULL_TREE
;
6887 argse
.expr
= fold_build2_loc (input_location
, MINUS_EXPR
,
6888 gfc_array_index_type
,
6889 argse
.expr
, gfc_index_one_node
);
6892 else if (expr
->value
.function
.actual
->expr
->rank
== 1)
6894 argse
.expr
= gfc_index_zero_node
;
6895 se
->expr
= NULL_TREE
;
6900 if (se
->expr
== NULL_TREE
)
6902 tree ubound
, lbound
;
6904 arg1
= build_fold_indirect_ref_loc (input_location
,
6906 ubound
= gfc_conv_descriptor_ubound_get (arg1
, argse
.expr
);
6907 lbound
= gfc_conv_descriptor_lbound_get (arg1
, argse
.expr
);
6908 se
->expr
= fold_build2_loc (input_location
, MINUS_EXPR
,
6909 gfc_array_index_type
, ubound
, lbound
);
6910 se
->expr
= fold_build2_loc (input_location
, PLUS_EXPR
,
6911 gfc_array_index_type
,
6912 se
->expr
, gfc_index_one_node
);
6913 se
->expr
= fold_build2_loc (input_location
, MAX_EXPR
,
6914 gfc_array_index_type
, se
->expr
,
6915 gfc_index_zero_node
);
6918 type
= gfc_typenode_for_spec (&expr
->ts
);
6919 se
->expr
= convert (type
, se
->expr
);
6923 /* Helper function to compute the size of a character variable,
6924 excluding the terminating null characters. The result has
6925 gfc_array_index_type type. */
6928 size_of_string_in_bytes (int kind
, tree string_length
)
6931 int i
= gfc_validate_kind (BT_CHARACTER
, kind
, false);
6933 bytesize
= build_int_cst (gfc_array_index_type
,
6934 gfc_character_kinds
[i
].bit_size
/ 8);
6936 return fold_build2_loc (input_location
, MULT_EXPR
, gfc_array_index_type
,
6938 fold_convert (gfc_array_index_type
, string_length
));
6943 gfc_conv_intrinsic_sizeof (gfc_se
*se
, gfc_expr
*expr
)
6955 gfc_init_se (&argse
, NULL
);
6956 arg
= expr
->value
.function
.actual
->expr
;
6958 if (arg
->rank
|| arg
->ts
.type
== BT_ASSUMED
)
6959 gfc_conv_expr_descriptor (&argse
, arg
);
6961 gfc_conv_expr_reference (&argse
, arg
);
6963 if (arg
->ts
.type
== BT_ASSUMED
)
6965 /* This only works if an array descriptor has been passed; thus, extract
6966 the size from the descriptor. */
6967 gcc_assert (TYPE_PRECISION (gfc_array_index_type
)
6968 == TYPE_PRECISION (size_type_node
));
6969 tmp
= arg
->symtree
->n
.sym
->backend_decl
;
6970 tmp
= DECL_LANG_SPECIFIC (tmp
)
6971 && GFC_DECL_SAVED_DESCRIPTOR (tmp
) != NULL_TREE
6972 ? GFC_DECL_SAVED_DESCRIPTOR (tmp
) : tmp
;
6973 if (POINTER_TYPE_P (TREE_TYPE (tmp
)))
6974 tmp
= build_fold_indirect_ref_loc (input_location
, tmp
);
6976 tmp
= gfc_conv_descriptor_dtype (tmp
);
6977 field
= gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
6978 GFC_DTYPE_ELEM_LEN
);
6979 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
6980 tmp
, field
, NULL_TREE
);
6982 byte_size
= fold_convert (gfc_array_index_type
, tmp
);
6984 else if (arg
->ts
.type
== BT_CLASS
)
6986 /* Conv_expr_descriptor returns a component_ref to _data component of the
6987 class object. The class object may be a non-pointer object, e.g.
6988 located on the stack, or a memory location pointed to, e.g. a
6989 parameter, i.e., an indirect_ref. */
6991 || (arg
->rank
> 0 && !VAR_P (argse
.expr
)
6992 && ((INDIRECT_REF_P (TREE_OPERAND (argse
.expr
, 0))
6993 && GFC_DECL_CLASS (TREE_OPERAND (
6994 TREE_OPERAND (argse
.expr
, 0), 0)))
6995 || GFC_DECL_CLASS (TREE_OPERAND (argse
.expr
, 0)))))
6996 byte_size
= gfc_class_vtab_size_get (TREE_OPERAND (argse
.expr
, 0));
6997 else if (arg
->rank
> 0
6999 && arg
->ref
&& arg
->ref
->type
== REF_COMPONENT
))
7000 /* The scalarizer added an additional temp. To get the class' vptr
7001 one has to look at the original backend_decl. */
7002 byte_size
= gfc_class_vtab_size_get (
7003 GFC_DECL_SAVED_DESCRIPTOR (arg
->symtree
->n
.sym
->backend_decl
));
7005 byte_size
= gfc_class_vtab_size_get (argse
.expr
);
7009 if (arg
->ts
.type
== BT_CHARACTER
)
7010 byte_size
= size_of_string_in_bytes (arg
->ts
.kind
, argse
.string_length
);
7014 byte_size
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
7017 byte_size
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
7018 byte_size
= fold_convert (gfc_array_index_type
,
7019 size_in_bytes (byte_size
));
7024 se
->expr
= byte_size
;
7027 source_bytes
= gfc_create_var (gfc_array_index_type
, "bytes");
7028 gfc_add_modify (&argse
.pre
, source_bytes
, byte_size
);
7030 if (arg
->rank
== -1)
7032 tree cond
, loop_var
, exit_label
;
7035 tmp
= fold_convert (gfc_array_index_type
,
7036 gfc_conv_descriptor_rank (argse
.expr
));
7037 loop_var
= gfc_create_var (gfc_array_index_type
, "i");
7038 gfc_add_modify (&argse
.pre
, loop_var
, gfc_index_zero_node
);
7039 exit_label
= gfc_build_label_decl (NULL_TREE
);
7046 source_bytes = source_bytes * array.dim[i].extent;
7050 gfc_start_block (&body
);
7051 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
7053 tmp
= build1_v (GOTO_EXPR
, exit_label
);
7054 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
7055 cond
, tmp
, build_empty_stmt (input_location
));
7056 gfc_add_expr_to_block (&body
, tmp
);
7058 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, loop_var
);
7059 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, loop_var
);
7060 tmp
= gfc_conv_array_extent_dim (lower
, upper
, NULL
);
7061 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
7062 gfc_array_index_type
, tmp
, source_bytes
);
7063 gfc_add_modify (&body
, source_bytes
, tmp
);
7065 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
7066 gfc_array_index_type
, loop_var
,
7067 gfc_index_one_node
);
7068 gfc_add_modify_loc (input_location
, &body
, loop_var
, tmp
);
7070 tmp
= gfc_finish_block (&body
);
7072 tmp
= fold_build1_loc (input_location
, LOOP_EXPR
, void_type_node
,
7074 gfc_add_expr_to_block (&argse
.pre
, tmp
);
7076 tmp
= build1_v (LABEL_EXPR
, exit_label
);
7077 gfc_add_expr_to_block (&argse
.pre
, tmp
);
7081 /* Obtain the size of the array in bytes. */
7082 for (n
= 0; n
< arg
->rank
; n
++)
7085 idx
= gfc_rank_cst
[n
];
7086 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, idx
);
7087 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, idx
);
7088 tmp
= gfc_conv_array_extent_dim (lower
, upper
, NULL
);
7089 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
7090 gfc_array_index_type
, tmp
, source_bytes
);
7091 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
7094 se
->expr
= source_bytes
;
7097 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7102 gfc_conv_intrinsic_storage_size (gfc_se
*se
, gfc_expr
*expr
)
7106 tree type
, result_type
, tmp
;
7108 arg
= expr
->value
.function
.actual
->expr
;
7110 gfc_init_se (&argse
, NULL
);
7111 result_type
= gfc_get_int_type (expr
->ts
.kind
);
7115 if (arg
->ts
.type
== BT_CLASS
)
7117 gfc_add_vptr_component (arg
);
7118 gfc_add_size_component (arg
);
7119 gfc_conv_expr (&argse
, arg
);
7120 tmp
= fold_convert (result_type
, argse
.expr
);
7124 gfc_conv_expr_reference (&argse
, arg
);
7125 type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
7130 argse
.want_pointer
= 0;
7131 gfc_conv_expr_descriptor (&argse
, arg
);
7132 if (arg
->ts
.type
== BT_CLASS
)
7135 tmp
= gfc_class_vtab_size_get (
7136 GFC_DECL_SAVED_DESCRIPTOR (arg
->symtree
->n
.sym
->backend_decl
));
7138 tmp
= gfc_class_vtab_size_get (TREE_OPERAND (argse
.expr
, 0));
7139 tmp
= fold_convert (result_type
, tmp
);
7142 type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
7145 /* Obtain the argument's word length. */
7146 if (arg
->ts
.type
== BT_CHARACTER
)
7147 tmp
= size_of_string_in_bytes (arg
->ts
.kind
, argse
.string_length
);
7149 tmp
= size_in_bytes (type
);
7150 tmp
= fold_convert (result_type
, tmp
);
7153 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, result_type
, tmp
,
7154 build_int_cst (result_type
, BITS_PER_UNIT
));
7155 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7159 /* Intrinsic string comparison functions. */
7162 gfc_conv_intrinsic_strcmp (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
7166 gfc_conv_intrinsic_function_args (se
, expr
, args
, 4);
7169 = gfc_build_compare_string (args
[0], args
[1], args
[2], args
[3],
7170 expr
->value
.function
.actual
->expr
->ts
.kind
,
7172 se
->expr
= fold_build2_loc (input_location
, op
,
7173 gfc_typenode_for_spec (&expr
->ts
), se
->expr
,
7174 build_int_cst (TREE_TYPE (se
->expr
), 0));
7177 /* Generate a call to the adjustl/adjustr library function. */
7179 gfc_conv_intrinsic_adjust (gfc_se
* se
, gfc_expr
* expr
, tree fndecl
)
7187 gfc_conv_intrinsic_function_args (se
, expr
, &args
[1], 2);
7190 type
= TREE_TYPE (args
[2]);
7191 var
= gfc_conv_string_tmp (se
, type
, len
);
7194 tmp
= build_call_expr_loc (input_location
,
7195 fndecl
, 3, args
[0], args
[1], args
[2]);
7196 gfc_add_expr_to_block (&se
->pre
, tmp
);
7198 se
->string_length
= len
;
7202 /* Generate code for the TRANSFER intrinsic:
7204 DEST = TRANSFER (SOURCE, MOLD)
7206 typeof<DEST> = typeof<MOLD>
7211 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
7213 typeof<DEST> = typeof<MOLD>
7215 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
7216 sizeof (DEST(0) * SIZE). */
7218 gfc_conv_intrinsic_transfer (gfc_se
* se
, gfc_expr
* expr
)
7234 gfc_actual_arglist
*arg
;
7236 gfc_array_info
*info
;
7240 gfc_expr
*source_expr
, *mold_expr
;
7244 info
= &se
->ss
->info
->data
.array
;
7246 /* Convert SOURCE. The output from this stage is:-
7247 source_bytes = length of the source in bytes
7248 source = pointer to the source data. */
7249 arg
= expr
->value
.function
.actual
;
7250 source_expr
= arg
->expr
;
7252 /* Ensure double transfer through LOGICAL preserves all
7254 if (arg
->expr
->expr_type
== EXPR_FUNCTION
7255 && arg
->expr
->value
.function
.esym
== NULL
7256 && arg
->expr
->value
.function
.isym
!= NULL
7257 && arg
->expr
->value
.function
.isym
->id
== GFC_ISYM_TRANSFER
7258 && arg
->expr
->ts
.type
== BT_LOGICAL
7259 && expr
->ts
.type
!= arg
->expr
->ts
.type
)
7260 arg
->expr
->value
.function
.name
= "__transfer_in_transfer";
7262 gfc_init_se (&argse
, NULL
);
7264 source_bytes
= gfc_create_var (gfc_array_index_type
, NULL
);
7266 /* Obtain the pointer to source and the length of source in bytes. */
7267 if (arg
->expr
->rank
== 0)
7269 gfc_conv_expr_reference (&argse
, arg
->expr
);
7270 if (arg
->expr
->ts
.type
== BT_CLASS
)
7271 source
= gfc_class_data_get (argse
.expr
);
7273 source
= argse
.expr
;
7275 /* Obtain the source word length. */
7276 switch (arg
->expr
->ts
.type
)
7279 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
,
7280 argse
.string_length
);
7283 tmp
= gfc_class_vtab_size_get (argse
.expr
);
7286 source_type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
7288 tmp
= fold_convert (gfc_array_index_type
,
7289 size_in_bytes (source_type
));
7295 argse
.want_pointer
= 0;
7296 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
7297 source
= gfc_conv_descriptor_data_get (argse
.expr
);
7298 source_type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
7300 /* Repack the source if not simply contiguous. */
7301 if (!gfc_is_simply_contiguous (arg
->expr
, false, true))
7303 tmp
= gfc_build_addr_expr (NULL_TREE
, argse
.expr
);
7305 if (warn_array_temporaries
)
7306 gfc_warning (OPT_Warray_temporaries
,
7307 "Creating array temporary at %L", &expr
->where
);
7309 source
= build_call_expr_loc (input_location
,
7310 gfor_fndecl_in_pack
, 1, tmp
);
7311 source
= gfc_evaluate_now (source
, &argse
.pre
);
7313 /* Free the temporary. */
7314 gfc_start_block (&block
);
7315 tmp
= gfc_call_free (source
);
7316 gfc_add_expr_to_block (&block
, tmp
);
7317 stmt
= gfc_finish_block (&block
);
7319 /* Clean up if it was repacked. */
7320 gfc_init_block (&block
);
7321 tmp
= gfc_conv_array_data (argse
.expr
);
7322 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
7324 tmp
= build3_v (COND_EXPR
, tmp
, stmt
,
7325 build_empty_stmt (input_location
));
7326 gfc_add_expr_to_block (&block
, tmp
);
7327 gfc_add_block_to_block (&block
, &se
->post
);
7328 gfc_init_block (&se
->post
);
7329 gfc_add_block_to_block (&se
->post
, &block
);
7332 /* Obtain the source word length. */
7333 if (arg
->expr
->ts
.type
== BT_CHARACTER
)
7334 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
,
7335 argse
.string_length
);
7337 tmp
= fold_convert (gfc_array_index_type
,
7338 size_in_bytes (source_type
));
7340 /* Obtain the size of the array in bytes. */
7341 extent
= gfc_create_var (gfc_array_index_type
, NULL
);
7342 for (n
= 0; n
< arg
->expr
->rank
; n
++)
7345 idx
= gfc_rank_cst
[n
];
7346 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
7347 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, idx
);
7348 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, idx
);
7349 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
7350 gfc_array_index_type
, upper
, lower
);
7351 gfc_add_modify (&argse
.pre
, extent
, tmp
);
7352 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
7353 gfc_array_index_type
, extent
,
7354 gfc_index_one_node
);
7355 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
7356 gfc_array_index_type
, tmp
, source_bytes
);
7360 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
7361 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7362 gfc_add_block_to_block (&se
->post
, &argse
.post
);
7364 /* Now convert MOLD. The outputs are:
7365 mold_type = the TREE type of MOLD
7366 dest_word_len = destination word length in bytes. */
7368 mold_expr
= arg
->expr
;
7370 gfc_init_se (&argse
, NULL
);
7372 scalar_mold
= arg
->expr
->rank
== 0;
7374 if (arg
->expr
->rank
== 0)
7376 gfc_conv_expr_reference (&argse
, arg
->expr
);
7377 mold_type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
7382 gfc_init_se (&argse
, NULL
);
7383 argse
.want_pointer
= 0;
7384 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
7385 mold_type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
7388 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7389 gfc_add_block_to_block (&se
->post
, &argse
.post
);
7391 if (strcmp (expr
->value
.function
.name
, "__transfer_in_transfer") == 0)
7393 /* If this TRANSFER is nested in another TRANSFER, use a type
7394 that preserves all bits. */
7395 if (arg
->expr
->ts
.type
== BT_LOGICAL
)
7396 mold_type
= gfc_get_int_type (arg
->expr
->ts
.kind
);
7399 /* Obtain the destination word length. */
7400 switch (arg
->expr
->ts
.type
)
7403 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
, argse
.string_length
);
7404 mold_type
= gfc_get_character_type_len (arg
->expr
->ts
.kind
, tmp
);
7407 tmp
= gfc_class_vtab_size_get (argse
.expr
);
7410 tmp
= fold_convert (gfc_array_index_type
, size_in_bytes (mold_type
));
7413 dest_word_len
= gfc_create_var (gfc_array_index_type
, NULL
);
7414 gfc_add_modify (&se
->pre
, dest_word_len
, tmp
);
7416 /* Finally convert SIZE, if it is present. */
7418 size_words
= gfc_create_var (gfc_array_index_type
, NULL
);
7422 gfc_init_se (&argse
, NULL
);
7423 gfc_conv_expr_reference (&argse
, arg
->expr
);
7424 tmp
= convert (gfc_array_index_type
,
7425 build_fold_indirect_ref_loc (input_location
,
7427 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7428 gfc_add_block_to_block (&se
->post
, &argse
.post
);
7433 /* Separate array and scalar results. */
7434 if (scalar_mold
&& tmp
== NULL_TREE
)
7435 goto scalar_transfer
;
7437 size_bytes
= gfc_create_var (gfc_array_index_type
, NULL
);
7438 if (tmp
!= NULL_TREE
)
7439 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, gfc_array_index_type
,
7440 tmp
, dest_word_len
);
7444 gfc_add_modify (&se
->pre
, size_bytes
, tmp
);
7445 gfc_add_modify (&se
->pre
, size_words
,
7446 fold_build2_loc (input_location
, CEIL_DIV_EXPR
,
7447 gfc_array_index_type
,
7448 size_bytes
, dest_word_len
));
7450 /* Evaluate the bounds of the result. If the loop range exists, we have
7451 to check if it is too large. If so, we modify loop->to be consistent
7452 with min(size, size(source)). Otherwise, size is made consistent with
7453 the loop range, so that the right number of bytes is transferred.*/
7454 n
= se
->loop
->order
[0];
7455 if (se
->loop
->to
[n
] != NULL_TREE
)
7457 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
7458 se
->loop
->to
[n
], se
->loop
->from
[n
]);
7459 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
7460 tmp
, gfc_index_one_node
);
7461 tmp
= fold_build2_loc (input_location
, MIN_EXPR
, gfc_array_index_type
,
7463 gfc_add_modify (&se
->pre
, size_words
, tmp
);
7464 gfc_add_modify (&se
->pre
, size_bytes
,
7465 fold_build2_loc (input_location
, MULT_EXPR
,
7466 gfc_array_index_type
,
7467 size_words
, dest_word_len
));
7468 upper
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
7469 size_words
, se
->loop
->from
[n
]);
7470 upper
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
7471 upper
, gfc_index_one_node
);
7475 upper
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
7476 size_words
, gfc_index_one_node
);
7477 se
->loop
->from
[n
] = gfc_index_zero_node
;
7480 se
->loop
->to
[n
] = upper
;
7482 /* Build a destination descriptor, using the pointer, source, as the
7484 gfc_trans_create_temp_array (&se
->pre
, &se
->post
, se
->ss
, mold_type
,
7485 NULL_TREE
, false, true, false, &expr
->where
);
7487 /* Cast the pointer to the result. */
7488 tmp
= gfc_conv_descriptor_data_get (info
->descriptor
);
7489 tmp
= fold_convert (pvoid_type_node
, tmp
);
7491 /* Use memcpy to do the transfer. */
7493 = build_call_expr_loc (input_location
,
7494 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3, tmp
,
7495 fold_convert (pvoid_type_node
, source
),
7496 fold_convert (size_type_node
,
7497 fold_build2_loc (input_location
,
7499 gfc_array_index_type
,
7502 gfc_add_expr_to_block (&se
->pre
, tmp
);
7504 se
->expr
= info
->descriptor
;
7505 if (expr
->ts
.type
== BT_CHARACTER
)
7506 se
->string_length
= fold_convert (gfc_charlen_type_node
, dest_word_len
);
7510 /* Deal with scalar results. */
7512 extent
= fold_build2_loc (input_location
, MIN_EXPR
, gfc_array_index_type
,
7513 dest_word_len
, source_bytes
);
7514 extent
= fold_build2_loc (input_location
, MAX_EXPR
, gfc_array_index_type
,
7515 extent
, gfc_index_zero_node
);
7517 if (expr
->ts
.type
== BT_CHARACTER
)
7519 tree direct
, indirect
, free
;
7521 ptr
= convert (gfc_get_pchar_type (expr
->ts
.kind
), source
);
7522 tmpdecl
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
),
7525 /* If source is longer than the destination, use a pointer to
7526 the source directly. */
7527 gfc_init_block (&block
);
7528 gfc_add_modify (&block
, tmpdecl
, ptr
);
7529 direct
= gfc_finish_block (&block
);
7531 /* Otherwise, allocate a string with the length of the destination
7532 and copy the source into it. */
7533 gfc_init_block (&block
);
7534 tmp
= gfc_get_pchar_type (expr
->ts
.kind
);
7535 tmp
= gfc_call_malloc (&block
, tmp
, dest_word_len
);
7536 gfc_add_modify (&block
, tmpdecl
,
7537 fold_convert (TREE_TYPE (ptr
), tmp
));
7538 tmp
= build_call_expr_loc (input_location
,
7539 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3,
7540 fold_convert (pvoid_type_node
, tmpdecl
),
7541 fold_convert (pvoid_type_node
, ptr
),
7542 fold_convert (size_type_node
, extent
));
7543 gfc_add_expr_to_block (&block
, tmp
);
7544 indirect
= gfc_finish_block (&block
);
7546 /* Wrap it up with the condition. */
7547 tmp
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
,
7548 dest_word_len
, source_bytes
);
7549 tmp
= build3_v (COND_EXPR
, tmp
, direct
, indirect
);
7550 gfc_add_expr_to_block (&se
->pre
, tmp
);
7552 /* Free the temporary string, if necessary. */
7553 free
= gfc_call_free (tmpdecl
);
7554 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
7555 dest_word_len
, source_bytes
);
7556 tmp
= build3_v (COND_EXPR
, tmp
, free
, build_empty_stmt (input_location
));
7557 gfc_add_expr_to_block (&se
->post
, tmp
);
7560 se
->string_length
= fold_convert (gfc_charlen_type_node
, dest_word_len
);
7564 tmpdecl
= gfc_create_var (mold_type
, "transfer");
7566 ptr
= convert (build_pointer_type (mold_type
), source
);
7568 /* For CLASS results, allocate the needed memory first. */
7569 if (mold_expr
->ts
.type
== BT_CLASS
)
7572 cdata
= gfc_class_data_get (tmpdecl
);
7573 tmp
= gfc_call_malloc (&se
->pre
, TREE_TYPE (cdata
), dest_word_len
);
7574 gfc_add_modify (&se
->pre
, cdata
, tmp
);
7577 /* Use memcpy to do the transfer. */
7578 if (mold_expr
->ts
.type
== BT_CLASS
)
7579 tmp
= gfc_class_data_get (tmpdecl
);
7581 tmp
= gfc_build_addr_expr (NULL_TREE
, tmpdecl
);
7583 tmp
= build_call_expr_loc (input_location
,
7584 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3,
7585 fold_convert (pvoid_type_node
, tmp
),
7586 fold_convert (pvoid_type_node
, ptr
),
7587 fold_convert (size_type_node
, extent
));
7588 gfc_add_expr_to_block (&se
->pre
, tmp
);
7590 /* For CLASS results, set the _vptr. */
7591 if (mold_expr
->ts
.type
== BT_CLASS
)
7595 vptr
= gfc_class_vptr_get (tmpdecl
);
7596 vtab
= gfc_find_derived_vtab (source_expr
->ts
.u
.derived
);
7598 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
7599 gfc_add_modify (&se
->pre
, vptr
, fold_convert (TREE_TYPE (vptr
), tmp
));
7607 /* Generate a call to caf_is_present. */
7610 trans_caf_is_present (gfc_se
*se
, gfc_expr
*expr
)
7612 tree caf_reference
, caf_decl
, token
, image_index
;
7614 /* Compile the reference chain. */
7615 caf_reference
= conv_expr_ref_to_caf_ref (&se
->pre
, expr
);
7616 gcc_assert (caf_reference
!= NULL_TREE
);
7618 caf_decl
= gfc_get_tree_for_caf_expr (expr
);
7619 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
7620 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
7621 image_index
= gfc_caf_get_image_index (&se
->pre
, expr
, caf_decl
);
7622 gfc_get_caf_token_offset (se
, &token
, NULL
, caf_decl
, NULL
,
7625 return build_call_expr_loc (input_location
, gfor_fndecl_caf_is_present
,
7626 3, token
, image_index
, caf_reference
);
7630 /* Test whether this ref-chain refs this image only. */
7633 caf_this_image_ref (gfc_ref
*ref
)
7635 for ( ; ref
; ref
= ref
->next
)
7636 if (ref
->type
== REF_ARRAY
&& ref
->u
.ar
.codimen
)
7637 return ref
->u
.ar
.dimen_type
[ref
->u
.ar
.dimen
] == DIMEN_THIS_IMAGE
;
7643 /* Generate code for the ALLOCATED intrinsic.
7644 Generate inline code that directly check the address of the argument. */
7647 gfc_conv_allocated (gfc_se
*se
, gfc_expr
*expr
)
7649 gfc_actual_arglist
*arg1
;
7652 symbol_attribute caf_attr
;
7654 gfc_init_se (&arg1se
, NULL
);
7655 arg1
= expr
->value
.function
.actual
;
7657 if (arg1
->expr
->ts
.type
== BT_CLASS
)
7659 /* Make sure that class array expressions have both a _data
7660 component reference and an array reference.... */
7661 if (CLASS_DATA (arg1
->expr
)->attr
.dimension
)
7662 gfc_add_class_array_ref (arg1
->expr
);
7663 /* .... whilst scalars only need the _data component. */
7665 gfc_add_data_component (arg1
->expr
);
7668 /* When arg1 references an allocatable component in a coarray, then call
7669 the caf-library function caf_is_present (). */
7670 if (flag_coarray
== GFC_FCOARRAY_LIB
&& arg1
->expr
->expr_type
== EXPR_FUNCTION
7671 && arg1
->expr
->value
.function
.isym
7672 && arg1
->expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
7673 caf_attr
= gfc_caf_attr (arg1
->expr
->value
.function
.actual
->expr
);
7675 gfc_clear_attr (&caf_attr
);
7676 if (flag_coarray
== GFC_FCOARRAY_LIB
&& caf_attr
.codimension
7677 && !caf_this_image_ref (arg1
->expr
->value
.function
.actual
->expr
->ref
))
7678 tmp
= trans_caf_is_present (se
, arg1
->expr
->value
.function
.actual
->expr
);
7681 if (arg1
->expr
->rank
== 0)
7683 /* Allocatable scalar. */
7684 arg1se
.want_pointer
= 1;
7685 gfc_conv_expr (&arg1se
, arg1
->expr
);
7690 /* Allocatable array. */
7691 arg1se
.descriptor_only
= 1;
7692 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
7693 tmp
= gfc_conv_descriptor_data_get (arg1se
.expr
);
7696 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, tmp
,
7697 fold_convert (TREE_TYPE (tmp
), null_pointer_node
));
7700 /* Components of pointer array references sometimes come back with a pre block. */
7701 if (arg1se
.pre
.head
)
7702 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
7704 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), tmp
);
7708 /* Generate code for the ASSOCIATED intrinsic.
7709 If both POINTER and TARGET are arrays, generate a call to library function
7710 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
7711 In other cases, generate inline code that directly compare the address of
7712 POINTER with the address of TARGET. */
7715 gfc_conv_associated (gfc_se
*se
, gfc_expr
*expr
)
7717 gfc_actual_arglist
*arg1
;
7718 gfc_actual_arglist
*arg2
;
7723 tree nonzero_charlen
;
7724 tree nonzero_arraylen
;
7728 gfc_init_se (&arg1se
, NULL
);
7729 gfc_init_se (&arg2se
, NULL
);
7730 arg1
= expr
->value
.function
.actual
;
7733 /* Check whether the expression is a scalar or not; we cannot use
7734 arg1->expr->rank as it can be nonzero for proc pointers. */
7735 ss
= gfc_walk_expr (arg1
->expr
);
7736 scalar
= ss
== gfc_ss_terminator
;
7738 gfc_free_ss_chain (ss
);
7742 /* No optional target. */
7745 /* A pointer to a scalar. */
7746 arg1se
.want_pointer
= 1;
7747 gfc_conv_expr (&arg1se
, arg1
->expr
);
7748 if (arg1
->expr
->symtree
->n
.sym
->attr
.proc_pointer
7749 && arg1
->expr
->symtree
->n
.sym
->attr
.dummy
)
7750 arg1se
.expr
= build_fold_indirect_ref_loc (input_location
,
7752 if (arg1
->expr
->ts
.type
== BT_CLASS
)
7754 tmp2
= gfc_class_data_get (arg1se
.expr
);
7755 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2
)))
7756 tmp2
= gfc_conv_descriptor_data_get (tmp2
);
7763 /* A pointer to an array. */
7764 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
7765 tmp2
= gfc_conv_descriptor_data_get (arg1se
.expr
);
7767 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
7768 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
7769 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, tmp2
,
7770 fold_convert (TREE_TYPE (tmp2
), null_pointer_node
));
7775 /* An optional target. */
7776 if (arg2
->expr
->ts
.type
== BT_CLASS
)
7777 gfc_add_data_component (arg2
->expr
);
7779 nonzero_charlen
= NULL_TREE
;
7780 if (arg1
->expr
->ts
.type
== BT_CHARACTER
)
7781 nonzero_charlen
= fold_build2_loc (input_location
, NE_EXPR
,
7783 arg1
->expr
->ts
.u
.cl
->backend_decl
,
7785 (TREE_TYPE (arg1
->expr
->ts
.u
.cl
->backend_decl
)));
7788 /* A pointer to a scalar. */
7789 arg1se
.want_pointer
= 1;
7790 gfc_conv_expr (&arg1se
, arg1
->expr
);
7791 if (arg1
->expr
->symtree
->n
.sym
->attr
.proc_pointer
7792 && arg1
->expr
->symtree
->n
.sym
->attr
.dummy
)
7793 arg1se
.expr
= build_fold_indirect_ref_loc (input_location
,
7795 if (arg1
->expr
->ts
.type
== BT_CLASS
)
7796 arg1se
.expr
= gfc_class_data_get (arg1se
.expr
);
7798 arg2se
.want_pointer
= 1;
7799 gfc_conv_expr (&arg2se
, arg2
->expr
);
7800 if (arg2
->expr
->symtree
->n
.sym
->attr
.proc_pointer
7801 && arg2
->expr
->symtree
->n
.sym
->attr
.dummy
)
7802 arg2se
.expr
= build_fold_indirect_ref_loc (input_location
,
7804 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
7805 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
7806 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
7807 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
7808 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
7809 arg1se
.expr
, arg2se
.expr
);
7810 tmp2
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
7811 arg1se
.expr
, null_pointer_node
);
7812 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
7813 logical_type_node
, tmp
, tmp2
);
7817 /* An array pointer of zero length is not associated if target is
7819 arg1se
.descriptor_only
= 1;
7820 gfc_conv_expr_lhs (&arg1se
, arg1
->expr
);
7821 if (arg1
->expr
->rank
== -1)
7823 tmp
= gfc_conv_descriptor_rank (arg1se
.expr
);
7824 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
7825 TREE_TYPE (tmp
), tmp
, gfc_index_one_node
);
7828 tmp
= gfc_rank_cst
[arg1
->expr
->rank
- 1];
7829 tmp
= gfc_conv_descriptor_stride_get (arg1se
.expr
, tmp
);
7830 nonzero_arraylen
= fold_build2_loc (input_location
, NE_EXPR
,
7831 logical_type_node
, tmp
,
7832 build_int_cst (TREE_TYPE (tmp
), 0));
7834 /* A pointer to an array, call library function _gfor_associated. */
7835 arg1se
.want_pointer
= 1;
7836 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
7838 arg2se
.want_pointer
= 1;
7839 gfc_conv_expr_descriptor (&arg2se
, arg2
->expr
);
7840 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
7841 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
7842 se
->expr
= build_call_expr_loc (input_location
,
7843 gfor_fndecl_associated
, 2,
7844 arg1se
.expr
, arg2se
.expr
);
7845 se
->expr
= convert (logical_type_node
, se
->expr
);
7846 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
7847 logical_type_node
, se
->expr
,
7851 /* If target is present zero character length pointers cannot
7853 if (nonzero_charlen
!= NULL_TREE
)
7854 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
7856 se
->expr
, nonzero_charlen
);
7859 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
7863 /* Generate code for the SAME_TYPE_AS intrinsic.
7864 Generate inline code that directly checks the vindices. */
7867 gfc_conv_same_type_as (gfc_se
*se
, gfc_expr
*expr
)
7872 tree conda
= NULL_TREE
, condb
= NULL_TREE
;
7874 gfc_init_se (&se1
, NULL
);
7875 gfc_init_se (&se2
, NULL
);
7877 a
= expr
->value
.function
.actual
->expr
;
7878 b
= expr
->value
.function
.actual
->next
->expr
;
7880 if (UNLIMITED_POLY (a
))
7882 tmp
= gfc_class_vptr_get (a
->symtree
->n
.sym
->backend_decl
);
7883 conda
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
7884 tmp
, build_int_cst (TREE_TYPE (tmp
), 0));
7887 if (UNLIMITED_POLY (b
))
7889 tmp
= gfc_class_vptr_get (b
->symtree
->n
.sym
->backend_decl
);
7890 condb
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
7891 tmp
, build_int_cst (TREE_TYPE (tmp
), 0));
7894 if (a
->ts
.type
== BT_CLASS
)
7896 gfc_add_vptr_component (a
);
7897 gfc_add_hash_component (a
);
7899 else if (a
->ts
.type
== BT_DERIVED
)
7900 a
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
,
7901 a
->ts
.u
.derived
->hash_value
);
7903 if (b
->ts
.type
== BT_CLASS
)
7905 gfc_add_vptr_component (b
);
7906 gfc_add_hash_component (b
);
7908 else if (b
->ts
.type
== BT_DERIVED
)
7909 b
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
,
7910 b
->ts
.u
.derived
->hash_value
);
7912 gfc_conv_expr (&se1
, a
);
7913 gfc_conv_expr (&se2
, b
);
7915 tmp
= fold_build2_loc (input_location
, EQ_EXPR
,
7916 logical_type_node
, se1
.expr
,
7917 fold_convert (TREE_TYPE (se1
.expr
), se2
.expr
));
7920 tmp
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
7921 logical_type_node
, conda
, tmp
);
7924 tmp
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
7925 logical_type_node
, condb
, tmp
);
7927 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), tmp
);
7931 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
7934 gfc_conv_intrinsic_sc_kind (gfc_se
*se
, gfc_expr
*expr
)
7938 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
7939 se
->expr
= build_call_expr_loc (input_location
,
7940 gfor_fndecl_sc_kind
, 2, args
[0], args
[1]);
7941 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
7945 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
7948 gfc_conv_intrinsic_si_kind (gfc_se
*se
, gfc_expr
*expr
)
7952 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
7954 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
7955 type
= gfc_get_int_type (4);
7956 arg
= gfc_build_addr_expr (NULL_TREE
, fold_convert (type
, arg
));
7958 /* Convert it to the required type. */
7959 type
= gfc_typenode_for_spec (&expr
->ts
);
7960 se
->expr
= build_call_expr_loc (input_location
,
7961 gfor_fndecl_si_kind
, 1, arg
);
7962 se
->expr
= fold_convert (type
, se
->expr
);
7966 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
7969 gfc_conv_intrinsic_sr_kind (gfc_se
*se
, gfc_expr
*expr
)
7971 gfc_actual_arglist
*actual
;
7974 vec
<tree
, va_gc
> *args
= NULL
;
7976 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
7978 gfc_init_se (&argse
, se
);
7980 /* Pass a NULL pointer for an absent arg. */
7981 if (actual
->expr
== NULL
)
7982 argse
.expr
= null_pointer_node
;
7988 if (actual
->expr
->ts
.kind
!= gfc_c_int_kind
)
7990 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
7991 ts
.type
= BT_INTEGER
;
7992 ts
.kind
= gfc_c_int_kind
;
7993 gfc_convert_type (actual
->expr
, &ts
, 2);
7995 gfc_conv_expr_reference (&argse
, actual
->expr
);
7998 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7999 gfc_add_block_to_block (&se
->post
, &argse
.post
);
8000 vec_safe_push (args
, argse
.expr
);
8003 /* Convert it to the required type. */
8004 type
= gfc_typenode_for_spec (&expr
->ts
);
8005 se
->expr
= build_call_expr_loc_vec (input_location
,
8006 gfor_fndecl_sr_kind
, args
);
8007 se
->expr
= fold_convert (type
, se
->expr
);
8011 /* Generate code for TRIM (A) intrinsic function. */
8014 gfc_conv_intrinsic_trim (gfc_se
* se
, gfc_expr
* expr
)
8024 unsigned int num_args
;
8026 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
8027 args
= XALLOCAVEC (tree
, num_args
);
8029 var
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
), "pstr");
8030 addr
= gfc_build_addr_expr (ppvoid_type_node
, var
);
8031 len
= gfc_create_var (gfc_charlen_type_node
, "len");
8033 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
8034 args
[0] = gfc_build_addr_expr (NULL_TREE
, len
);
8037 if (expr
->ts
.kind
== 1)
8038 function
= gfor_fndecl_string_trim
;
8039 else if (expr
->ts
.kind
== 4)
8040 function
= gfor_fndecl_string_trim_char4
;
8044 fndecl
= build_addr (function
);
8045 tmp
= build_call_array_loc (input_location
,
8046 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
8048 gfc_add_expr_to_block (&se
->pre
, tmp
);
8050 /* Free the temporary afterwards, if necessary. */
8051 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
8052 len
, build_int_cst (TREE_TYPE (len
), 0));
8053 tmp
= gfc_call_free (var
);
8054 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
8055 gfc_add_expr_to_block (&se
->post
, tmp
);
8058 se
->string_length
= len
;
8062 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
8065 gfc_conv_intrinsic_repeat (gfc_se
* se
, gfc_expr
* expr
)
8067 tree args
[3], ncopies
, dest
, dlen
, src
, slen
, ncopies_type
;
8068 tree type
, cond
, tmp
, count
, exit_label
, n
, max
, largest
;
8070 stmtblock_t block
, body
;
8073 /* We store in charsize the size of a character. */
8074 i
= gfc_validate_kind (BT_CHARACTER
, expr
->ts
.kind
, false);
8075 size
= build_int_cst (sizetype
, gfc_character_kinds
[i
].bit_size
/ 8);
8077 /* Get the arguments. */
8078 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
8079 slen
= fold_convert (sizetype
, gfc_evaluate_now (args
[0], &se
->pre
));
8081 ncopies
= gfc_evaluate_now (args
[2], &se
->pre
);
8082 ncopies_type
= TREE_TYPE (ncopies
);
8084 /* Check that NCOPIES is not negative. */
8085 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
, ncopies
,
8086 build_int_cst (ncopies_type
, 0));
8087 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
8088 "Argument NCOPIES of REPEAT intrinsic is negative "
8089 "(its value is %ld)",
8090 fold_convert (long_integer_type_node
, ncopies
));
8092 /* If the source length is zero, any non negative value of NCOPIES
8093 is valid, and nothing happens. */
8094 n
= gfc_create_var (ncopies_type
, "ncopies");
8095 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, slen
,
8097 tmp
= fold_build3_loc (input_location
, COND_EXPR
, ncopies_type
, cond
,
8098 build_int_cst (ncopies_type
, 0), ncopies
);
8099 gfc_add_modify (&se
->pre
, n
, tmp
);
8102 /* Check that ncopies is not too large: ncopies should be less than
8103 (or equal to) MAX / slen, where MAX is the maximal integer of
8104 the gfc_charlen_type_node type. If slen == 0, we need a special
8105 case to avoid the division by zero. */
8106 max
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
, sizetype
,
8107 fold_convert (sizetype
,
8108 TYPE_MAX_VALUE (gfc_charlen_type_node
)),
8110 largest
= TYPE_PRECISION (sizetype
) > TYPE_PRECISION (ncopies_type
)
8111 ? sizetype
: ncopies_type
;
8112 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
8113 fold_convert (largest
, ncopies
),
8114 fold_convert (largest
, max
));
8115 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, slen
,
8117 cond
= fold_build3_loc (input_location
, COND_EXPR
, logical_type_node
, tmp
,
8118 logical_false_node
, cond
);
8119 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
8120 "Argument NCOPIES of REPEAT intrinsic is too large");
8122 /* Compute the destination length. */
8123 dlen
= fold_build2_loc (input_location
, MULT_EXPR
, gfc_charlen_type_node
,
8124 fold_convert (gfc_charlen_type_node
, slen
),
8125 fold_convert (gfc_charlen_type_node
, ncopies
));
8126 type
= gfc_get_character_type (expr
->ts
.kind
, expr
->ts
.u
.cl
);
8127 dest
= gfc_conv_string_tmp (se
, build_pointer_type (type
), dlen
);
8129 /* Generate the code to do the repeat operation:
8130 for (i = 0; i < ncopies; i++)
8131 memmove (dest + (i * slen * size), src, slen*size); */
8132 gfc_start_block (&block
);
8133 count
= gfc_create_var (sizetype
, "count");
8134 gfc_add_modify (&block
, count
, size_zero_node
);
8135 exit_label
= gfc_build_label_decl (NULL_TREE
);
8137 /* Start the loop body. */
8138 gfc_start_block (&body
);
8140 /* Exit the loop if count >= ncopies. */
8141 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, count
,
8142 fold_convert (sizetype
, ncopies
));
8143 tmp
= build1_v (GOTO_EXPR
, exit_label
);
8144 TREE_USED (exit_label
) = 1;
8145 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
, tmp
,
8146 build_empty_stmt (input_location
));
8147 gfc_add_expr_to_block (&body
, tmp
);
8149 /* Call memmove (dest + (i*slen*size), src, slen*size). */
8150 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, sizetype
, slen
,
8152 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, sizetype
, tmp
,
8154 tmp
= fold_build_pointer_plus_loc (input_location
,
8155 fold_convert (pvoid_type_node
, dest
), tmp
);
8156 tmp
= build_call_expr_loc (input_location
,
8157 builtin_decl_explicit (BUILT_IN_MEMMOVE
),
8159 fold_build2_loc (input_location
, MULT_EXPR
,
8160 size_type_node
, slen
, size
));
8161 gfc_add_expr_to_block (&body
, tmp
);
8163 /* Increment count. */
8164 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, sizetype
,
8165 count
, size_one_node
);
8166 gfc_add_modify (&body
, count
, tmp
);
8168 /* Build the loop. */
8169 tmp
= build1_v (LOOP_EXPR
, gfc_finish_block (&body
));
8170 gfc_add_expr_to_block (&block
, tmp
);
8172 /* Add the exit label. */
8173 tmp
= build1_v (LABEL_EXPR
, exit_label
);
8174 gfc_add_expr_to_block (&block
, tmp
);
8176 /* Finish the block. */
8177 tmp
= gfc_finish_block (&block
);
8178 gfc_add_expr_to_block (&se
->pre
, tmp
);
8180 /* Set the result value. */
8182 se
->string_length
= dlen
;
8186 /* Generate code for the IARGC intrinsic. */
8189 gfc_conv_intrinsic_iargc (gfc_se
* se
, gfc_expr
* expr
)
8195 /* Call the library function. This always returns an INTEGER(4). */
8196 fndecl
= gfor_fndecl_iargc
;
8197 tmp
= build_call_expr_loc (input_location
,
8200 /* Convert it to the required type. */
8201 type
= gfc_typenode_for_spec (&expr
->ts
);
8202 tmp
= fold_convert (type
, tmp
);
8208 /* Generate code for the KILL intrinsic. */
8211 conv_intrinsic_kill (gfc_se
*se
, gfc_expr
*expr
)
8214 tree int4_type_node
= gfc_get_int_type (4);
8218 unsigned int num_args
;
8220 num_args
= gfc_intrinsic_argument_list_length (expr
);
8221 args
= XALLOCAVEC (tree
, num_args
);
8222 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
8224 /* Convert PID to a INTEGER(4) entity. */
8225 pid
= convert (int4_type_node
, args
[0]);
8227 /* Convert SIG to a INTEGER(4) entity. */
8228 sig
= convert (int4_type_node
, args
[1]);
8230 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_kill
, 2, pid
, sig
);
8232 se
->expr
= fold_convert (TREE_TYPE (args
[0]), tmp
);
8237 conv_intrinsic_kill_sub (gfc_code
*code
)
8241 tree int4_type_node
= gfc_get_int_type (4);
8247 /* Make the function call. */
8248 gfc_init_block (&block
);
8249 gfc_init_se (&se
, NULL
);
8251 /* Convert PID to a INTEGER(4) entity. */
8252 gfc_conv_expr (&se
, code
->ext
.actual
->expr
);
8253 gfc_add_block_to_block (&block
, &se
.pre
);
8254 pid
= fold_convert (int4_type_node
, gfc_evaluate_now (se
.expr
, &block
));
8255 gfc_add_block_to_block (&block
, &se
.post
);
8257 /* Convert SIG to a INTEGER(4) entity. */
8258 gfc_conv_expr (&se
, code
->ext
.actual
->next
->expr
);
8259 gfc_add_block_to_block (&block
, &se
.pre
);
8260 sig
= fold_convert (int4_type_node
, gfc_evaluate_now (se
.expr
, &block
));
8261 gfc_add_block_to_block (&block
, &se
.post
);
8263 /* Deal with an optional STATUS. */
8264 if (code
->ext
.actual
->next
->next
->expr
)
8266 gfc_init_se (&se_stat
, NULL
);
8267 gfc_conv_expr (&se_stat
, code
->ext
.actual
->next
->next
->expr
);
8268 statp
= gfc_create_var (gfc_get_int_type (4), "_statp");
8273 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_kill_sub
, 3, pid
, sig
,
8274 statp
? gfc_build_addr_expr (NULL_TREE
, statp
) : null_pointer_node
);
8276 gfc_add_expr_to_block (&block
, tmp
);
8278 if (statp
&& statp
!= se_stat
.expr
)
8279 gfc_add_modify (&block
, se_stat
.expr
,
8280 fold_convert (TREE_TYPE (se_stat
.expr
), statp
));
8282 return gfc_finish_block (&block
);
8287 /* The loc intrinsic returns the address of its argument as
8288 gfc_index_integer_kind integer. */
8291 gfc_conv_intrinsic_loc (gfc_se
* se
, gfc_expr
* expr
)
8296 gcc_assert (!se
->ss
);
8298 arg_expr
= expr
->value
.function
.actual
->expr
;
8299 if (arg_expr
->rank
== 0)
8301 if (arg_expr
->ts
.type
== BT_CLASS
)
8302 gfc_add_data_component (arg_expr
);
8303 gfc_conv_expr_reference (se
, arg_expr
);
8306 gfc_conv_array_parameter (se
, arg_expr
, true, NULL
, NULL
, NULL
);
8307 se
->expr
= convert (gfc_get_int_type (gfc_index_integer_kind
), se
->expr
);
8309 /* Create a temporary variable for loc return value. Without this,
8310 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
8311 temp_var
= gfc_create_var (gfc_get_int_type (gfc_index_integer_kind
), NULL
);
8312 gfc_add_modify (&se
->pre
, temp_var
, se
->expr
);
8313 se
->expr
= temp_var
;
8317 /* The following routine generates code for the intrinsic
8318 functions from the ISO_C_BINDING module:
8324 conv_isocbinding_function (gfc_se
*se
, gfc_expr
*expr
)
8326 gfc_actual_arglist
*arg
= expr
->value
.function
.actual
;
8328 if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_LOC
)
8330 if (arg
->expr
->rank
== 0)
8331 gfc_conv_expr_reference (se
, arg
->expr
);
8332 else if (gfc_is_simply_contiguous (arg
->expr
, false, false))
8333 gfc_conv_array_parameter (se
, arg
->expr
, true, NULL
, NULL
, NULL
);
8336 gfc_conv_expr_descriptor (se
, arg
->expr
);
8337 se
->expr
= gfc_conv_descriptor_data_get (se
->expr
);
8340 /* TODO -- the following two lines shouldn't be necessary, but if
8341 they're removed, a bug is exposed later in the code path.
8342 This workaround was thus introduced, but will have to be
8343 removed; please see PR 35150 for details about the issue. */
8344 se
->expr
= convert (pvoid_type_node
, se
->expr
);
8345 se
->expr
= gfc_evaluate_now (se
->expr
, &se
->pre
);
8347 else if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_FUNLOC
)
8348 gfc_conv_expr_reference (se
, arg
->expr
);
8349 else if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_ASSOCIATED
)
8354 /* Build the addr_expr for the first argument. The argument is
8355 already an *address* so we don't need to set want_pointer in
8357 gfc_init_se (&arg1se
, NULL
);
8358 gfc_conv_expr (&arg1se
, arg
->expr
);
8359 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
8360 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
8362 /* See if we were given two arguments. */
8363 if (arg
->next
->expr
== NULL
)
8364 /* Only given one arg so generate a null and do a
8365 not-equal comparison against the first arg. */
8366 se
->expr
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
8368 fold_convert (TREE_TYPE (arg1se
.expr
),
8369 null_pointer_node
));
8375 /* Given two arguments so build the arg2se from second arg. */
8376 gfc_init_se (&arg2se
, NULL
);
8377 gfc_conv_expr (&arg2se
, arg
->next
->expr
);
8378 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
8379 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
8381 /* Generate test to compare that the two args are equal. */
8382 eq_expr
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
8383 arg1se
.expr
, arg2se
.expr
);
8384 /* Generate test to ensure that the first arg is not null. */
8385 not_null_expr
= fold_build2_loc (input_location
, NE_EXPR
,
8387 arg1se
.expr
, null_pointer_node
);
8389 /* Finally, the generated test must check that both arg1 is not
8390 NULL and that it is equal to the second arg. */
8391 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
8393 not_null_expr
, eq_expr
);
8401 /* The following routine generates code for the intrinsic
8402 subroutines from the ISO_C_BINDING module:
8404 * C_F_PROCPOINTER. */
8407 conv_isocbinding_subroutine (gfc_code
*code
)
8414 tree desc
, dim
, tmp
, stride
, offset
;
8415 stmtblock_t body
, block
;
8417 gfc_actual_arglist
*arg
= code
->ext
.actual
;
8419 gfc_init_se (&se
, NULL
);
8420 gfc_init_se (&cptrse
, NULL
);
8421 gfc_conv_expr (&cptrse
, arg
->expr
);
8422 gfc_add_block_to_block (&se
.pre
, &cptrse
.pre
);
8423 gfc_add_block_to_block (&se
.post
, &cptrse
.post
);
8425 gfc_init_se (&fptrse
, NULL
);
8426 if (arg
->next
->expr
->rank
== 0)
8428 fptrse
.want_pointer
= 1;
8429 gfc_conv_expr (&fptrse
, arg
->next
->expr
);
8430 gfc_add_block_to_block (&se
.pre
, &fptrse
.pre
);
8431 gfc_add_block_to_block (&se
.post
, &fptrse
.post
);
8432 if (arg
->next
->expr
->symtree
->n
.sym
->attr
.proc_pointer
8433 && arg
->next
->expr
->symtree
->n
.sym
->attr
.dummy
)
8434 fptrse
.expr
= build_fold_indirect_ref_loc (input_location
,
8436 se
.expr
= fold_build2_loc (input_location
, MODIFY_EXPR
,
8437 TREE_TYPE (fptrse
.expr
),
8439 fold_convert (TREE_TYPE (fptrse
.expr
),
8441 gfc_add_expr_to_block (&se
.pre
, se
.expr
);
8442 gfc_add_block_to_block (&se
.pre
, &se
.post
);
8443 return gfc_finish_block (&se
.pre
);
8446 gfc_start_block (&block
);
8448 /* Get the descriptor of the Fortran pointer. */
8449 fptrse
.descriptor_only
= 1;
8450 gfc_conv_expr_descriptor (&fptrse
, arg
->next
->expr
);
8451 gfc_add_block_to_block (&block
, &fptrse
.pre
);
8454 /* Set the span field. */
8455 tmp
= TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc
)));
8456 tmp
= fold_convert (gfc_array_index_type
, tmp
);
8457 gfc_conv_descriptor_span_set (&block
, desc
, tmp
);
8459 /* Set data value, dtype, and offset. */
8460 tmp
= GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc
));
8461 gfc_conv_descriptor_data_set (&block
, desc
, fold_convert (tmp
, cptrse
.expr
));
8462 gfc_add_modify (&block
, gfc_conv_descriptor_dtype (desc
),
8463 gfc_get_dtype (TREE_TYPE (desc
)));
8465 /* Start scalarization of the bounds, using the shape argument. */
8467 shape_ss
= gfc_walk_expr (arg
->next
->next
->expr
);
8468 gcc_assert (shape_ss
!= gfc_ss_terminator
);
8469 gfc_init_se (&shapese
, NULL
);
8471 gfc_init_loopinfo (&loop
);
8472 gfc_add_ss_to_loop (&loop
, shape_ss
);
8473 gfc_conv_ss_startstride (&loop
);
8474 gfc_conv_loop_setup (&loop
, &arg
->next
->expr
->where
);
8475 gfc_mark_ss_chain_used (shape_ss
, 1);
8477 gfc_copy_loopinfo_to_se (&shapese
, &loop
);
8478 shapese
.ss
= shape_ss
;
8480 stride
= gfc_create_var (gfc_array_index_type
, "stride");
8481 offset
= gfc_create_var (gfc_array_index_type
, "offset");
8482 gfc_add_modify (&block
, stride
, gfc_index_one_node
);
8483 gfc_add_modify (&block
, offset
, gfc_index_zero_node
);
8486 gfc_start_scalarized_body (&loop
, &body
);
8488 dim
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
8489 loop
.loopvar
[0], loop
.from
[0]);
8491 /* Set bounds and stride. */
8492 gfc_conv_descriptor_lbound_set (&body
, desc
, dim
, gfc_index_one_node
);
8493 gfc_conv_descriptor_stride_set (&body
, desc
, dim
, stride
);
8495 gfc_conv_expr (&shapese
, arg
->next
->next
->expr
);
8496 gfc_add_block_to_block (&body
, &shapese
.pre
);
8497 gfc_conv_descriptor_ubound_set (&body
, desc
, dim
, shapese
.expr
);
8498 gfc_add_block_to_block (&body
, &shapese
.post
);
8500 /* Calculate offset. */
8501 gfc_add_modify (&body
, offset
,
8502 fold_build2_loc (input_location
, PLUS_EXPR
,
8503 gfc_array_index_type
, offset
, stride
));
8504 /* Update stride. */
8505 gfc_add_modify (&body
, stride
,
8506 fold_build2_loc (input_location
, MULT_EXPR
,
8507 gfc_array_index_type
, stride
,
8508 fold_convert (gfc_array_index_type
,
8510 /* Finish scalarization loop. */
8511 gfc_trans_scalarizing_loops (&loop
, &body
);
8512 gfc_add_block_to_block (&block
, &loop
.pre
);
8513 gfc_add_block_to_block (&block
, &loop
.post
);
8514 gfc_add_block_to_block (&block
, &fptrse
.post
);
8515 gfc_cleanup_loop (&loop
);
8517 gfc_add_modify (&block
, offset
,
8518 fold_build1_loc (input_location
, NEGATE_EXPR
,
8519 gfc_array_index_type
, offset
));
8520 gfc_conv_descriptor_offset_set (&block
, desc
, offset
);
8522 gfc_add_expr_to_block (&se
.pre
, gfc_finish_block (&block
));
8523 gfc_add_block_to_block (&se
.pre
, &se
.post
);
8524 return gfc_finish_block (&se
.pre
);
8528 /* Save and restore floating-point state. */
8531 gfc_save_fp_state (stmtblock_t
*block
)
8533 tree type
, fpstate
, tmp
;
8535 type
= build_array_type (char_type_node
,
8536 build_range_type (size_type_node
, size_zero_node
,
8537 size_int (GFC_FPE_STATE_BUFFER_SIZE
)));
8538 fpstate
= gfc_create_var (type
, "fpstate");
8539 fpstate
= gfc_build_addr_expr (pvoid_type_node
, fpstate
);
8541 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_ieee_procedure_entry
,
8543 gfc_add_expr_to_block (block
, tmp
);
8550 gfc_restore_fp_state (stmtblock_t
*block
, tree fpstate
)
8554 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_ieee_procedure_exit
,
8556 gfc_add_expr_to_block (block
, tmp
);
8560 /* Generate code for arguments of IEEE functions. */
8563 conv_ieee_function_args (gfc_se
*se
, gfc_expr
*expr
, tree
*argarray
,
8566 gfc_actual_arglist
*actual
;
8571 actual
= expr
->value
.function
.actual
;
8572 for (arg
= 0; arg
< nargs
; arg
++, actual
= actual
->next
)
8574 gcc_assert (actual
);
8577 gfc_init_se (&argse
, se
);
8578 gfc_conv_expr_val (&argse
, e
);
8580 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8581 gfc_add_block_to_block (&se
->post
, &argse
.post
);
8582 argarray
[arg
] = argse
.expr
;
8587 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
8588 and IEEE_UNORDERED, which translate directly to GCC type-generic
8592 conv_intrinsic_ieee_builtin (gfc_se
* se
, gfc_expr
* expr
,
8593 enum built_in_function code
, int nargs
)
8596 gcc_assert ((unsigned) nargs
<= sizeof(args
)/sizeof(args
[0]));
8598 conv_ieee_function_args (se
, expr
, args
, nargs
);
8599 se
->expr
= build_call_expr_loc_array (input_location
,
8600 builtin_decl_explicit (code
),
8602 STRIP_TYPE_NOPS (se
->expr
);
8603 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
8607 /* Generate code for IEEE_IS_NORMAL intrinsic:
8608 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
8611 conv_intrinsic_ieee_is_normal (gfc_se
* se
, gfc_expr
* expr
)
8613 tree arg
, isnormal
, iszero
;
8615 /* Convert arg, evaluate it only once. */
8616 conv_ieee_function_args (se
, expr
, &arg
, 1);
8617 arg
= gfc_evaluate_now (arg
, &se
->pre
);
8619 isnormal
= build_call_expr_loc (input_location
,
8620 builtin_decl_explicit (BUILT_IN_ISNORMAL
),
8622 iszero
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, arg
,
8623 build_real_from_int_cst (TREE_TYPE (arg
),
8624 integer_zero_node
));
8625 se
->expr
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
8626 logical_type_node
, isnormal
, iszero
);
8627 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
8631 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
8632 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
8635 conv_intrinsic_ieee_is_negative (gfc_se
* se
, gfc_expr
* expr
)
8637 tree arg
, signbit
, isnan
;
8639 /* Convert arg, evaluate it only once. */
8640 conv_ieee_function_args (se
, expr
, &arg
, 1);
8641 arg
= gfc_evaluate_now (arg
, &se
->pre
);
8643 isnan
= build_call_expr_loc (input_location
,
8644 builtin_decl_explicit (BUILT_IN_ISNAN
),
8646 STRIP_TYPE_NOPS (isnan
);
8648 signbit
= build_call_expr_loc (input_location
,
8649 builtin_decl_explicit (BUILT_IN_SIGNBIT
),
8651 signbit
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
8652 signbit
, integer_zero_node
);
8654 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
8655 logical_type_node
, signbit
,
8656 fold_build1_loc (input_location
, TRUTH_NOT_EXPR
,
8657 TREE_TYPE(isnan
), isnan
));
8659 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
8663 /* Generate code for IEEE_LOGB and IEEE_RINT. */
8666 conv_intrinsic_ieee_logb_rint (gfc_se
* se
, gfc_expr
* expr
,
8667 enum built_in_function code
)
8669 tree arg
, decl
, call
, fpstate
;
8672 conv_ieee_function_args (se
, expr
, &arg
, 1);
8673 argprec
= TYPE_PRECISION (TREE_TYPE (arg
));
8674 decl
= builtin_decl_for_precision (code
, argprec
);
8676 /* Save floating-point state. */
8677 fpstate
= gfc_save_fp_state (&se
->pre
);
8679 /* Make the function call. */
8680 call
= build_call_expr_loc (input_location
, decl
, 1, arg
);
8681 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), call
);
8683 /* Restore floating-point state. */
8684 gfc_restore_fp_state (&se
->post
, fpstate
);
8688 /* Generate code for IEEE_REM. */
8691 conv_intrinsic_ieee_rem (gfc_se
* se
, gfc_expr
* expr
)
8693 tree args
[2], decl
, call
, fpstate
;
8696 conv_ieee_function_args (se
, expr
, args
, 2);
8698 /* If arguments have unequal size, convert them to the larger. */
8699 if (TYPE_PRECISION (TREE_TYPE (args
[0]))
8700 > TYPE_PRECISION (TREE_TYPE (args
[1])))
8701 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
8702 else if (TYPE_PRECISION (TREE_TYPE (args
[1]))
8703 > TYPE_PRECISION (TREE_TYPE (args
[0])))
8704 args
[0] = fold_convert (TREE_TYPE (args
[1]), args
[0]);
8706 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
8707 decl
= builtin_decl_for_precision (BUILT_IN_REMAINDER
, argprec
);
8709 /* Save floating-point state. */
8710 fpstate
= gfc_save_fp_state (&se
->pre
);
8712 /* Make the function call. */
8713 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
8714 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
8716 /* Restore floating-point state. */
8717 gfc_restore_fp_state (&se
->post
, fpstate
);
8721 /* Generate code for IEEE_NEXT_AFTER. */
8724 conv_intrinsic_ieee_next_after (gfc_se
* se
, gfc_expr
* expr
)
8726 tree args
[2], decl
, call
, fpstate
;
8729 conv_ieee_function_args (se
, expr
, args
, 2);
8731 /* Result has the characteristics of first argument. */
8732 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
8733 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
8734 decl
= builtin_decl_for_precision (BUILT_IN_NEXTAFTER
, argprec
);
8736 /* Save floating-point state. */
8737 fpstate
= gfc_save_fp_state (&se
->pre
);
8739 /* Make the function call. */
8740 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
8741 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
8743 /* Restore floating-point state. */
8744 gfc_restore_fp_state (&se
->post
, fpstate
);
8748 /* Generate code for IEEE_SCALB. */
8751 conv_intrinsic_ieee_scalb (gfc_se
* se
, gfc_expr
* expr
)
8753 tree args
[2], decl
, call
, huge
, type
;
8756 conv_ieee_function_args (se
, expr
, args
, 2);
8758 /* Result has the characteristics of first argument. */
8759 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
8760 decl
= builtin_decl_for_precision (BUILT_IN_SCALBN
, argprec
);
8762 if (TYPE_PRECISION (TREE_TYPE (args
[1])) > TYPE_PRECISION (integer_type_node
))
8764 /* We need to fold the integer into the range of a C int. */
8765 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
8766 type
= TREE_TYPE (args
[1]);
8768 n
= gfc_validate_kind (BT_INTEGER
, gfc_c_int_kind
, false);
8769 huge
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
,
8771 huge
= fold_convert (type
, huge
);
8772 args
[1] = fold_build2_loc (input_location
, MIN_EXPR
, type
, args
[1],
8774 args
[1] = fold_build2_loc (input_location
, MAX_EXPR
, type
, args
[1],
8775 fold_build1_loc (input_location
, NEGATE_EXPR
,
8779 args
[1] = fold_convert (integer_type_node
, args
[1]);
8781 /* Make the function call. */
8782 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
8783 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
8787 /* Generate code for IEEE_COPY_SIGN. */
8790 conv_intrinsic_ieee_copy_sign (gfc_se
* se
, gfc_expr
* expr
)
8792 tree args
[2], decl
, sign
;
8795 conv_ieee_function_args (se
, expr
, args
, 2);
8797 /* Get the sign of the second argument. */
8798 sign
= build_call_expr_loc (input_location
,
8799 builtin_decl_explicit (BUILT_IN_SIGNBIT
),
8801 sign
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
8802 sign
, integer_zero_node
);
8804 /* Create a value of one, with the right sign. */
8805 sign
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
8807 fold_build1_loc (input_location
, NEGATE_EXPR
,
8811 args
[1] = fold_convert (TREE_TYPE (args
[0]), sign
);
8813 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
8814 decl
= builtin_decl_for_precision (BUILT_IN_COPYSIGN
, argprec
);
8816 se
->expr
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
8820 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
8824 gfc_conv_ieee_arithmetic_function (gfc_se
* se
, gfc_expr
* expr
)
8826 const char *name
= expr
->value
.function
.name
;
8828 #define STARTS_WITH(A,B) (strncmp((A), (B), strlen(B)) == 0)
8830 if (STARTS_WITH (name
, "_gfortran_ieee_is_nan"))
8831 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISNAN
, 1);
8832 else if (STARTS_WITH (name
, "_gfortran_ieee_is_finite"))
8833 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISFINITE
, 1);
8834 else if (STARTS_WITH (name
, "_gfortran_ieee_unordered"))
8835 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISUNORDERED
, 2);
8836 else if (STARTS_WITH (name
, "_gfortran_ieee_is_normal"))
8837 conv_intrinsic_ieee_is_normal (se
, expr
);
8838 else if (STARTS_WITH (name
, "_gfortran_ieee_is_negative"))
8839 conv_intrinsic_ieee_is_negative (se
, expr
);
8840 else if (STARTS_WITH (name
, "_gfortran_ieee_copy_sign"))
8841 conv_intrinsic_ieee_copy_sign (se
, expr
);
8842 else if (STARTS_WITH (name
, "_gfortran_ieee_scalb"))
8843 conv_intrinsic_ieee_scalb (se
, expr
);
8844 else if (STARTS_WITH (name
, "_gfortran_ieee_next_after"))
8845 conv_intrinsic_ieee_next_after (se
, expr
);
8846 else if (STARTS_WITH (name
, "_gfortran_ieee_rem"))
8847 conv_intrinsic_ieee_rem (se
, expr
);
8848 else if (STARTS_WITH (name
, "_gfortran_ieee_logb"))
8849 conv_intrinsic_ieee_logb_rint (se
, expr
, BUILT_IN_LOGB
);
8850 else if (STARTS_WITH (name
, "_gfortran_ieee_rint"))
8851 conv_intrinsic_ieee_logb_rint (se
, expr
, BUILT_IN_RINT
);
8853 /* It is not among the functions we translate directly. We return
8854 false, so a library function call is emitted. */
8863 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
8866 gfc_conv_intrinsic_malloc (gfc_se
* se
, gfc_expr
* expr
)
8868 tree arg
, res
, restype
;
8870 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
8871 arg
= fold_convert (size_type_node
, arg
);
8872 res
= build_call_expr_loc (input_location
,
8873 builtin_decl_explicit (BUILT_IN_MALLOC
), 1, arg
);
8874 restype
= gfc_typenode_for_spec (&expr
->ts
);
8875 se
->expr
= fold_convert (restype
, res
);
8879 /* Generate code for an intrinsic function. Some map directly to library
8880 calls, others get special handling. In some cases the name of the function
8881 used depends on the type specifiers. */
8884 gfc_conv_intrinsic_function (gfc_se
* se
, gfc_expr
* expr
)
8890 name
= &expr
->value
.function
.name
[2];
8894 lib
= gfc_is_intrinsic_libcall (expr
);
8898 se
->ignore_optional
= 1;
8900 switch (expr
->value
.function
.isym
->id
)
8902 case GFC_ISYM_EOSHIFT
:
8904 case GFC_ISYM_RESHAPE
:
8905 /* For all of those the first argument specifies the type and the
8906 third is optional. */
8907 conv_generic_with_optional_char_arg (se
, expr
, 1, 3);
8910 case GFC_ISYM_MINLOC
:
8911 gfc_conv_intrinsic_minmaxloc (se
, expr
, LT_EXPR
);
8914 case GFC_ISYM_MAXLOC
:
8915 gfc_conv_intrinsic_minmaxloc (se
, expr
, GT_EXPR
);
8918 case GFC_ISYM_SHAPE
:
8919 gfc_conv_intrinsic_shape (se
, expr
);
8923 gfc_conv_intrinsic_funcall (se
, expr
);
8931 switch (expr
->value
.function
.isym
->id
)
8936 case GFC_ISYM_REPEAT
:
8937 gfc_conv_intrinsic_repeat (se
, expr
);
8941 gfc_conv_intrinsic_trim (se
, expr
);
8944 case GFC_ISYM_SC_KIND
:
8945 gfc_conv_intrinsic_sc_kind (se
, expr
);
8948 case GFC_ISYM_SI_KIND
:
8949 gfc_conv_intrinsic_si_kind (se
, expr
);
8952 case GFC_ISYM_SR_KIND
:
8953 gfc_conv_intrinsic_sr_kind (se
, expr
);
8956 case GFC_ISYM_EXPONENT
:
8957 gfc_conv_intrinsic_exponent (se
, expr
);
8961 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
8963 fndecl
= gfor_fndecl_string_scan
;
8965 fndecl
= gfor_fndecl_string_scan_char4
;
8969 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
8972 case GFC_ISYM_VERIFY
:
8973 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
8975 fndecl
= gfor_fndecl_string_verify
;
8977 fndecl
= gfor_fndecl_string_verify_char4
;
8981 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
8984 case GFC_ISYM_ALLOCATED
:
8985 gfc_conv_allocated (se
, expr
);
8988 case GFC_ISYM_ASSOCIATED
:
8989 gfc_conv_associated(se
, expr
);
8992 case GFC_ISYM_SAME_TYPE_AS
:
8993 gfc_conv_same_type_as (se
, expr
);
8997 gfc_conv_intrinsic_abs (se
, expr
);
9000 case GFC_ISYM_ADJUSTL
:
9001 if (expr
->ts
.kind
== 1)
9002 fndecl
= gfor_fndecl_adjustl
;
9003 else if (expr
->ts
.kind
== 4)
9004 fndecl
= gfor_fndecl_adjustl_char4
;
9008 gfc_conv_intrinsic_adjust (se
, expr
, fndecl
);
9011 case GFC_ISYM_ADJUSTR
:
9012 if (expr
->ts
.kind
== 1)
9013 fndecl
= gfor_fndecl_adjustr
;
9014 else if (expr
->ts
.kind
== 4)
9015 fndecl
= gfor_fndecl_adjustr_char4
;
9019 gfc_conv_intrinsic_adjust (se
, expr
, fndecl
);
9022 case GFC_ISYM_AIMAG
:
9023 gfc_conv_intrinsic_imagpart (se
, expr
);
9027 gfc_conv_intrinsic_aint (se
, expr
, RND_TRUNC
);
9031 gfc_conv_intrinsic_anyall (se
, expr
, EQ_EXPR
);
9034 case GFC_ISYM_ANINT
:
9035 gfc_conv_intrinsic_aint (se
, expr
, RND_ROUND
);
9039 gfc_conv_intrinsic_bitop (se
, expr
, BIT_AND_EXPR
);
9043 gfc_conv_intrinsic_anyall (se
, expr
, NE_EXPR
);
9046 case GFC_ISYM_BTEST
:
9047 gfc_conv_intrinsic_btest (se
, expr
);
9051 gfc_conv_intrinsic_bitcomp (se
, expr
, GE_EXPR
);
9055 gfc_conv_intrinsic_bitcomp (se
, expr
, GT_EXPR
);
9059 gfc_conv_intrinsic_bitcomp (se
, expr
, LE_EXPR
);
9063 gfc_conv_intrinsic_bitcomp (se
, expr
, LT_EXPR
);
9066 case GFC_ISYM_C_ASSOCIATED
:
9067 case GFC_ISYM_C_FUNLOC
:
9068 case GFC_ISYM_C_LOC
:
9069 conv_isocbinding_function (se
, expr
);
9072 case GFC_ISYM_ACHAR
:
9074 gfc_conv_intrinsic_char (se
, expr
);
9077 case GFC_ISYM_CONVERSION
:
9079 case GFC_ISYM_LOGICAL
:
9081 gfc_conv_intrinsic_conversion (se
, expr
);
9084 /* Integer conversions are handled separately to make sure we get the
9085 correct rounding mode. */
9090 gfc_conv_intrinsic_int (se
, expr
, RND_TRUNC
);
9094 gfc_conv_intrinsic_int (se
, expr
, RND_ROUND
);
9097 case GFC_ISYM_CEILING
:
9098 gfc_conv_intrinsic_int (se
, expr
, RND_CEIL
);
9101 case GFC_ISYM_FLOOR
:
9102 gfc_conv_intrinsic_int (se
, expr
, RND_FLOOR
);
9106 gfc_conv_intrinsic_mod (se
, expr
, 0);
9109 case GFC_ISYM_MODULO
:
9110 gfc_conv_intrinsic_mod (se
, expr
, 1);
9113 case GFC_ISYM_CAF_GET
:
9114 gfc_conv_intrinsic_caf_get (se
, expr
, NULL_TREE
, NULL_TREE
, NULL_TREE
,
9118 case GFC_ISYM_CMPLX
:
9119 gfc_conv_intrinsic_cmplx (se
, expr
, name
[5] == '1');
9122 case GFC_ISYM_COMMAND_ARGUMENT_COUNT
:
9123 gfc_conv_intrinsic_iargc (se
, expr
);
9126 case GFC_ISYM_COMPLEX
:
9127 gfc_conv_intrinsic_cmplx (se
, expr
, 1);
9130 case GFC_ISYM_CONJG
:
9131 gfc_conv_intrinsic_conjg (se
, expr
);
9134 case GFC_ISYM_COUNT
:
9135 gfc_conv_intrinsic_count (se
, expr
);
9138 case GFC_ISYM_CTIME
:
9139 gfc_conv_intrinsic_ctime (se
, expr
);
9143 gfc_conv_intrinsic_dim (se
, expr
);
9146 case GFC_ISYM_DOT_PRODUCT
:
9147 gfc_conv_intrinsic_dot_product (se
, expr
);
9150 case GFC_ISYM_DPROD
:
9151 gfc_conv_intrinsic_dprod (se
, expr
);
9154 case GFC_ISYM_DSHIFTL
:
9155 gfc_conv_intrinsic_dshift (se
, expr
, true);
9158 case GFC_ISYM_DSHIFTR
:
9159 gfc_conv_intrinsic_dshift (se
, expr
, false);
9162 case GFC_ISYM_FDATE
:
9163 gfc_conv_intrinsic_fdate (se
, expr
);
9166 case GFC_ISYM_FRACTION
:
9167 gfc_conv_intrinsic_fraction (se
, expr
);
9171 gfc_conv_intrinsic_arith (se
, expr
, BIT_AND_EXPR
, false);
9175 gfc_conv_intrinsic_bitop (se
, expr
, BIT_AND_EXPR
);
9179 gfc_conv_intrinsic_arith (se
, expr
, BIT_IOR_EXPR
, false);
9182 case GFC_ISYM_IBCLR
:
9183 gfc_conv_intrinsic_singlebitop (se
, expr
, 0);
9186 case GFC_ISYM_IBITS
:
9187 gfc_conv_intrinsic_ibits (se
, expr
);
9190 case GFC_ISYM_IBSET
:
9191 gfc_conv_intrinsic_singlebitop (se
, expr
, 1);
9194 case GFC_ISYM_IACHAR
:
9195 case GFC_ISYM_ICHAR
:
9196 /* We assume ASCII character sequence. */
9197 gfc_conv_intrinsic_ichar (se
, expr
);
9200 case GFC_ISYM_IARGC
:
9201 gfc_conv_intrinsic_iargc (se
, expr
);
9205 gfc_conv_intrinsic_bitop (se
, expr
, BIT_XOR_EXPR
);
9208 case GFC_ISYM_INDEX
:
9209 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
9211 fndecl
= gfor_fndecl_string_index
;
9213 fndecl
= gfor_fndecl_string_index_char4
;
9217 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
9221 gfc_conv_intrinsic_bitop (se
, expr
, BIT_IOR_EXPR
);
9224 case GFC_ISYM_IPARITY
:
9225 gfc_conv_intrinsic_arith (se
, expr
, BIT_XOR_EXPR
, false);
9228 case GFC_ISYM_IS_IOSTAT_END
:
9229 gfc_conv_has_intvalue (se
, expr
, LIBERROR_END
);
9232 case GFC_ISYM_IS_IOSTAT_EOR
:
9233 gfc_conv_has_intvalue (se
, expr
, LIBERROR_EOR
);
9236 case GFC_ISYM_ISNAN
:
9237 gfc_conv_intrinsic_isnan (se
, expr
);
9241 conv_intrinsic_kill (se
, expr
);
9244 case GFC_ISYM_LSHIFT
:
9245 gfc_conv_intrinsic_shift (se
, expr
, false, false);
9248 case GFC_ISYM_RSHIFT
:
9249 gfc_conv_intrinsic_shift (se
, expr
, true, true);
9252 case GFC_ISYM_SHIFTA
:
9253 gfc_conv_intrinsic_shift (se
, expr
, true, true);
9256 case GFC_ISYM_SHIFTL
:
9257 gfc_conv_intrinsic_shift (se
, expr
, false, false);
9260 case GFC_ISYM_SHIFTR
:
9261 gfc_conv_intrinsic_shift (se
, expr
, true, false);
9264 case GFC_ISYM_ISHFT
:
9265 gfc_conv_intrinsic_ishft (se
, expr
);
9268 case GFC_ISYM_ISHFTC
:
9269 gfc_conv_intrinsic_ishftc (se
, expr
);
9272 case GFC_ISYM_LEADZ
:
9273 gfc_conv_intrinsic_leadz (se
, expr
);
9276 case GFC_ISYM_TRAILZ
:
9277 gfc_conv_intrinsic_trailz (se
, expr
);
9280 case GFC_ISYM_POPCNT
:
9281 gfc_conv_intrinsic_popcnt_poppar (se
, expr
, 0);
9284 case GFC_ISYM_POPPAR
:
9285 gfc_conv_intrinsic_popcnt_poppar (se
, expr
, 1);
9288 case GFC_ISYM_LBOUND
:
9289 gfc_conv_intrinsic_bound (se
, expr
, 0);
9292 case GFC_ISYM_LCOBOUND
:
9293 conv_intrinsic_cobound (se
, expr
);
9296 case GFC_ISYM_TRANSPOSE
:
9297 /* The scalarizer has already been set up for reversed dimension access
9298 order ; now we just get the argument value normally. */
9299 gfc_conv_expr (se
, expr
->value
.function
.actual
->expr
);
9303 gfc_conv_intrinsic_len (se
, expr
);
9306 case GFC_ISYM_LEN_TRIM
:
9307 gfc_conv_intrinsic_len_trim (se
, expr
);
9311 gfc_conv_intrinsic_strcmp (se
, expr
, GE_EXPR
);
9315 gfc_conv_intrinsic_strcmp (se
, expr
, GT_EXPR
);
9319 gfc_conv_intrinsic_strcmp (se
, expr
, LE_EXPR
);
9323 gfc_conv_intrinsic_strcmp (se
, expr
, LT_EXPR
);
9326 case GFC_ISYM_MALLOC
:
9327 gfc_conv_intrinsic_malloc (se
, expr
);
9330 case GFC_ISYM_MASKL
:
9331 gfc_conv_intrinsic_mask (se
, expr
, 1);
9334 case GFC_ISYM_MASKR
:
9335 gfc_conv_intrinsic_mask (se
, expr
, 0);
9339 if (expr
->ts
.type
== BT_CHARACTER
)
9340 gfc_conv_intrinsic_minmax_char (se
, expr
, 1);
9342 gfc_conv_intrinsic_minmax (se
, expr
, GT_EXPR
);
9345 case GFC_ISYM_MAXLOC
:
9346 gfc_conv_intrinsic_minmaxloc (se
, expr
, GT_EXPR
);
9349 case GFC_ISYM_MAXVAL
:
9350 gfc_conv_intrinsic_minmaxval (se
, expr
, GT_EXPR
);
9353 case GFC_ISYM_MERGE
:
9354 gfc_conv_intrinsic_merge (se
, expr
);
9357 case GFC_ISYM_MERGE_BITS
:
9358 gfc_conv_intrinsic_merge_bits (se
, expr
);
9362 if (expr
->ts
.type
== BT_CHARACTER
)
9363 gfc_conv_intrinsic_minmax_char (se
, expr
, -1);
9365 gfc_conv_intrinsic_minmax (se
, expr
, LT_EXPR
);
9368 case GFC_ISYM_MINLOC
:
9369 gfc_conv_intrinsic_minmaxloc (se
, expr
, LT_EXPR
);
9372 case GFC_ISYM_MINVAL
:
9373 gfc_conv_intrinsic_minmaxval (se
, expr
, LT_EXPR
);
9376 case GFC_ISYM_NEAREST
:
9377 gfc_conv_intrinsic_nearest (se
, expr
);
9380 case GFC_ISYM_NORM2
:
9381 gfc_conv_intrinsic_arith (se
, expr
, PLUS_EXPR
, true);
9385 gfc_conv_intrinsic_not (se
, expr
);
9389 gfc_conv_intrinsic_bitop (se
, expr
, BIT_IOR_EXPR
);
9392 case GFC_ISYM_PARITY
:
9393 gfc_conv_intrinsic_arith (se
, expr
, NE_EXPR
, false);
9396 case GFC_ISYM_PRESENT
:
9397 gfc_conv_intrinsic_present (se
, expr
);
9400 case GFC_ISYM_PRODUCT
:
9401 gfc_conv_intrinsic_arith (se
, expr
, MULT_EXPR
, false);
9405 gfc_conv_intrinsic_rank (se
, expr
);
9408 case GFC_ISYM_RRSPACING
:
9409 gfc_conv_intrinsic_rrspacing (se
, expr
);
9412 case GFC_ISYM_SET_EXPONENT
:
9413 gfc_conv_intrinsic_set_exponent (se
, expr
);
9416 case GFC_ISYM_SCALE
:
9417 gfc_conv_intrinsic_scale (se
, expr
);
9421 gfc_conv_intrinsic_sign (se
, expr
);
9425 gfc_conv_intrinsic_size (se
, expr
);
9428 case GFC_ISYM_SIZEOF
:
9429 case GFC_ISYM_C_SIZEOF
:
9430 gfc_conv_intrinsic_sizeof (se
, expr
);
9433 case GFC_ISYM_STORAGE_SIZE
:
9434 gfc_conv_intrinsic_storage_size (se
, expr
);
9437 case GFC_ISYM_SPACING
:
9438 gfc_conv_intrinsic_spacing (se
, expr
);
9441 case GFC_ISYM_STRIDE
:
9442 conv_intrinsic_stride (se
, expr
);
9446 gfc_conv_intrinsic_arith (se
, expr
, PLUS_EXPR
, false);
9449 case GFC_ISYM_TEAM_NUMBER
:
9450 conv_intrinsic_team_number (se
, expr
);
9453 case GFC_ISYM_TRANSFER
:
9454 if (se
->ss
&& se
->ss
->info
->useflags
)
9455 /* Access the previously obtained result. */
9456 gfc_conv_tmp_array_ref (se
);
9458 gfc_conv_intrinsic_transfer (se
, expr
);
9461 case GFC_ISYM_TTYNAM
:
9462 gfc_conv_intrinsic_ttynam (se
, expr
);
9465 case GFC_ISYM_UBOUND
:
9466 gfc_conv_intrinsic_bound (se
, expr
, 1);
9469 case GFC_ISYM_UCOBOUND
:
9470 conv_intrinsic_cobound (se
, expr
);
9474 gfc_conv_intrinsic_bitop (se
, expr
, BIT_XOR_EXPR
);
9478 gfc_conv_intrinsic_loc (se
, expr
);
9481 case GFC_ISYM_THIS_IMAGE
:
9482 /* For num_images() == 1, handle as LCOBOUND. */
9483 if (expr
->value
.function
.actual
->expr
9484 && flag_coarray
== GFC_FCOARRAY_SINGLE
)
9485 conv_intrinsic_cobound (se
, expr
);
9487 trans_this_image (se
, expr
);
9490 case GFC_ISYM_IMAGE_INDEX
:
9491 trans_image_index (se
, expr
);
9494 case GFC_ISYM_IMAGE_STATUS
:
9495 conv_intrinsic_image_status (se
, expr
);
9498 case GFC_ISYM_NUM_IMAGES
:
9499 trans_num_images (se
, expr
);
9502 case GFC_ISYM_ACCESS
:
9503 case GFC_ISYM_CHDIR
:
9504 case GFC_ISYM_CHMOD
:
9505 case GFC_ISYM_DTIME
:
9506 case GFC_ISYM_ETIME
:
9507 case GFC_ISYM_EXTENDS_TYPE_OF
:
9509 case GFC_ISYM_FGETC
:
9512 case GFC_ISYM_FPUTC
:
9513 case GFC_ISYM_FSTAT
:
9514 case GFC_ISYM_FTELL
:
9515 case GFC_ISYM_GETCWD
:
9516 case GFC_ISYM_GETGID
:
9517 case GFC_ISYM_GETPID
:
9518 case GFC_ISYM_GETUID
:
9519 case GFC_ISYM_HOSTNM
:
9520 case GFC_ISYM_IERRNO
:
9521 case GFC_ISYM_IRAND
:
9522 case GFC_ISYM_ISATTY
:
9525 case GFC_ISYM_LSTAT
:
9526 case GFC_ISYM_MATMUL
:
9527 case GFC_ISYM_MCLOCK
:
9528 case GFC_ISYM_MCLOCK8
:
9530 case GFC_ISYM_RENAME
:
9531 case GFC_ISYM_SECOND
:
9532 case GFC_ISYM_SECNDS
:
9533 case GFC_ISYM_SIGNAL
:
9535 case GFC_ISYM_SYMLNK
:
9536 case GFC_ISYM_SYSTEM
:
9538 case GFC_ISYM_TIME8
:
9539 case GFC_ISYM_UMASK
:
9540 case GFC_ISYM_UNLINK
:
9542 gfc_conv_intrinsic_funcall (se
, expr
);
9545 case GFC_ISYM_EOSHIFT
:
9547 case GFC_ISYM_RESHAPE
:
9548 /* For those, expr->rank should always be >0 and thus the if above the
9549 switch should have matched. */
9554 gfc_conv_intrinsic_lib_function (se
, expr
);
9561 walk_inline_intrinsic_transpose (gfc_ss
*ss
, gfc_expr
*expr
)
9563 gfc_ss
*arg_ss
, *tmp_ss
;
9564 gfc_actual_arglist
*arg
;
9566 arg
= expr
->value
.function
.actual
;
9568 gcc_assert (arg
->expr
);
9570 arg_ss
= gfc_walk_subexpr (gfc_ss_terminator
, arg
->expr
);
9571 gcc_assert (arg_ss
!= gfc_ss_terminator
);
9573 for (tmp_ss
= arg_ss
; ; tmp_ss
= tmp_ss
->next
)
9575 if (tmp_ss
->info
->type
!= GFC_SS_SCALAR
9576 && tmp_ss
->info
->type
!= GFC_SS_REFERENCE
)
9578 gcc_assert (tmp_ss
->dimen
== 2);
9580 /* We just invert dimensions. */
9581 std::swap (tmp_ss
->dim
[0], tmp_ss
->dim
[1]);
9584 /* Stop when tmp_ss points to the last valid element of the chain... */
9585 if (tmp_ss
->next
== gfc_ss_terminator
)
9589 /* ... so that we can attach the rest of the chain to it. */
9596 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
9597 This has the side effect of reversing the nested list, so there is no
9598 need to call gfc_reverse_ss on it (the given list is assumed not to be
9602 nest_loop_dimension (gfc_ss
*ss
, int dim
)
9605 gfc_ss
*new_ss
, *prev_ss
= gfc_ss_terminator
;
9606 gfc_loopinfo
*new_loop
;
9608 gcc_assert (ss
!= gfc_ss_terminator
);
9610 for (; ss
!= gfc_ss_terminator
; ss
= ss
->next
)
9612 new_ss
= gfc_get_ss ();
9613 new_ss
->next
= prev_ss
;
9614 new_ss
->parent
= ss
;
9615 new_ss
->info
= ss
->info
;
9616 new_ss
->info
->refcount
++;
9619 gcc_assert (ss
->info
->type
!= GFC_SS_SCALAR
9620 && ss
->info
->type
!= GFC_SS_REFERENCE
);
9623 new_ss
->dim
[0] = ss
->dim
[dim
];
9625 gcc_assert (dim
< ss
->dimen
);
9627 ss_dim
= --ss
->dimen
;
9628 for (i
= dim
; i
< ss_dim
; i
++)
9629 ss
->dim
[i
] = ss
->dim
[i
+ 1];
9631 ss
->dim
[ss_dim
] = 0;
9637 ss
->nested_ss
->parent
= new_ss
;
9638 new_ss
->nested_ss
= ss
->nested_ss
;
9640 ss
->nested_ss
= new_ss
;
9643 new_loop
= gfc_get_loopinfo ();
9644 gfc_init_loopinfo (new_loop
);
9646 gcc_assert (prev_ss
!= NULL
);
9647 gcc_assert (prev_ss
!= gfc_ss_terminator
);
9648 gfc_add_ss_to_loop (new_loop
, prev_ss
);
9649 return new_ss
->parent
;
9653 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
9654 is to be inlined. */
9657 walk_inline_intrinsic_arith (gfc_ss
*ss
, gfc_expr
*expr
)
9659 gfc_ss
*tmp_ss
, *tail
, *array_ss
;
9660 gfc_actual_arglist
*arg1
, *arg2
, *arg3
;
9662 bool scalar_mask
= false;
9664 /* The rank of the result will be determined later. */
9665 arg1
= expr
->value
.function
.actual
;
9668 gcc_assert (arg3
!= NULL
);
9670 if (expr
->rank
== 0)
9673 tmp_ss
= gfc_ss_terminator
;
9679 mask_ss
= gfc_walk_subexpr (tmp_ss
, arg3
->expr
);
9680 if (mask_ss
== tmp_ss
)
9686 array_ss
= gfc_walk_subexpr (tmp_ss
, arg1
->expr
);
9687 gcc_assert (array_ss
!= tmp_ss
);
9689 /* Odd thing: If the mask is scalar, it is used by the frontend after
9690 the array (to make an if around the nested loop). Thus it shall
9691 be after array_ss once the gfc_ss list is reversed. */
9693 tmp_ss
= gfc_get_scalar_ss (array_ss
, arg3
->expr
);
9697 /* "Hide" the dimension on which we will sum in the first arg's scalarization
9699 sum_dim
= mpz_get_si (arg2
->expr
->value
.integer
) - 1;
9700 tail
= nest_loop_dimension (tmp_ss
, sum_dim
);
9708 walk_inline_intrinsic_function (gfc_ss
* ss
, gfc_expr
* expr
)
9711 switch (expr
->value
.function
.isym
->id
)
9713 case GFC_ISYM_PRODUCT
:
9715 return walk_inline_intrinsic_arith (ss
, expr
);
9717 case GFC_ISYM_TRANSPOSE
:
9718 return walk_inline_intrinsic_transpose (ss
, expr
);
9727 /* This generates code to execute before entering the scalarization loop.
9728 Currently does nothing. */
9731 gfc_add_intrinsic_ss_code (gfc_loopinfo
* loop ATTRIBUTE_UNUSED
, gfc_ss
* ss
)
9733 switch (ss
->info
->expr
->value
.function
.isym
->id
)
9735 case GFC_ISYM_UBOUND
:
9736 case GFC_ISYM_LBOUND
:
9737 case GFC_ISYM_UCOBOUND
:
9738 case GFC_ISYM_LCOBOUND
:
9739 case GFC_ISYM_THIS_IMAGE
:
9748 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
9749 are expanded into code inside the scalarization loop. */
9752 gfc_walk_intrinsic_bound (gfc_ss
* ss
, gfc_expr
* expr
)
9754 if (expr
->value
.function
.actual
->expr
->ts
.type
== BT_CLASS
)
9755 gfc_add_class_array_ref (expr
->value
.function
.actual
->expr
);
9757 /* The two argument version returns a scalar. */
9758 if (expr
->value
.function
.actual
->next
->expr
)
9761 return gfc_get_array_ss (ss
, expr
, 1, GFC_SS_INTRINSIC
);
9765 /* Walk an intrinsic array libcall. */
9768 gfc_walk_intrinsic_libfunc (gfc_ss
* ss
, gfc_expr
* expr
)
9770 gcc_assert (expr
->rank
> 0);
9771 return gfc_get_array_ss (ss
, expr
, expr
->rank
, GFC_SS_FUNCTION
);
9775 /* Return whether the function call expression EXPR will be expanded
9776 inline by gfc_conv_intrinsic_function. */
9779 gfc_inline_intrinsic_function_p (gfc_expr
*expr
)
9781 gfc_actual_arglist
*args
;
9783 if (!expr
->value
.function
.isym
)
9786 switch (expr
->value
.function
.isym
->id
)
9788 case GFC_ISYM_PRODUCT
:
9790 /* Disable inline expansion if code size matters. */
9794 args
= expr
->value
.function
.actual
;
9795 /* We need to be able to subset the SUM argument at compile-time. */
9796 if (args
->next
->expr
&& args
->next
->expr
->expr_type
!= EXPR_CONSTANT
)
9801 case GFC_ISYM_TRANSPOSE
:
9810 /* Returns nonzero if the specified intrinsic function call maps directly to
9811 an external library call. Should only be used for functions that return
9815 gfc_is_intrinsic_libcall (gfc_expr
* expr
)
9817 gcc_assert (expr
->expr_type
== EXPR_FUNCTION
&& expr
->value
.function
.isym
);
9818 gcc_assert (expr
->rank
> 0);
9820 if (gfc_inline_intrinsic_function_p (expr
))
9823 switch (expr
->value
.function
.isym
->id
)
9827 case GFC_ISYM_COUNT
:
9831 case GFC_ISYM_IPARITY
:
9832 case GFC_ISYM_MATMUL
:
9833 case GFC_ISYM_MAXLOC
:
9834 case GFC_ISYM_MAXVAL
:
9835 case GFC_ISYM_MINLOC
:
9836 case GFC_ISYM_MINVAL
:
9837 case GFC_ISYM_NORM2
:
9838 case GFC_ISYM_PARITY
:
9839 case GFC_ISYM_PRODUCT
:
9841 case GFC_ISYM_SHAPE
:
9842 case GFC_ISYM_SPREAD
:
9844 /* Ignore absent optional parameters. */
9847 case GFC_ISYM_CSHIFT
:
9848 case GFC_ISYM_EOSHIFT
:
9849 case GFC_ISYM_GET_TEAM
:
9850 case GFC_ISYM_FAILED_IMAGES
:
9851 case GFC_ISYM_STOPPED_IMAGES
:
9853 case GFC_ISYM_RESHAPE
:
9854 case GFC_ISYM_UNPACK
:
9855 /* Pass absent optional parameters. */
9863 /* Walk an intrinsic function. */
9865 gfc_walk_intrinsic_function (gfc_ss
* ss
, gfc_expr
* expr
,
9866 gfc_intrinsic_sym
* isym
)
9870 if (isym
->elemental
)
9871 return gfc_walk_elemental_function_args (ss
, expr
->value
.function
.actual
,
9872 NULL
, GFC_SS_SCALAR
);
9874 if (expr
->rank
== 0)
9877 if (gfc_inline_intrinsic_function_p (expr
))
9878 return walk_inline_intrinsic_function (ss
, expr
);
9880 if (gfc_is_intrinsic_libcall (expr
))
9881 return gfc_walk_intrinsic_libfunc (ss
, expr
);
9883 /* Special cases. */
9886 case GFC_ISYM_LBOUND
:
9887 case GFC_ISYM_LCOBOUND
:
9888 case GFC_ISYM_UBOUND
:
9889 case GFC_ISYM_UCOBOUND
:
9890 case GFC_ISYM_THIS_IMAGE
:
9891 return gfc_walk_intrinsic_bound (ss
, expr
);
9893 case GFC_ISYM_TRANSFER
:
9894 case GFC_ISYM_CAF_GET
:
9895 return gfc_walk_intrinsic_libfunc (ss
, expr
);
9898 /* This probably meant someone forgot to add an intrinsic to the above
9899 list(s) when they implemented it, or something's gone horribly
9907 conv_co_collective (gfc_code
*code
)
9910 stmtblock_t block
, post_block
;
9911 tree fndecl
, array
, strlen
, image_index
, stat
, errmsg
, errmsg_len
;
9912 gfc_expr
*image_idx_expr
, *stat_expr
, *errmsg_expr
, *opr_expr
;
9914 gfc_start_block (&block
);
9915 gfc_init_block (&post_block
);
9917 if (code
->resolved_isym
->id
== GFC_ISYM_CO_REDUCE
)
9919 opr_expr
= code
->ext
.actual
->next
->expr
;
9920 image_idx_expr
= code
->ext
.actual
->next
->next
->expr
;
9921 stat_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
9922 errmsg_expr
= code
->ext
.actual
->next
->next
->next
->next
->expr
;
9927 image_idx_expr
= code
->ext
.actual
->next
->expr
;
9928 stat_expr
= code
->ext
.actual
->next
->next
->expr
;
9929 errmsg_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
9935 gfc_init_se (&argse
, NULL
);
9936 gfc_conv_expr (&argse
, stat_expr
);
9937 gfc_add_block_to_block (&block
, &argse
.pre
);
9938 gfc_add_block_to_block (&post_block
, &argse
.post
);
9940 if (flag_coarray
!= GFC_FCOARRAY_SINGLE
)
9941 stat
= gfc_build_addr_expr (NULL_TREE
, stat
);
9943 else if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
9946 stat
= null_pointer_node
;
9948 /* Early exit for GFC_FCOARRAY_SINGLE. */
9949 if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
9951 if (stat
!= NULL_TREE
)
9952 gfc_add_modify (&block
, stat
,
9953 fold_convert (TREE_TYPE (stat
), integer_zero_node
));
9954 return gfc_finish_block (&block
);
9957 /* Handle the array. */
9958 gfc_init_se (&argse
, NULL
);
9959 if (code
->ext
.actual
->expr
->rank
== 0)
9961 symbol_attribute attr
;
9962 gfc_clear_attr (&attr
);
9963 gfc_init_se (&argse
, NULL
);
9964 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
9965 gfc_add_block_to_block (&block
, &argse
.pre
);
9966 gfc_add_block_to_block (&post_block
, &argse
.post
);
9967 array
= gfc_conv_scalar_to_descriptor (&argse
, argse
.expr
, attr
);
9968 array
= gfc_build_addr_expr (NULL_TREE
, array
);
9972 argse
.want_pointer
= 1;
9973 gfc_conv_expr_descriptor (&argse
, code
->ext
.actual
->expr
);
9976 gfc_add_block_to_block (&block
, &argse
.pre
);
9977 gfc_add_block_to_block (&post_block
, &argse
.post
);
9979 if (code
->ext
.actual
->expr
->ts
.type
== BT_CHARACTER
)
9980 strlen
= argse
.string_length
;
9982 strlen
= integer_zero_node
;
9987 gfc_init_se (&argse
, NULL
);
9988 gfc_conv_expr (&argse
, image_idx_expr
);
9989 gfc_add_block_to_block (&block
, &argse
.pre
);
9990 gfc_add_block_to_block (&post_block
, &argse
.post
);
9991 image_index
= fold_convert (integer_type_node
, argse
.expr
);
9994 image_index
= integer_zero_node
;
9999 gfc_init_se (&argse
, NULL
);
10000 gfc_conv_expr (&argse
, errmsg_expr
);
10001 gfc_add_block_to_block (&block
, &argse
.pre
);
10002 gfc_add_block_to_block (&post_block
, &argse
.post
);
10003 errmsg
= argse
.expr
;
10004 errmsg_len
= fold_convert (size_type_node
, argse
.string_length
);
10008 errmsg
= null_pointer_node
;
10009 errmsg_len
= build_zero_cst (size_type_node
);
10012 /* Generate the function call. */
10013 switch (code
->resolved_isym
->id
)
10015 case GFC_ISYM_CO_BROADCAST
:
10016 fndecl
= gfor_fndecl_co_broadcast
;
10018 case GFC_ISYM_CO_MAX
:
10019 fndecl
= gfor_fndecl_co_max
;
10021 case GFC_ISYM_CO_MIN
:
10022 fndecl
= gfor_fndecl_co_min
;
10024 case GFC_ISYM_CO_REDUCE
:
10025 fndecl
= gfor_fndecl_co_reduce
;
10027 case GFC_ISYM_CO_SUM
:
10028 fndecl
= gfor_fndecl_co_sum
;
10031 gcc_unreachable ();
10034 if (code
->resolved_isym
->id
== GFC_ISYM_CO_SUM
10035 || code
->resolved_isym
->id
== GFC_ISYM_CO_BROADCAST
)
10036 fndecl
= build_call_expr_loc (input_location
, fndecl
, 5, array
,
10037 image_index
, stat
, errmsg
, errmsg_len
);
10038 else if (code
->resolved_isym
->id
!= GFC_ISYM_CO_REDUCE
)
10039 fndecl
= build_call_expr_loc (input_location
, fndecl
, 6, array
, image_index
,
10040 stat
, errmsg
, strlen
, errmsg_len
);
10043 tree opr
, opr_flags
;
10045 // FIXME: Handle TS29113's bind(C) strings with descriptor.
10047 if (gfc_is_proc_ptr_comp (opr_expr
))
10049 gfc_symbol
*sym
= gfc_get_proc_ptr_comp (opr_expr
)->ts
.interface
;
10050 opr_flag_int
= sym
->attr
.dimension
10051 || (sym
->ts
.type
== BT_CHARACTER
10052 && !sym
->attr
.is_bind_c
)
10053 ? GFC_CAF_BYREF
: 0;
10054 opr_flag_int
|= opr_expr
->ts
.type
== BT_CHARACTER
10055 && !sym
->attr
.is_bind_c
10056 ? GFC_CAF_HIDDENLEN
: 0;
10057 opr_flag_int
|= sym
->formal
->sym
->attr
.value
? GFC_CAF_ARG_VALUE
: 0;
10061 opr_flag_int
= gfc_return_by_reference (opr_expr
->symtree
->n
.sym
)
10062 ? GFC_CAF_BYREF
: 0;
10063 opr_flag_int
|= opr_expr
->ts
.type
== BT_CHARACTER
10064 && !opr_expr
->symtree
->n
.sym
->attr
.is_bind_c
10065 ? GFC_CAF_HIDDENLEN
: 0;
10066 opr_flag_int
|= opr_expr
->symtree
->n
.sym
->formal
->sym
->attr
.value
10067 ? GFC_CAF_ARG_VALUE
: 0;
10069 opr_flags
= build_int_cst (integer_type_node
, opr_flag_int
);
10070 gfc_conv_expr (&argse
, opr_expr
);
10072 fndecl
= build_call_expr_loc (input_location
, fndecl
, 8, array
, opr
, opr_flags
,
10073 image_index
, stat
, errmsg
, strlen
, errmsg_len
);
10076 gfc_add_expr_to_block (&block
, fndecl
);
10077 gfc_add_block_to_block (&block
, &post_block
);
10079 return gfc_finish_block (&block
);
10084 conv_intrinsic_atomic_op (gfc_code
*code
)
10087 tree tmp
, atom
, value
, old
= NULL_TREE
, stat
= NULL_TREE
;
10088 stmtblock_t block
, post_block
;
10089 gfc_expr
*atom_expr
= code
->ext
.actual
->expr
;
10090 gfc_expr
*stat_expr
;
10091 built_in_function fn
;
10093 if (atom_expr
->expr_type
== EXPR_FUNCTION
10094 && atom_expr
->value
.function
.isym
10095 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
10096 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
10098 gfc_start_block (&block
);
10099 gfc_init_block (&post_block
);
10101 gfc_init_se (&argse
, NULL
);
10102 argse
.want_pointer
= 1;
10103 gfc_conv_expr (&argse
, atom_expr
);
10104 gfc_add_block_to_block (&block
, &argse
.pre
);
10105 gfc_add_block_to_block (&post_block
, &argse
.post
);
10108 gfc_init_se (&argse
, NULL
);
10109 if (flag_coarray
== GFC_FCOARRAY_LIB
10110 && code
->ext
.actual
->next
->expr
->ts
.kind
== atom_expr
->ts
.kind
)
10111 argse
.want_pointer
= 1;
10112 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->expr
);
10113 gfc_add_block_to_block (&block
, &argse
.pre
);
10114 gfc_add_block_to_block (&post_block
, &argse
.post
);
10115 value
= argse
.expr
;
10117 switch (code
->resolved_isym
->id
)
10119 case GFC_ISYM_ATOMIC_ADD
:
10120 case GFC_ISYM_ATOMIC_AND
:
10121 case GFC_ISYM_ATOMIC_DEF
:
10122 case GFC_ISYM_ATOMIC_OR
:
10123 case GFC_ISYM_ATOMIC_XOR
:
10124 stat_expr
= code
->ext
.actual
->next
->next
->expr
;
10125 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10126 old
= null_pointer_node
;
10129 gfc_init_se (&argse
, NULL
);
10130 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10131 argse
.want_pointer
= 1;
10132 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->expr
);
10133 gfc_add_block_to_block (&block
, &argse
.pre
);
10134 gfc_add_block_to_block (&post_block
, &argse
.post
);
10136 stat_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
10140 if (stat_expr
!= NULL
)
10142 gcc_assert (stat_expr
->expr_type
== EXPR_VARIABLE
);
10143 gfc_init_se (&argse
, NULL
);
10144 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10145 argse
.want_pointer
= 1;
10146 gfc_conv_expr_val (&argse
, stat_expr
);
10147 gfc_add_block_to_block (&block
, &argse
.pre
);
10148 gfc_add_block_to_block (&post_block
, &argse
.post
);
10151 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
10152 stat
= null_pointer_node
;
10154 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10156 tree image_index
, caf_decl
, offset
, token
;
10159 switch (code
->resolved_isym
->id
)
10161 case GFC_ISYM_ATOMIC_ADD
:
10162 case GFC_ISYM_ATOMIC_FETCH_ADD
:
10163 op
= (int) GFC_CAF_ATOMIC_ADD
;
10165 case GFC_ISYM_ATOMIC_AND
:
10166 case GFC_ISYM_ATOMIC_FETCH_AND
:
10167 op
= (int) GFC_CAF_ATOMIC_AND
;
10169 case GFC_ISYM_ATOMIC_OR
:
10170 case GFC_ISYM_ATOMIC_FETCH_OR
:
10171 op
= (int) GFC_CAF_ATOMIC_OR
;
10173 case GFC_ISYM_ATOMIC_XOR
:
10174 case GFC_ISYM_ATOMIC_FETCH_XOR
:
10175 op
= (int) GFC_CAF_ATOMIC_XOR
;
10177 case GFC_ISYM_ATOMIC_DEF
:
10178 op
= 0; /* Unused. */
10181 gcc_unreachable ();
10184 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
10185 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
10186 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
10188 if (gfc_is_coindexed (atom_expr
))
10189 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
10191 image_index
= integer_zero_node
;
10193 if (!POINTER_TYPE_P (TREE_TYPE (value
)))
10195 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (atom
)), "value");
10196 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), value
));
10197 value
= gfc_build_addr_expr (NULL_TREE
, tmp
);
10200 gfc_init_se (&argse
, NULL
);
10201 gfc_get_caf_token_offset (&argse
, &token
, &offset
, caf_decl
, atom
,
10204 gfc_add_block_to_block (&block
, &argse
.pre
);
10205 if (code
->resolved_isym
->id
== GFC_ISYM_ATOMIC_DEF
)
10206 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_def
, 7,
10207 token
, offset
, image_index
, value
, stat
,
10208 build_int_cst (integer_type_node
,
10209 (int) atom_expr
->ts
.type
),
10210 build_int_cst (integer_type_node
,
10211 (int) atom_expr
->ts
.kind
));
10213 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_op
, 9,
10214 build_int_cst (integer_type_node
, op
),
10215 token
, offset
, image_index
, value
, old
, stat
,
10216 build_int_cst (integer_type_node
,
10217 (int) atom_expr
->ts
.type
),
10218 build_int_cst (integer_type_node
,
10219 (int) atom_expr
->ts
.kind
));
10221 gfc_add_expr_to_block (&block
, tmp
);
10222 gfc_add_block_to_block (&block
, &argse
.post
);
10223 gfc_add_block_to_block (&block
, &post_block
);
10224 return gfc_finish_block (&block
);
10228 switch (code
->resolved_isym
->id
)
10230 case GFC_ISYM_ATOMIC_ADD
:
10231 case GFC_ISYM_ATOMIC_FETCH_ADD
:
10232 fn
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
10234 case GFC_ISYM_ATOMIC_AND
:
10235 case GFC_ISYM_ATOMIC_FETCH_AND
:
10236 fn
= BUILT_IN_ATOMIC_FETCH_AND_N
;
10238 case GFC_ISYM_ATOMIC_DEF
:
10239 fn
= BUILT_IN_ATOMIC_STORE_N
;
10241 case GFC_ISYM_ATOMIC_OR
:
10242 case GFC_ISYM_ATOMIC_FETCH_OR
:
10243 fn
= BUILT_IN_ATOMIC_FETCH_OR_N
;
10245 case GFC_ISYM_ATOMIC_XOR
:
10246 case GFC_ISYM_ATOMIC_FETCH_XOR
:
10247 fn
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
10250 gcc_unreachable ();
10253 tmp
= TREE_TYPE (TREE_TYPE (atom
));
10254 fn
= (built_in_function
) ((int) fn
10255 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
10257 tmp
= builtin_decl_explicit (fn
);
10258 tree itype
= TREE_TYPE (TREE_TYPE (atom
));
10259 tmp
= builtin_decl_explicit (fn
);
10261 switch (code
->resolved_isym
->id
)
10263 case GFC_ISYM_ATOMIC_ADD
:
10264 case GFC_ISYM_ATOMIC_AND
:
10265 case GFC_ISYM_ATOMIC_DEF
:
10266 case GFC_ISYM_ATOMIC_OR
:
10267 case GFC_ISYM_ATOMIC_XOR
:
10268 tmp
= build_call_expr_loc (input_location
, tmp
, 3, atom
,
10269 fold_convert (itype
, value
),
10270 build_int_cst (NULL
, MEMMODEL_RELAXED
));
10271 gfc_add_expr_to_block (&block
, tmp
);
10274 tmp
= build_call_expr_loc (input_location
, tmp
, 3, atom
,
10275 fold_convert (itype
, value
),
10276 build_int_cst (NULL
, MEMMODEL_RELAXED
));
10277 gfc_add_modify (&block
, old
, fold_convert (TREE_TYPE (old
), tmp
));
10281 if (stat
!= NULL_TREE
)
10282 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
10283 gfc_add_block_to_block (&block
, &post_block
);
10284 return gfc_finish_block (&block
);
10289 conv_intrinsic_atomic_ref (gfc_code
*code
)
10292 tree tmp
, atom
, value
, stat
= NULL_TREE
;
10293 stmtblock_t block
, post_block
;
10294 built_in_function fn
;
10295 gfc_expr
*atom_expr
= code
->ext
.actual
->next
->expr
;
10297 if (atom_expr
->expr_type
== EXPR_FUNCTION
10298 && atom_expr
->value
.function
.isym
10299 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
10300 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
10302 gfc_start_block (&block
);
10303 gfc_init_block (&post_block
);
10304 gfc_init_se (&argse
, NULL
);
10305 argse
.want_pointer
= 1;
10306 gfc_conv_expr (&argse
, atom_expr
);
10307 gfc_add_block_to_block (&block
, &argse
.pre
);
10308 gfc_add_block_to_block (&post_block
, &argse
.post
);
10311 gfc_init_se (&argse
, NULL
);
10312 if (flag_coarray
== GFC_FCOARRAY_LIB
10313 && code
->ext
.actual
->expr
->ts
.kind
== atom_expr
->ts
.kind
)
10314 argse
.want_pointer
= 1;
10315 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
10316 gfc_add_block_to_block (&block
, &argse
.pre
);
10317 gfc_add_block_to_block (&post_block
, &argse
.post
);
10318 value
= argse
.expr
;
10321 if (code
->ext
.actual
->next
->next
->expr
!= NULL
)
10323 gcc_assert (code
->ext
.actual
->next
->next
->expr
->expr_type
10325 gfc_init_se (&argse
, NULL
);
10326 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10327 argse
.want_pointer
= 1;
10328 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->next
->expr
);
10329 gfc_add_block_to_block (&block
, &argse
.pre
);
10330 gfc_add_block_to_block (&post_block
, &argse
.post
);
10333 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
10334 stat
= null_pointer_node
;
10336 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10338 tree image_index
, caf_decl
, offset
, token
;
10339 tree orig_value
= NULL_TREE
, vardecl
= NULL_TREE
;
10341 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
10342 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
10343 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
10345 if (gfc_is_coindexed (atom_expr
))
10346 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
10348 image_index
= integer_zero_node
;
10350 gfc_init_se (&argse
, NULL
);
10351 gfc_get_caf_token_offset (&argse
, &token
, &offset
, caf_decl
, atom
,
10353 gfc_add_block_to_block (&block
, &argse
.pre
);
10355 /* Different type, need type conversion. */
10356 if (!POINTER_TYPE_P (TREE_TYPE (value
)))
10358 vardecl
= gfc_create_var (TREE_TYPE (TREE_TYPE (atom
)), "value");
10359 orig_value
= value
;
10360 value
= gfc_build_addr_expr (NULL_TREE
, vardecl
);
10363 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_ref
, 7,
10364 token
, offset
, image_index
, value
, stat
,
10365 build_int_cst (integer_type_node
,
10366 (int) atom_expr
->ts
.type
),
10367 build_int_cst (integer_type_node
,
10368 (int) atom_expr
->ts
.kind
));
10369 gfc_add_expr_to_block (&block
, tmp
);
10370 if (vardecl
!= NULL_TREE
)
10371 gfc_add_modify (&block
, orig_value
,
10372 fold_convert (TREE_TYPE (orig_value
), vardecl
));
10373 gfc_add_block_to_block (&block
, &argse
.post
);
10374 gfc_add_block_to_block (&block
, &post_block
);
10375 return gfc_finish_block (&block
);
10378 tmp
= TREE_TYPE (TREE_TYPE (atom
));
10379 fn
= (built_in_function
) ((int) BUILT_IN_ATOMIC_LOAD_N
10380 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
10382 tmp
= builtin_decl_explicit (fn
);
10383 tmp
= build_call_expr_loc (input_location
, tmp
, 2, atom
,
10384 build_int_cst (integer_type_node
,
10385 MEMMODEL_RELAXED
));
10386 gfc_add_modify (&block
, value
, fold_convert (TREE_TYPE (value
), tmp
));
10388 if (stat
!= NULL_TREE
)
10389 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
10390 gfc_add_block_to_block (&block
, &post_block
);
10391 return gfc_finish_block (&block
);
10396 conv_intrinsic_atomic_cas (gfc_code
*code
)
10399 tree tmp
, atom
, old
, new_val
, comp
, stat
= NULL_TREE
;
10400 stmtblock_t block
, post_block
;
10401 built_in_function fn
;
10402 gfc_expr
*atom_expr
= code
->ext
.actual
->expr
;
10404 if (atom_expr
->expr_type
== EXPR_FUNCTION
10405 && atom_expr
->value
.function
.isym
10406 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
10407 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
10409 gfc_init_block (&block
);
10410 gfc_init_block (&post_block
);
10411 gfc_init_se (&argse
, NULL
);
10412 argse
.want_pointer
= 1;
10413 gfc_conv_expr (&argse
, atom_expr
);
10416 gfc_init_se (&argse
, NULL
);
10417 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10418 argse
.want_pointer
= 1;
10419 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->expr
);
10420 gfc_add_block_to_block (&block
, &argse
.pre
);
10421 gfc_add_block_to_block (&post_block
, &argse
.post
);
10424 gfc_init_se (&argse
, NULL
);
10425 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10426 argse
.want_pointer
= 1;
10427 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->expr
);
10428 gfc_add_block_to_block (&block
, &argse
.pre
);
10429 gfc_add_block_to_block (&post_block
, &argse
.post
);
10432 gfc_init_se (&argse
, NULL
);
10433 if (flag_coarray
== GFC_FCOARRAY_LIB
10434 && code
->ext
.actual
->next
->next
->next
->expr
->ts
.kind
10435 == atom_expr
->ts
.kind
)
10436 argse
.want_pointer
= 1;
10437 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->next
->expr
);
10438 gfc_add_block_to_block (&block
, &argse
.pre
);
10439 gfc_add_block_to_block (&post_block
, &argse
.post
);
10440 new_val
= argse
.expr
;
10443 if (code
->ext
.actual
->next
->next
->next
->next
->expr
!= NULL
)
10445 gcc_assert (code
->ext
.actual
->next
->next
->next
->next
->expr
->expr_type
10447 gfc_init_se (&argse
, NULL
);
10448 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10449 argse
.want_pointer
= 1;
10450 gfc_conv_expr_val (&argse
,
10451 code
->ext
.actual
->next
->next
->next
->next
->expr
);
10452 gfc_add_block_to_block (&block
, &argse
.pre
);
10453 gfc_add_block_to_block (&post_block
, &argse
.post
);
10456 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
10457 stat
= null_pointer_node
;
10459 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10461 tree image_index
, caf_decl
, offset
, token
;
10463 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
10464 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
10465 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
10467 if (gfc_is_coindexed (atom_expr
))
10468 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
10470 image_index
= integer_zero_node
;
10472 if (TREE_TYPE (TREE_TYPE (new_val
)) != TREE_TYPE (TREE_TYPE (old
)))
10474 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (old
)), "new");
10475 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), new_val
));
10476 new_val
= gfc_build_addr_expr (NULL_TREE
, tmp
);
10479 /* Convert a constant to a pointer. */
10480 if (!POINTER_TYPE_P (TREE_TYPE (comp
)))
10482 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (old
)), "comp");
10483 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), comp
));
10484 comp
= gfc_build_addr_expr (NULL_TREE
, tmp
);
10487 gfc_init_se (&argse
, NULL
);
10488 gfc_get_caf_token_offset (&argse
, &token
, &offset
, caf_decl
, atom
,
10490 gfc_add_block_to_block (&block
, &argse
.pre
);
10492 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_cas
, 9,
10493 token
, offset
, image_index
, old
, comp
, new_val
,
10494 stat
, build_int_cst (integer_type_node
,
10495 (int) atom_expr
->ts
.type
),
10496 build_int_cst (integer_type_node
,
10497 (int) atom_expr
->ts
.kind
));
10498 gfc_add_expr_to_block (&block
, tmp
);
10499 gfc_add_block_to_block (&block
, &argse
.post
);
10500 gfc_add_block_to_block (&block
, &post_block
);
10501 return gfc_finish_block (&block
);
10504 tmp
= TREE_TYPE (TREE_TYPE (atom
));
10505 fn
= (built_in_function
) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
10506 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
10508 tmp
= builtin_decl_explicit (fn
);
10510 gfc_add_modify (&block
, old
, comp
);
10511 tmp
= build_call_expr_loc (input_location
, tmp
, 6, atom
,
10512 gfc_build_addr_expr (NULL
, old
),
10513 fold_convert (TREE_TYPE (old
), new_val
),
10514 boolean_false_node
,
10515 build_int_cst (NULL
, MEMMODEL_RELAXED
),
10516 build_int_cst (NULL
, MEMMODEL_RELAXED
));
10517 gfc_add_expr_to_block (&block
, tmp
);
10519 if (stat
!= NULL_TREE
)
10520 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
10521 gfc_add_block_to_block (&block
, &post_block
);
10522 return gfc_finish_block (&block
);
10526 conv_intrinsic_event_query (gfc_code
*code
)
10529 tree stat
= NULL_TREE
, stat2
= NULL_TREE
;
10530 tree count
= NULL_TREE
, count2
= NULL_TREE
;
10532 gfc_expr
*event_expr
= code
->ext
.actual
->expr
;
10534 if (code
->ext
.actual
->next
->next
->expr
)
10536 gcc_assert (code
->ext
.actual
->next
->next
->expr
->expr_type
10538 gfc_init_se (&argse
, NULL
);
10539 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->next
->expr
);
10542 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
10543 stat
= null_pointer_node
;
10545 if (code
->ext
.actual
->next
->expr
)
10547 gcc_assert (code
->ext
.actual
->next
->expr
->expr_type
== EXPR_VARIABLE
);
10548 gfc_init_se (&argse
, NULL
);
10549 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->expr
);
10550 count
= argse
.expr
;
10553 gfc_start_block (&se
.pre
);
10554 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10556 tree tmp
, token
, image_index
;
10557 tree index
= size_zero_node
;
10559 if (event_expr
->expr_type
== EXPR_FUNCTION
10560 && event_expr
->value
.function
.isym
10561 && event_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
10562 event_expr
= event_expr
->value
.function
.actual
->expr
;
10564 tree caf_decl
= gfc_get_tree_for_caf_expr (event_expr
);
10566 if (event_expr
->symtree
->n
.sym
->ts
.type
!= BT_DERIVED
10567 || event_expr
->symtree
->n
.sym
->ts
.u
.derived
->from_intmod
10568 != INTMOD_ISO_FORTRAN_ENV
10569 || event_expr
->symtree
->n
.sym
->ts
.u
.derived
->intmod_sym_id
10570 != ISOFORTRAN_EVENT_TYPE
)
10572 gfc_error ("Sorry, the event component of derived type at %L is not "
10573 "yet supported", &event_expr
->where
);
10577 if (gfc_is_coindexed (event_expr
))
10579 gfc_error ("The event variable at %L shall not be coindexed",
10580 &event_expr
->where
);
10584 image_index
= integer_zero_node
;
10586 gfc_get_caf_token_offset (&se
, &token
, NULL
, caf_decl
, NULL_TREE
,
10589 /* For arrays, obtain the array index. */
10590 if (gfc_expr_attr (event_expr
).dimension
)
10592 tree desc
, tmp
, extent
, lbound
, ubound
;
10593 gfc_array_ref
*ar
, ar2
;
10596 /* TODO: Extend this, once DT components are supported. */
10597 ar
= &event_expr
->ref
->u
.ar
;
10599 memset (ar
, '\0', sizeof (*ar
));
10601 ar
->type
= AR_FULL
;
10603 gfc_init_se (&argse
, NULL
);
10604 argse
.descriptor_only
= 1;
10605 gfc_conv_expr_descriptor (&argse
, event_expr
);
10606 gfc_add_block_to_block (&se
.pre
, &argse
.pre
);
10610 extent
= integer_one_node
;
10611 for (i
= 0; i
< ar
->dimen
; i
++)
10613 gfc_init_se (&argse
, NULL
);
10614 gfc_conv_expr_type (&argse
, ar
->start
[i
], integer_type_node
);
10615 gfc_add_block_to_block (&argse
.pre
, &argse
.pre
);
10616 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[i
]);
10617 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
10618 integer_type_node
, argse
.expr
,
10619 fold_convert(integer_type_node
, lbound
));
10620 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
10621 integer_type_node
, extent
, tmp
);
10622 index
= fold_build2_loc (input_location
, PLUS_EXPR
,
10623 integer_type_node
, index
, tmp
);
10624 if (i
< ar
->dimen
- 1)
10626 ubound
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[i
]);
10627 tmp
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
10628 tmp
= fold_convert (integer_type_node
, tmp
);
10629 extent
= fold_build2_loc (input_location
, MULT_EXPR
,
10630 integer_type_node
, extent
, tmp
);
10635 if (count
!= null_pointer_node
&& TREE_TYPE (count
) != integer_type_node
)
10638 count
= gfc_create_var (integer_type_node
, "count");
10641 if (stat
!= null_pointer_node
&& TREE_TYPE (stat
) != integer_type_node
)
10644 stat
= gfc_create_var (integer_type_node
, "stat");
10647 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_event_query
, 5,
10648 token
, index
, image_index
, count
10649 ? gfc_build_addr_expr (NULL
, count
) : count
,
10650 stat
!= null_pointer_node
10651 ? gfc_build_addr_expr (NULL
, stat
) : stat
);
10652 gfc_add_expr_to_block (&se
.pre
, tmp
);
10654 if (count2
!= NULL_TREE
)
10655 gfc_add_modify (&se
.pre
, count2
,
10656 fold_convert (TREE_TYPE (count2
), count
));
10658 if (stat2
!= NULL_TREE
)
10659 gfc_add_modify (&se
.pre
, stat2
,
10660 fold_convert (TREE_TYPE (stat2
), stat
));
10662 return gfc_finish_block (&se
.pre
);
10665 gfc_init_se (&argse
, NULL
);
10666 gfc_conv_expr_val (&argse
, code
->ext
.actual
->expr
);
10667 gfc_add_modify (&se
.pre
, count
, fold_convert (TREE_TYPE (count
), argse
.expr
));
10669 if (stat
!= NULL_TREE
)
10670 gfc_add_modify (&se
.pre
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
10672 return gfc_finish_block (&se
.pre
);
10676 conv_intrinsic_move_alloc (gfc_code
*code
)
10679 gfc_expr
*from_expr
, *to_expr
;
10680 gfc_expr
*to_expr2
, *from_expr2
= NULL
;
10681 gfc_se from_se
, to_se
;
10685 gfc_start_block (&block
);
10687 from_expr
= code
->ext
.actual
->expr
;
10688 to_expr
= code
->ext
.actual
->next
->expr
;
10690 gfc_init_se (&from_se
, NULL
);
10691 gfc_init_se (&to_se
, NULL
);
10693 gcc_assert (from_expr
->ts
.type
!= BT_CLASS
10694 || to_expr
->ts
.type
== BT_CLASS
);
10695 coarray
= gfc_get_corank (from_expr
) != 0;
10697 if (from_expr
->rank
== 0 && !coarray
)
10699 if (from_expr
->ts
.type
!= BT_CLASS
)
10700 from_expr2
= from_expr
;
10703 from_expr2
= gfc_copy_expr (from_expr
);
10704 gfc_add_data_component (from_expr2
);
10707 if (to_expr
->ts
.type
!= BT_CLASS
)
10708 to_expr2
= to_expr
;
10711 to_expr2
= gfc_copy_expr (to_expr
);
10712 gfc_add_data_component (to_expr2
);
10715 from_se
.want_pointer
= 1;
10716 to_se
.want_pointer
= 1;
10717 gfc_conv_expr (&from_se
, from_expr2
);
10718 gfc_conv_expr (&to_se
, to_expr2
);
10719 gfc_add_block_to_block (&block
, &from_se
.pre
);
10720 gfc_add_block_to_block (&block
, &to_se
.pre
);
10722 /* Deallocate "to". */
10723 tmp
= gfc_deallocate_scalar_with_status (to_se
.expr
, NULL_TREE
, NULL_TREE
,
10724 true, to_expr
, to_expr
->ts
);
10725 gfc_add_expr_to_block (&block
, tmp
);
10727 /* Assign (_data) pointers. */
10728 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
10729 fold_convert (TREE_TYPE (to_se
.expr
), from_se
.expr
));
10731 /* Set "from" to NULL. */
10732 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
10733 fold_convert (TREE_TYPE (from_se
.expr
), null_pointer_node
));
10735 gfc_add_block_to_block (&block
, &from_se
.post
);
10736 gfc_add_block_to_block (&block
, &to_se
.post
);
10739 if (to_expr
->ts
.type
== BT_CLASS
)
10743 gfc_free_expr (to_expr2
);
10744 gfc_init_se (&to_se
, NULL
);
10745 to_se
.want_pointer
= 1;
10746 gfc_add_vptr_component (to_expr
);
10747 gfc_conv_expr (&to_se
, to_expr
);
10749 if (from_expr
->ts
.type
== BT_CLASS
)
10751 if (UNLIMITED_POLY (from_expr
))
10755 vtab
= gfc_find_derived_vtab (from_expr
->ts
.u
.derived
);
10759 gfc_free_expr (from_expr2
);
10760 gfc_init_se (&from_se
, NULL
);
10761 from_se
.want_pointer
= 1;
10762 gfc_add_vptr_component (from_expr
);
10763 gfc_conv_expr (&from_se
, from_expr
);
10764 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
10765 fold_convert (TREE_TYPE (to_se
.expr
),
10768 /* Reset _vptr component to declared type. */
10770 /* Unlimited polymorphic. */
10771 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
10772 fold_convert (TREE_TYPE (from_se
.expr
),
10773 null_pointer_node
));
10776 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
10777 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
10778 fold_convert (TREE_TYPE (from_se
.expr
), tmp
));
10783 vtab
= gfc_find_vtab (&from_expr
->ts
);
10785 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
10786 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
10787 fold_convert (TREE_TYPE (to_se
.expr
), tmp
));
10791 if (to_expr
->ts
.type
== BT_CHARACTER
&& to_expr
->ts
.deferred
)
10793 gfc_add_modify_loc (input_location
, &block
, to_se
.string_length
,
10794 fold_convert (TREE_TYPE (to_se
.string_length
),
10795 from_se
.string_length
));
10796 if (from_expr
->ts
.deferred
)
10797 gfc_add_modify_loc (input_location
, &block
, from_se
.string_length
,
10798 build_int_cst (TREE_TYPE (from_se
.string_length
), 0));
10801 return gfc_finish_block (&block
);
10804 /* Update _vptr component. */
10805 if (to_expr
->ts
.type
== BT_CLASS
)
10809 to_se
.want_pointer
= 1;
10810 to_expr2
= gfc_copy_expr (to_expr
);
10811 gfc_add_vptr_component (to_expr2
);
10812 gfc_conv_expr (&to_se
, to_expr2
);
10814 if (from_expr
->ts
.type
== BT_CLASS
)
10816 if (UNLIMITED_POLY (from_expr
))
10820 vtab
= gfc_find_derived_vtab (from_expr
->ts
.u
.derived
);
10824 from_se
.want_pointer
= 1;
10825 from_expr2
= gfc_copy_expr (from_expr
);
10826 gfc_add_vptr_component (from_expr2
);
10827 gfc_conv_expr (&from_se
, from_expr2
);
10828 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
10829 fold_convert (TREE_TYPE (to_se
.expr
),
10832 /* Reset _vptr component to declared type. */
10834 /* Unlimited polymorphic. */
10835 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
10836 fold_convert (TREE_TYPE (from_se
.expr
),
10837 null_pointer_node
));
10840 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
10841 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
10842 fold_convert (TREE_TYPE (from_se
.expr
), tmp
));
10847 vtab
= gfc_find_vtab (&from_expr
->ts
);
10849 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
10850 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
10851 fold_convert (TREE_TYPE (to_se
.expr
), tmp
));
10854 gfc_free_expr (to_expr2
);
10855 gfc_init_se (&to_se
, NULL
);
10857 if (from_expr
->ts
.type
== BT_CLASS
)
10859 gfc_free_expr (from_expr2
);
10860 gfc_init_se (&from_se
, NULL
);
10865 /* Deallocate "to". */
10866 if (from_expr
->rank
== 0)
10868 to_se
.want_coarray
= 1;
10869 from_se
.want_coarray
= 1;
10871 gfc_conv_expr_descriptor (&to_se
, to_expr
);
10872 gfc_conv_expr_descriptor (&from_se
, from_expr
);
10874 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
10875 is an image control "statement", cf. IR F08/0040 in 12-006A. */
10876 if (coarray
&& flag_coarray
== GFC_FCOARRAY_LIB
)
10880 tmp
= gfc_deallocate_with_status (to_se
.expr
, NULL_TREE
, NULL_TREE
,
10881 NULL_TREE
, NULL_TREE
, true, to_expr
,
10882 GFC_CAF_COARRAY_DEALLOCATE_ONLY
);
10883 gfc_add_expr_to_block (&block
, tmp
);
10885 tmp
= gfc_conv_descriptor_data_get (to_se
.expr
);
10886 cond
= fold_build2_loc (input_location
, EQ_EXPR
,
10887 logical_type_node
, tmp
,
10888 fold_convert (TREE_TYPE (tmp
),
10889 null_pointer_node
));
10890 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_sync_all
,
10891 3, null_pointer_node
, null_pointer_node
,
10892 build_int_cst (integer_type_node
, 0));
10894 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
,
10895 tmp
, build_empty_stmt (input_location
));
10896 gfc_add_expr_to_block (&block
, tmp
);
10900 if (to_expr
->ts
.type
== BT_DERIVED
10901 && to_expr
->ts
.u
.derived
->attr
.alloc_comp
)
10903 tmp
= gfc_deallocate_alloc_comp (to_expr
->ts
.u
.derived
,
10904 to_se
.expr
, to_expr
->rank
);
10905 gfc_add_expr_to_block (&block
, tmp
);
10908 tmp
= gfc_conv_descriptor_data_get (to_se
.expr
);
10909 tmp
= gfc_deallocate_with_status (tmp
, NULL_TREE
, NULL_TREE
, NULL_TREE
,
10910 NULL_TREE
, true, to_expr
,
10911 GFC_CAF_COARRAY_NOCOARRAY
);
10912 gfc_add_expr_to_block (&block
, tmp
);
10915 /* Move the pointer and update the array descriptor data. */
10916 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
, from_se
.expr
);
10918 /* Set "from" to NULL. */
10919 tmp
= gfc_conv_descriptor_data_get (from_se
.expr
);
10920 gfc_add_modify_loc (input_location
, &block
, tmp
,
10921 fold_convert (TREE_TYPE (tmp
), null_pointer_node
));
10924 if (to_expr
->ts
.type
== BT_CHARACTER
&& to_expr
->ts
.deferred
)
10926 gfc_add_modify_loc (input_location
, &block
, to_se
.string_length
,
10927 fold_convert (TREE_TYPE (to_se
.string_length
),
10928 from_se
.string_length
));
10929 if (from_expr
->ts
.deferred
)
10930 gfc_add_modify_loc (input_location
, &block
, from_se
.string_length
,
10931 build_int_cst (TREE_TYPE (from_se
.string_length
), 0));
10934 return gfc_finish_block (&block
);
10939 gfc_conv_intrinsic_subroutine (gfc_code
*code
)
10943 gcc_assert (code
->resolved_isym
);
10945 switch (code
->resolved_isym
->id
)
10947 case GFC_ISYM_MOVE_ALLOC
:
10948 res
= conv_intrinsic_move_alloc (code
);
10951 case GFC_ISYM_ATOMIC_CAS
:
10952 res
= conv_intrinsic_atomic_cas (code
);
10955 case GFC_ISYM_ATOMIC_ADD
:
10956 case GFC_ISYM_ATOMIC_AND
:
10957 case GFC_ISYM_ATOMIC_DEF
:
10958 case GFC_ISYM_ATOMIC_OR
:
10959 case GFC_ISYM_ATOMIC_XOR
:
10960 case GFC_ISYM_ATOMIC_FETCH_ADD
:
10961 case GFC_ISYM_ATOMIC_FETCH_AND
:
10962 case GFC_ISYM_ATOMIC_FETCH_OR
:
10963 case GFC_ISYM_ATOMIC_FETCH_XOR
:
10964 res
= conv_intrinsic_atomic_op (code
);
10967 case GFC_ISYM_ATOMIC_REF
:
10968 res
= conv_intrinsic_atomic_ref (code
);
10971 case GFC_ISYM_EVENT_QUERY
:
10972 res
= conv_intrinsic_event_query (code
);
10975 case GFC_ISYM_C_F_POINTER
:
10976 case GFC_ISYM_C_F_PROCPOINTER
:
10977 res
= conv_isocbinding_subroutine (code
);
10980 case GFC_ISYM_CAF_SEND
:
10981 res
= conv_caf_send (code
);
10984 case GFC_ISYM_CO_BROADCAST
:
10985 case GFC_ISYM_CO_MIN
:
10986 case GFC_ISYM_CO_MAX
:
10987 case GFC_ISYM_CO_REDUCE
:
10988 case GFC_ISYM_CO_SUM
:
10989 res
= conv_co_collective (code
);
10992 case GFC_ISYM_FREE
:
10993 res
= conv_intrinsic_free (code
);
10996 case GFC_ISYM_KILL
:
10997 res
= conv_intrinsic_kill_sub (code
);
11000 case GFC_ISYM_SYSTEM_CLOCK
:
11001 res
= conv_intrinsic_system_clock (code
);
11012 #include "gt-fortran-trans-intrinsic.h"