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 RANDOM_INIT library subroutine with a hidden argument for
3639 handling seeding on coarray images. */
3642 conv_intrinsic_random_init (gfc_code
*code
)
3646 tree arg1
, arg2
, arg3
, tmp
;
3647 tree logical4_type_node
= gfc_get_logical_type (4);
3649 /* Make the function call. */
3650 gfc_init_block (&block
);
3651 gfc_init_se (&se
, NULL
);
3653 /* Convert REPEATABLE to a LOGICAL(4) entity. */
3654 gfc_conv_expr (&se
, code
->ext
.actual
->expr
);
3655 gfc_add_block_to_block (&block
, &se
.pre
);
3656 arg1
= fold_convert (logical4_type_node
, gfc_evaluate_now (se
.expr
, &block
));
3657 gfc_add_block_to_block (&block
, &se
.post
);
3659 /* Convert IMAGE_DISTINCT to a LOGICAL(4) entity. */
3660 gfc_conv_expr (&se
, code
->ext
.actual
->next
->expr
);
3661 gfc_add_block_to_block (&block
, &se
.pre
);
3662 arg2
= fold_convert (logical4_type_node
, gfc_evaluate_now (se
.expr
, &block
));
3663 gfc_add_block_to_block (&block
, &se
.post
);
3665 /* Create the hidden argument. For non-coarray codes and -fcoarray=single,
3666 simply set this to 0. For -fcoarray=lib, generate a call to
3667 THIS_IMAGE() without arguments. */
3668 arg3
= build_int_cst (gfc_get_int_type (4), 0);
3669 if (flag_coarray
== GFC_FCOARRAY_LIB
)
3671 arg3
= build_call_expr_loc (input_location
, gfor_fndecl_caf_this_image
,
3673 se
.expr
= fold_convert (gfc_get_int_type (4), arg3
);
3676 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_random_init
, 3,
3678 gfc_add_expr_to_block (&block
, tmp
);
3680 return gfc_finish_block (&block
);
3684 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
3688 conv_intrinsic_system_clock (gfc_code
*code
)
3691 gfc_se count_se
, count_rate_se
, count_max_se
;
3692 tree arg1
= NULL_TREE
, arg2
= NULL_TREE
, arg3
= NULL_TREE
;
3696 gfc_expr
*count
= code
->ext
.actual
->expr
;
3697 gfc_expr
*count_rate
= code
->ext
.actual
->next
->expr
;
3698 gfc_expr
*count_max
= code
->ext
.actual
->next
->next
->expr
;
3700 /* Evaluate our arguments. */
3703 gfc_init_se (&count_se
, NULL
);
3704 gfc_conv_expr (&count_se
, count
);
3709 gfc_init_se (&count_rate_se
, NULL
);
3710 gfc_conv_expr (&count_rate_se
, count_rate
);
3715 gfc_init_se (&count_max_se
, NULL
);
3716 gfc_conv_expr (&count_max_se
, count_max
);
3719 /* Find the smallest kind found of the arguments. */
3721 least
= (count
&& count
->ts
.kind
< least
) ? count
->ts
.kind
: least
;
3722 least
= (count_rate
&& count_rate
->ts
.kind
< least
) ? count_rate
->ts
.kind
3724 least
= (count_max
&& count_max
->ts
.kind
< least
) ? count_max
->ts
.kind
3727 /* Prepare temporary variables. */
3732 arg1
= gfc_create_var (gfc_get_int_type (8), "count");
3733 else if (least
== 4)
3734 arg1
= gfc_create_var (gfc_get_int_type (4), "count");
3735 else if (count
->ts
.kind
== 1)
3736 arg1
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[0].pedantic_min_int
,
3739 arg1
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[1].pedantic_min_int
,
3746 arg2
= gfc_create_var (gfc_get_int_type (8), "count_rate");
3747 else if (least
== 4)
3748 arg2
= gfc_create_var (gfc_get_int_type (4), "count_rate");
3750 arg2
= integer_zero_node
;
3756 arg3
= gfc_create_var (gfc_get_int_type (8), "count_max");
3757 else if (least
== 4)
3758 arg3
= gfc_create_var (gfc_get_int_type (4), "count_max");
3760 arg3
= integer_zero_node
;
3763 /* Make the function call. */
3764 gfc_init_block (&block
);
3770 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
3771 : null_pointer_node
;
3772 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
3773 : null_pointer_node
;
3774 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
3775 : null_pointer_node
;
3780 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
3781 : null_pointer_node
;
3782 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
3783 : null_pointer_node
;
3784 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
3785 : null_pointer_node
;
3792 tmp
= build_call_expr_loc (input_location
,
3793 gfor_fndecl_system_clock4
, 3,
3794 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
3795 : null_pointer_node
,
3796 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
3797 : null_pointer_node
,
3798 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
3799 : null_pointer_node
);
3800 gfc_add_expr_to_block (&block
, tmp
);
3802 /* Handle kind>=8, 10, or 16 arguments */
3805 tmp
= build_call_expr_loc (input_location
,
3806 gfor_fndecl_system_clock8
, 3,
3807 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
3808 : null_pointer_node
,
3809 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
3810 : null_pointer_node
,
3811 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
3812 : null_pointer_node
);
3813 gfc_add_expr_to_block (&block
, tmp
);
3817 /* And store values back if needed. */
3818 if (arg1
&& arg1
!= count_se
.expr
)
3819 gfc_add_modify (&block
, count_se
.expr
,
3820 fold_convert (TREE_TYPE (count_se
.expr
), arg1
));
3821 if (arg2
&& arg2
!= count_rate_se
.expr
)
3822 gfc_add_modify (&block
, count_rate_se
.expr
,
3823 fold_convert (TREE_TYPE (count_rate_se
.expr
), arg2
));
3824 if (arg3
&& arg3
!= count_max_se
.expr
)
3825 gfc_add_modify (&block
, count_max_se
.expr
,
3826 fold_convert (TREE_TYPE (count_max_se
.expr
), arg3
));
3828 return gfc_finish_block (&block
);
3832 /* Return a character string containing the tty name. */
3835 gfc_conv_intrinsic_ttynam (gfc_se
* se
, gfc_expr
* expr
)
3843 unsigned int num_args
;
3845 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
3846 args
= XALLOCAVEC (tree
, num_args
);
3848 var
= gfc_create_var (pchar_type_node
, "pstr");
3849 len
= gfc_create_var (gfc_charlen_type_node
, "len");
3851 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
3852 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
3853 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
3855 fndecl
= build_addr (gfor_fndecl_ttynam
);
3856 tmp
= build_call_array_loc (input_location
,
3857 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam
)),
3858 fndecl
, num_args
, args
);
3859 gfc_add_expr_to_block (&se
->pre
, tmp
);
3861 /* Free the temporary afterwards, if necessary. */
3862 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
3863 len
, build_int_cst (TREE_TYPE (len
), 0));
3864 tmp
= gfc_call_free (var
);
3865 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
3866 gfc_add_expr_to_block (&se
->post
, tmp
);
3869 se
->string_length
= len
;
3873 /* Get the minimum/maximum value of all the parameters.
3874 minmax (a1, a2, a3, ...)
3877 if (a2 .op. mvar || isnan (mvar))
3879 if (a3 .op. mvar || isnan (mvar))
3886 /* TODO: Mismatching types can occur when specific names are used.
3887 These should be handled during resolution. */
3889 gfc_conv_intrinsic_minmax (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
3897 gfc_actual_arglist
*argexpr
;
3898 unsigned int i
, nargs
;
3900 nargs
= gfc_intrinsic_argument_list_length (expr
);
3901 args
= XALLOCAVEC (tree
, nargs
);
3903 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
3904 type
= gfc_typenode_for_spec (&expr
->ts
);
3906 argexpr
= expr
->value
.function
.actual
;
3907 if (TREE_TYPE (args
[0]) != type
)
3908 args
[0] = convert (type
, args
[0]);
3909 /* Only evaluate the argument once. */
3910 if (!VAR_P (args
[0]) && !TREE_CONSTANT (args
[0]))
3911 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
3913 mvar
= gfc_create_var (type
, "M");
3914 gfc_add_modify (&se
->pre
, mvar
, args
[0]);
3915 for (i
= 1, argexpr
= argexpr
->next
; i
< nargs
; i
++)
3921 /* Handle absent optional arguments by ignoring the comparison. */
3922 if (argexpr
->expr
->expr_type
== EXPR_VARIABLE
3923 && argexpr
->expr
->symtree
->n
.sym
->attr
.optional
3924 && TREE_CODE (val
) == INDIRECT_REF
)
3925 cond
= fold_build2_loc (input_location
,
3926 NE_EXPR
, logical_type_node
,
3927 TREE_OPERAND (val
, 0),
3928 build_int_cst (TREE_TYPE (TREE_OPERAND (val
, 0)), 0));
3933 /* Only evaluate the argument once. */
3934 if (!VAR_P (val
) && !TREE_CONSTANT (val
))
3935 val
= gfc_evaluate_now (val
, &se
->pre
);
3938 thencase
= build2_v (MODIFY_EXPR
, mvar
, convert (type
, val
));
3940 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
,
3941 convert (type
, val
), mvar
);
3943 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
3944 __builtin_isnan might be made dependent on that module being loaded,
3945 to help performance of programs that don't rely on IEEE semantics. */
3946 if (FLOAT_TYPE_P (TREE_TYPE (mvar
)))
3948 isnan
= build_call_expr_loc (input_location
,
3949 builtin_decl_explicit (BUILT_IN_ISNAN
),
3951 tmp
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
3952 logical_type_node
, tmp
,
3953 fold_convert (logical_type_node
, isnan
));
3955 tmp
= build3_v (COND_EXPR
, tmp
, thencase
,
3956 build_empty_stmt (input_location
));
3958 if (cond
!= NULL_TREE
)
3959 tmp
= build3_v (COND_EXPR
, cond
, tmp
,
3960 build_empty_stmt (input_location
));
3962 gfc_add_expr_to_block (&se
->pre
, tmp
);
3963 argexpr
= argexpr
->next
;
3969 /* Generate library calls for MIN and MAX intrinsics for character
3972 gfc_conv_intrinsic_minmax_char (gfc_se
* se
, gfc_expr
* expr
, int op
)
3975 tree var
, len
, fndecl
, tmp
, cond
, function
;
3978 nargs
= gfc_intrinsic_argument_list_length (expr
);
3979 args
= XALLOCAVEC (tree
, nargs
+ 4);
3980 gfc_conv_intrinsic_function_args (se
, expr
, &args
[4], nargs
);
3982 /* Create the result variables. */
3983 len
= gfc_create_var (gfc_charlen_type_node
, "len");
3984 args
[0] = gfc_build_addr_expr (NULL_TREE
, len
);
3985 var
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
), "pstr");
3986 args
[1] = gfc_build_addr_expr (ppvoid_type_node
, var
);
3987 args
[2] = build_int_cst (integer_type_node
, op
);
3988 args
[3] = build_int_cst (integer_type_node
, nargs
/ 2);
3990 if (expr
->ts
.kind
== 1)
3991 function
= gfor_fndecl_string_minmax
;
3992 else if (expr
->ts
.kind
== 4)
3993 function
= gfor_fndecl_string_minmax_char4
;
3997 /* Make the function call. */
3998 fndecl
= build_addr (function
);
3999 tmp
= build_call_array_loc (input_location
,
4000 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
4002 gfc_add_expr_to_block (&se
->pre
, tmp
);
4004 /* Free the temporary afterwards, if necessary. */
4005 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
4006 len
, build_int_cst (TREE_TYPE (len
), 0));
4007 tmp
= gfc_call_free (var
);
4008 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
4009 gfc_add_expr_to_block (&se
->post
, tmp
);
4012 se
->string_length
= len
;
4016 /* Create a symbol node for this intrinsic. The symbol from the frontend
4017 has the generic name. */
4020 gfc_get_symbol_for_expr (gfc_expr
* expr
, bool ignore_optional
)
4024 /* TODO: Add symbols for intrinsic function to the global namespace. */
4025 gcc_assert (strlen (expr
->value
.function
.name
) <= GFC_MAX_SYMBOL_LEN
- 5);
4026 sym
= gfc_new_symbol (expr
->value
.function
.name
, NULL
);
4029 sym
->attr
.external
= 1;
4030 sym
->attr
.function
= 1;
4031 sym
->attr
.always_explicit
= 1;
4032 sym
->attr
.proc
= PROC_INTRINSIC
;
4033 sym
->attr
.flavor
= FL_PROCEDURE
;
4037 sym
->attr
.dimension
= 1;
4038 sym
->as
= gfc_get_array_spec ();
4039 sym
->as
->type
= AS_ASSUMED_SHAPE
;
4040 sym
->as
->rank
= expr
->rank
;
4043 gfc_copy_formal_args_intr (sym
, expr
->value
.function
.isym
,
4044 ignore_optional
? expr
->value
.function
.actual
4050 /* Generate a call to an external intrinsic function. */
4052 gfc_conv_intrinsic_funcall (gfc_se
* se
, gfc_expr
* expr
)
4055 vec
<tree
, va_gc
> *append_args
;
4057 gcc_assert (!se
->ss
|| se
->ss
->info
->expr
== expr
);
4060 gcc_assert (expr
->rank
> 0);
4062 gcc_assert (expr
->rank
== 0);
4064 sym
= gfc_get_symbol_for_expr (expr
, se
->ignore_optional
);
4066 /* Calls to libgfortran_matmul need to be appended special arguments,
4067 to be able to call the BLAS ?gemm functions if required and possible. */
4069 if (expr
->value
.function
.isym
->id
== GFC_ISYM_MATMUL
4070 && sym
->ts
.type
!= BT_LOGICAL
)
4072 tree cint
= gfc_get_int_type (gfc_c_int_kind
);
4074 if (flag_external_blas
4075 && (sym
->ts
.type
== BT_REAL
|| sym
->ts
.type
== BT_COMPLEX
)
4076 && (sym
->ts
.kind
== 4 || sym
->ts
.kind
== 8))
4080 if (sym
->ts
.type
== BT_REAL
)
4082 if (sym
->ts
.kind
== 4)
4083 gemm_fndecl
= gfor_fndecl_sgemm
;
4085 gemm_fndecl
= gfor_fndecl_dgemm
;
4089 if (sym
->ts
.kind
== 4)
4090 gemm_fndecl
= gfor_fndecl_cgemm
;
4092 gemm_fndecl
= gfor_fndecl_zgemm
;
4095 vec_alloc (append_args
, 3);
4096 append_args
->quick_push (build_int_cst (cint
, 1));
4097 append_args
->quick_push (build_int_cst (cint
,
4098 flag_blas_matmul_limit
));
4099 append_args
->quick_push (gfc_build_addr_expr (NULL_TREE
,
4104 vec_alloc (append_args
, 3);
4105 append_args
->quick_push (build_int_cst (cint
, 0));
4106 append_args
->quick_push (build_int_cst (cint
, 0));
4107 append_args
->quick_push (null_pointer_node
);
4111 gfc_conv_procedure_call (se
, sym
, expr
->value
.function
.actual
, expr
,
4113 gfc_free_symbol (sym
);
4116 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
4136 gfc_conv_intrinsic_anyall (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
4145 gfc_actual_arglist
*actual
;
4152 gfc_conv_intrinsic_funcall (se
, expr
);
4156 actual
= expr
->value
.function
.actual
;
4157 type
= gfc_typenode_for_spec (&expr
->ts
);
4158 /* Initialize the result. */
4159 resvar
= gfc_create_var (type
, "test");
4161 tmp
= convert (type
, boolean_true_node
);
4163 tmp
= convert (type
, boolean_false_node
);
4164 gfc_add_modify (&se
->pre
, resvar
, tmp
);
4166 /* Walk the arguments. */
4167 arrayss
= gfc_walk_expr (actual
->expr
);
4168 gcc_assert (arrayss
!= gfc_ss_terminator
);
4170 /* Initialize the scalarizer. */
4171 gfc_init_loopinfo (&loop
);
4172 exit_label
= gfc_build_label_decl (NULL_TREE
);
4173 TREE_USED (exit_label
) = 1;
4174 gfc_add_ss_to_loop (&loop
, arrayss
);
4176 /* Initialize the loop. */
4177 gfc_conv_ss_startstride (&loop
);
4178 gfc_conv_loop_setup (&loop
, &expr
->where
);
4180 gfc_mark_ss_chain_used (arrayss
, 1);
4181 /* Generate the loop body. */
4182 gfc_start_scalarized_body (&loop
, &body
);
4184 /* If the condition matches then set the return value. */
4185 gfc_start_block (&block
);
4187 tmp
= convert (type
, boolean_false_node
);
4189 tmp
= convert (type
, boolean_true_node
);
4190 gfc_add_modify (&block
, resvar
, tmp
);
4192 /* And break out of the loop. */
4193 tmp
= build1_v (GOTO_EXPR
, exit_label
);
4194 gfc_add_expr_to_block (&block
, tmp
);
4196 found
= gfc_finish_block (&block
);
4198 /* Check this element. */
4199 gfc_init_se (&arrayse
, NULL
);
4200 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
4201 arrayse
.ss
= arrayss
;
4202 gfc_conv_expr_val (&arrayse
, actual
->expr
);
4204 gfc_add_block_to_block (&body
, &arrayse
.pre
);
4205 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
, arrayse
.expr
,
4206 build_int_cst (TREE_TYPE (arrayse
.expr
), 0));
4207 tmp
= build3_v (COND_EXPR
, tmp
, found
, build_empty_stmt (input_location
));
4208 gfc_add_expr_to_block (&body
, tmp
);
4209 gfc_add_block_to_block (&body
, &arrayse
.post
);
4211 gfc_trans_scalarizing_loops (&loop
, &body
);
4213 /* Add the exit label. */
4214 tmp
= build1_v (LABEL_EXPR
, exit_label
);
4215 gfc_add_expr_to_block (&loop
.pre
, tmp
);
4217 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
4218 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
4219 gfc_cleanup_loop (&loop
);
4224 /* COUNT(A) = Number of true elements in A. */
4226 gfc_conv_intrinsic_count (gfc_se
* se
, gfc_expr
* expr
)
4233 gfc_actual_arglist
*actual
;
4239 gfc_conv_intrinsic_funcall (se
, expr
);
4243 actual
= expr
->value
.function
.actual
;
4245 type
= gfc_typenode_for_spec (&expr
->ts
);
4246 /* Initialize the result. */
4247 resvar
= gfc_create_var (type
, "count");
4248 gfc_add_modify (&se
->pre
, resvar
, build_int_cst (type
, 0));
4250 /* Walk the arguments. */
4251 arrayss
= gfc_walk_expr (actual
->expr
);
4252 gcc_assert (arrayss
!= gfc_ss_terminator
);
4254 /* Initialize the scalarizer. */
4255 gfc_init_loopinfo (&loop
);
4256 gfc_add_ss_to_loop (&loop
, arrayss
);
4258 /* Initialize the loop. */
4259 gfc_conv_ss_startstride (&loop
);
4260 gfc_conv_loop_setup (&loop
, &expr
->where
);
4262 gfc_mark_ss_chain_used (arrayss
, 1);
4263 /* Generate the loop body. */
4264 gfc_start_scalarized_body (&loop
, &body
);
4266 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (resvar
),
4267 resvar
, build_int_cst (TREE_TYPE (resvar
), 1));
4268 tmp
= build2_v (MODIFY_EXPR
, resvar
, tmp
);
4270 gfc_init_se (&arrayse
, NULL
);
4271 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
4272 arrayse
.ss
= arrayss
;
4273 gfc_conv_expr_val (&arrayse
, actual
->expr
);
4274 tmp
= build3_v (COND_EXPR
, arrayse
.expr
, tmp
,
4275 build_empty_stmt (input_location
));
4277 gfc_add_block_to_block (&body
, &arrayse
.pre
);
4278 gfc_add_expr_to_block (&body
, tmp
);
4279 gfc_add_block_to_block (&body
, &arrayse
.post
);
4281 gfc_trans_scalarizing_loops (&loop
, &body
);
4283 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
4284 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
4285 gfc_cleanup_loop (&loop
);
4291 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
4292 struct and return the corresponding loopinfo. */
4294 static gfc_loopinfo
*
4295 enter_nested_loop (gfc_se
*se
)
4297 se
->ss
= se
->ss
->nested_ss
;
4298 gcc_assert (se
->ss
== se
->ss
->loop
->ss
);
4300 return se
->ss
->loop
;
4304 /* Inline implementation of the sum and product intrinsics. */
4306 gfc_conv_intrinsic_arith (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
,
4310 tree scale
= NULL_TREE
;
4315 gfc_loopinfo loop
, *ploop
;
4316 gfc_actual_arglist
*arg_array
, *arg_mask
;
4317 gfc_ss
*arrayss
= NULL
;
4318 gfc_ss
*maskss
= NULL
;
4322 gfc_expr
*arrayexpr
;
4327 gcc_assert (gfc_inline_intrinsic_function_p (expr
));
4333 type
= gfc_typenode_for_spec (&expr
->ts
);
4334 /* Initialize the result. */
4335 resvar
= gfc_create_var (type
, "val");
4340 scale
= gfc_create_var (type
, "scale");
4341 gfc_add_modify (&se
->pre
, scale
,
4342 gfc_build_const (type
, integer_one_node
));
4343 tmp
= gfc_build_const (type
, integer_zero_node
);
4345 else if (op
== PLUS_EXPR
|| op
== BIT_IOR_EXPR
|| op
== BIT_XOR_EXPR
)
4346 tmp
= gfc_build_const (type
, integer_zero_node
);
4347 else if (op
== NE_EXPR
)
4349 tmp
= convert (type
, boolean_false_node
);
4350 else if (op
== BIT_AND_EXPR
)
4351 tmp
= gfc_build_const (type
, fold_build1_loc (input_location
, NEGATE_EXPR
,
4352 type
, integer_one_node
));
4354 tmp
= gfc_build_const (type
, integer_one_node
);
4356 gfc_add_modify (&se
->pre
, resvar
, tmp
);
4358 arg_array
= expr
->value
.function
.actual
;
4360 arrayexpr
= arg_array
->expr
;
4362 if (op
== NE_EXPR
|| norm2
)
4363 /* PARITY and NORM2. */
4367 arg_mask
= arg_array
->next
->next
;
4368 gcc_assert (arg_mask
!= NULL
);
4369 maskexpr
= arg_mask
->expr
;
4372 if (expr
->rank
== 0)
4374 /* Walk the arguments. */
4375 arrayss
= gfc_walk_expr (arrayexpr
);
4376 gcc_assert (arrayss
!= gfc_ss_terminator
);
4378 if (maskexpr
&& maskexpr
->rank
> 0)
4380 maskss
= gfc_walk_expr (maskexpr
);
4381 gcc_assert (maskss
!= gfc_ss_terminator
);
4386 /* Initialize the scalarizer. */
4387 gfc_init_loopinfo (&loop
);
4388 gfc_add_ss_to_loop (&loop
, arrayss
);
4389 if (maskexpr
&& maskexpr
->rank
> 0)
4390 gfc_add_ss_to_loop (&loop
, maskss
);
4392 /* Initialize the loop. */
4393 gfc_conv_ss_startstride (&loop
);
4394 gfc_conv_loop_setup (&loop
, &expr
->where
);
4396 gfc_mark_ss_chain_used (arrayss
, 1);
4397 if (maskexpr
&& maskexpr
->rank
> 0)
4398 gfc_mark_ss_chain_used (maskss
, 1);
4403 /* All the work has been done in the parent loops. */
4404 ploop
= enter_nested_loop (se
);
4408 /* Generate the loop body. */
4409 gfc_start_scalarized_body (ploop
, &body
);
4411 /* If we have a mask, only add this element if the mask is set. */
4412 if (maskexpr
&& maskexpr
->rank
> 0)
4414 gfc_init_se (&maskse
, parent_se
);
4415 gfc_copy_loopinfo_to_se (&maskse
, ploop
);
4416 if (expr
->rank
== 0)
4418 gfc_conv_expr_val (&maskse
, maskexpr
);
4419 gfc_add_block_to_block (&body
, &maskse
.pre
);
4421 gfc_start_block (&block
);
4424 gfc_init_block (&block
);
4426 /* Do the actual summation/product. */
4427 gfc_init_se (&arrayse
, parent_se
);
4428 gfc_copy_loopinfo_to_se (&arrayse
, ploop
);
4429 if (expr
->rank
== 0)
4430 arrayse
.ss
= arrayss
;
4431 gfc_conv_expr_val (&arrayse
, arrayexpr
);
4432 gfc_add_block_to_block (&block
, &arrayse
.pre
);
4436 /* if (x (i) != 0.0)
4442 result = 1.0 + result * val * val;
4448 result += val * val;
4451 tree res1
, res2
, cond
, absX
, val
;
4452 stmtblock_t ifblock1
, ifblock2
, ifblock3
;
4454 gfc_init_block (&ifblock1
);
4456 absX
= gfc_create_var (type
, "absX");
4457 gfc_add_modify (&ifblock1
, absX
,
4458 fold_build1_loc (input_location
, ABS_EXPR
, type
,
4460 val
= gfc_create_var (type
, "val");
4461 gfc_add_expr_to_block (&ifblock1
, val
);
4463 gfc_init_block (&ifblock2
);
4464 gfc_add_modify (&ifblock2
, val
,
4465 fold_build2_loc (input_location
, RDIV_EXPR
, type
, scale
,
4467 res1
= fold_build2_loc (input_location
, MULT_EXPR
, type
, val
, val
);
4468 res1
= fold_build2_loc (input_location
, MULT_EXPR
, type
, resvar
, res1
);
4469 res1
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, res1
,
4470 gfc_build_const (type
, integer_one_node
));
4471 gfc_add_modify (&ifblock2
, resvar
, res1
);
4472 gfc_add_modify (&ifblock2
, scale
, absX
);
4473 res1
= gfc_finish_block (&ifblock2
);
4475 gfc_init_block (&ifblock3
);
4476 gfc_add_modify (&ifblock3
, val
,
4477 fold_build2_loc (input_location
, RDIV_EXPR
, type
, absX
,
4479 res2
= fold_build2_loc (input_location
, MULT_EXPR
, type
, val
, val
);
4480 res2
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, resvar
, res2
);
4481 gfc_add_modify (&ifblock3
, resvar
, res2
);
4482 res2
= gfc_finish_block (&ifblock3
);
4484 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
4486 tmp
= build3_v (COND_EXPR
, cond
, res1
, res2
);
4487 gfc_add_expr_to_block (&ifblock1
, tmp
);
4488 tmp
= gfc_finish_block (&ifblock1
);
4490 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
4492 gfc_build_const (type
, integer_zero_node
));
4494 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
4495 gfc_add_expr_to_block (&block
, tmp
);
4499 tmp
= fold_build2_loc (input_location
, op
, type
, resvar
, arrayse
.expr
);
4500 gfc_add_modify (&block
, resvar
, tmp
);
4503 gfc_add_block_to_block (&block
, &arrayse
.post
);
4505 if (maskexpr
&& maskexpr
->rank
> 0)
4507 /* We enclose the above in if (mask) {...} . */
4509 tmp
= gfc_finish_block (&block
);
4510 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
4511 build_empty_stmt (input_location
));
4514 tmp
= gfc_finish_block (&block
);
4515 gfc_add_expr_to_block (&body
, tmp
);
4517 gfc_trans_scalarizing_loops (ploop
, &body
);
4519 /* For a scalar mask, enclose the loop in an if statement. */
4520 if (maskexpr
&& maskexpr
->rank
== 0)
4522 gfc_init_block (&block
);
4523 gfc_add_block_to_block (&block
, &ploop
->pre
);
4524 gfc_add_block_to_block (&block
, &ploop
->post
);
4525 tmp
= gfc_finish_block (&block
);
4529 tmp
= build3_v (COND_EXPR
, se
->ss
->info
->data
.scalar
.value
, tmp
,
4530 build_empty_stmt (input_location
));
4531 gfc_advance_se_ss_chain (se
);
4535 gcc_assert (expr
->rank
== 0);
4536 gfc_init_se (&maskse
, NULL
);
4537 gfc_conv_expr_val (&maskse
, maskexpr
);
4538 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
4539 build_empty_stmt (input_location
));
4542 gfc_add_expr_to_block (&block
, tmp
);
4543 gfc_add_block_to_block (&se
->pre
, &block
);
4544 gcc_assert (se
->post
.head
== NULL
);
4548 gfc_add_block_to_block (&se
->pre
, &ploop
->pre
);
4549 gfc_add_block_to_block (&se
->pre
, &ploop
->post
);
4552 if (expr
->rank
== 0)
4553 gfc_cleanup_loop (ploop
);
4557 /* result = scale * sqrt(result). */
4559 sqrt
= gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT
, expr
->ts
.kind
);
4560 resvar
= build_call_expr_loc (input_location
,
4562 resvar
= fold_build2_loc (input_location
, MULT_EXPR
, type
, scale
, resvar
);
4569 /* Inline implementation of the dot_product intrinsic. This function
4570 is based on gfc_conv_intrinsic_arith (the previous function). */
4572 gfc_conv_intrinsic_dot_product (gfc_se
* se
, gfc_expr
* expr
)
4580 gfc_actual_arglist
*actual
;
4581 gfc_ss
*arrayss1
, *arrayss2
;
4582 gfc_se arrayse1
, arrayse2
;
4583 gfc_expr
*arrayexpr1
, *arrayexpr2
;
4585 type
= gfc_typenode_for_spec (&expr
->ts
);
4587 /* Initialize the result. */
4588 resvar
= gfc_create_var (type
, "val");
4589 if (expr
->ts
.type
== BT_LOGICAL
)
4590 tmp
= build_int_cst (type
, 0);
4592 tmp
= gfc_build_const (type
, integer_zero_node
);
4594 gfc_add_modify (&se
->pre
, resvar
, tmp
);
4596 /* Walk argument #1. */
4597 actual
= expr
->value
.function
.actual
;
4598 arrayexpr1
= actual
->expr
;
4599 arrayss1
= gfc_walk_expr (arrayexpr1
);
4600 gcc_assert (arrayss1
!= gfc_ss_terminator
);
4602 /* Walk argument #2. */
4603 actual
= actual
->next
;
4604 arrayexpr2
= actual
->expr
;
4605 arrayss2
= gfc_walk_expr (arrayexpr2
);
4606 gcc_assert (arrayss2
!= gfc_ss_terminator
);
4608 /* Initialize the scalarizer. */
4609 gfc_init_loopinfo (&loop
);
4610 gfc_add_ss_to_loop (&loop
, arrayss1
);
4611 gfc_add_ss_to_loop (&loop
, arrayss2
);
4613 /* Initialize the loop. */
4614 gfc_conv_ss_startstride (&loop
);
4615 gfc_conv_loop_setup (&loop
, &expr
->where
);
4617 gfc_mark_ss_chain_used (arrayss1
, 1);
4618 gfc_mark_ss_chain_used (arrayss2
, 1);
4620 /* Generate the loop body. */
4621 gfc_start_scalarized_body (&loop
, &body
);
4622 gfc_init_block (&block
);
4624 /* Make the tree expression for [conjg(]array1[)]. */
4625 gfc_init_se (&arrayse1
, NULL
);
4626 gfc_copy_loopinfo_to_se (&arrayse1
, &loop
);
4627 arrayse1
.ss
= arrayss1
;
4628 gfc_conv_expr_val (&arrayse1
, arrayexpr1
);
4629 if (expr
->ts
.type
== BT_COMPLEX
)
4630 arrayse1
.expr
= fold_build1_loc (input_location
, CONJ_EXPR
, type
,
4632 gfc_add_block_to_block (&block
, &arrayse1
.pre
);
4634 /* Make the tree expression for array2. */
4635 gfc_init_se (&arrayse2
, NULL
);
4636 gfc_copy_loopinfo_to_se (&arrayse2
, &loop
);
4637 arrayse2
.ss
= arrayss2
;
4638 gfc_conv_expr_val (&arrayse2
, arrayexpr2
);
4639 gfc_add_block_to_block (&block
, &arrayse2
.pre
);
4641 /* Do the actual product and sum. */
4642 if (expr
->ts
.type
== BT_LOGICAL
)
4644 tmp
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
, type
,
4645 arrayse1
.expr
, arrayse2
.expr
);
4646 tmp
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
, type
, resvar
, tmp
);
4650 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, type
, arrayse1
.expr
,
4652 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, resvar
, tmp
);
4654 gfc_add_modify (&block
, resvar
, tmp
);
4656 /* Finish up the loop block and the loop. */
4657 tmp
= gfc_finish_block (&block
);
4658 gfc_add_expr_to_block (&body
, tmp
);
4660 gfc_trans_scalarizing_loops (&loop
, &body
);
4661 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
4662 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
4663 gfc_cleanup_loop (&loop
);
4669 /* Emit code for minloc or maxloc intrinsic. There are many different cases
4670 we need to handle. For performance reasons we sometimes create two
4671 loops instead of one, where the second one is much simpler.
4672 Examples for minloc intrinsic:
4673 1) Result is an array, a call is generated
4674 2) Array mask is used and NaNs need to be supported:
4680 if (pos == 0) pos = S + (1 - from);
4681 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4688 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4692 3) NaNs need to be supported, but it is known at compile time or cheaply
4693 at runtime whether array is nonempty or not:
4698 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4701 if (from <= to) pos = 1;
4705 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4709 4) NaNs aren't supported, array mask is used:
4710 limit = infinities_supported ? Infinity : huge (limit);
4714 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
4720 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4724 5) Same without array mask:
4725 limit = infinities_supported ? Infinity : huge (limit);
4726 pos = (from <= to) ? 1 : 0;
4729 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
4732 For 3) and 5), if mask is scalar, this all goes into a conditional,
4733 setting pos = 0; in the else branch.
4735 Since we now also support the BACK argument, instead of using
4736 if (a[S] < limit), we now use
4739 cond = a[S] <= limit;
4741 cond = a[S] < limit;
4745 The optimizer is smart enough to move the condition out of the loop.
4746 The are now marked as unlikely to for further speedup. */
4749 gfc_conv_intrinsic_minmaxloc (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
4753 stmtblock_t ifblock
;
4754 stmtblock_t elseblock
;
4766 gfc_actual_arglist
*actual
;
4771 gfc_expr
*arrayexpr
;
4778 actual
= expr
->value
.function
.actual
;
4780 /* The last argument, BACK, is passed by value. Ensure that
4781 by setting its name to %VAL. */
4782 for (gfc_actual_arglist
*a
= actual
; a
; a
= a
->next
)
4784 if (a
->next
== NULL
)
4790 gfc_conv_intrinsic_funcall (se
, expr
);
4794 arrayexpr
= actual
->expr
;
4796 /* Special case for character maxloc. Remove unneeded actual
4797 arguments, then call a library function. */
4799 if (arrayexpr
->ts
.type
== BT_CHARACTER
)
4801 gfc_actual_arglist
*a
, *b
;
4806 if (b
->expr
== NULL
|| strcmp (b
->name
, "dim") == 0)
4810 gfc_free_actual_arglist (b
);
4815 gfc_conv_intrinsic_funcall (se
, expr
);
4819 /* Initialize the result. */
4820 pos
= gfc_create_var (gfc_array_index_type
, "pos");
4821 offset
= gfc_create_var (gfc_array_index_type
, "offset");
4822 type
= gfc_typenode_for_spec (&expr
->ts
);
4824 /* Walk the arguments. */
4825 arrayss
= gfc_walk_expr (arrayexpr
);
4826 gcc_assert (arrayss
!= gfc_ss_terminator
);
4828 actual
= actual
->next
->next
;
4829 gcc_assert (actual
);
4830 maskexpr
= actual
->expr
;
4831 backexpr
= actual
->next
->next
->expr
;
4833 if (maskexpr
&& maskexpr
->rank
!= 0)
4835 maskss
= gfc_walk_expr (maskexpr
);
4836 gcc_assert (maskss
!= gfc_ss_terminator
);
4841 if (gfc_array_size (arrayexpr
, &asize
))
4843 nonempty
= gfc_conv_mpz_to_tree (asize
, gfc_index_integer_kind
);
4845 nonempty
= fold_build2_loc (input_location
, GT_EXPR
,
4846 logical_type_node
, nonempty
,
4847 gfc_index_zero_node
);
4852 limit
= gfc_create_var (gfc_typenode_for_spec (&arrayexpr
->ts
), "limit");
4853 switch (arrayexpr
->ts
.type
)
4856 tmp
= gfc_build_inf_or_huge (TREE_TYPE (limit
), arrayexpr
->ts
.kind
);
4860 n
= gfc_validate_kind (arrayexpr
->ts
.type
, arrayexpr
->ts
.kind
, false);
4861 tmp
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
,
4862 arrayexpr
->ts
.kind
);
4869 /* We start with the most negative possible value for MAXLOC, and the most
4870 positive possible value for MINLOC. The most negative possible value is
4871 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
4872 possible value is HUGE in both cases. */
4874 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (tmp
), tmp
);
4875 if (op
== GT_EXPR
&& arrayexpr
->ts
.type
== BT_INTEGER
)
4876 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (tmp
), tmp
,
4877 build_int_cst (TREE_TYPE (tmp
), 1));
4879 gfc_add_modify (&se
->pre
, limit
, tmp
);
4881 /* Initialize the scalarizer. */
4882 gfc_init_loopinfo (&loop
);
4883 gfc_add_ss_to_loop (&loop
, arrayss
);
4885 gfc_add_ss_to_loop (&loop
, maskss
);
4887 /* Initialize the loop. */
4888 gfc_conv_ss_startstride (&loop
);
4890 /* The code generated can have more than one loop in sequence (see the
4891 comment at the function header). This doesn't work well with the
4892 scalarizer, which changes arrays' offset when the scalarization loops
4893 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
4894 are currently inlined in the scalar case only (for which loop is of rank
4895 one). As there is no dependency to care about in that case, there is no
4896 temporary, so that we can use the scalarizer temporary code to handle
4897 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
4898 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
4900 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
4901 should eventually go away. We could either create two loops properly,
4902 or find another way to save/restore the array offsets between the two
4903 loops (without conflicting with temporary management), or use a single
4904 loop minmaxloc implementation. See PR 31067. */
4905 loop
.temp_dim
= loop
.dimen
;
4906 gfc_conv_loop_setup (&loop
, &expr
->where
);
4908 gcc_assert (loop
.dimen
== 1);
4909 if (nonempty
== NULL
&& maskss
== NULL
&& loop
.from
[0] && loop
.to
[0])
4910 nonempty
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
,
4911 loop
.from
[0], loop
.to
[0]);
4915 /* Initialize the position to zero, following Fortran 2003. We are free
4916 to do this because Fortran 95 allows the result of an entirely false
4917 mask to be processor dependent. If we know at compile time the array
4918 is non-empty and no MASK is used, we can initialize to 1 to simplify
4920 if (nonempty
!= NULL
&& !HONOR_NANS (DECL_MODE (limit
)))
4921 gfc_add_modify (&loop
.pre
, pos
,
4922 fold_build3_loc (input_location
, COND_EXPR
,
4923 gfc_array_index_type
,
4924 nonempty
, gfc_index_one_node
,
4925 gfc_index_zero_node
));
4928 gfc_add_modify (&loop
.pre
, pos
, gfc_index_zero_node
);
4929 lab1
= gfc_build_label_decl (NULL_TREE
);
4930 TREE_USED (lab1
) = 1;
4931 lab2
= gfc_build_label_decl (NULL_TREE
);
4932 TREE_USED (lab2
) = 1;
4935 /* An offset must be added to the loop
4936 counter to obtain the required position. */
4937 gcc_assert (loop
.from
[0]);
4939 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
4940 gfc_index_one_node
, loop
.from
[0]);
4941 gfc_add_modify (&loop
.pre
, offset
, tmp
);
4943 gfc_mark_ss_chain_used (arrayss
, lab1
? 3 : 1);
4945 gfc_mark_ss_chain_used (maskss
, lab1
? 3 : 1);
4946 /* Generate the loop body. */
4947 gfc_start_scalarized_body (&loop
, &body
);
4949 /* If we have a mask, only check this element if the mask is set. */
4952 gfc_init_se (&maskse
, NULL
);
4953 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
4955 gfc_conv_expr_val (&maskse
, maskexpr
);
4956 gfc_add_block_to_block (&body
, &maskse
.pre
);
4958 gfc_start_block (&block
);
4961 gfc_init_block (&block
);
4963 /* Compare with the current limit. */
4964 gfc_init_se (&arrayse
, NULL
);
4965 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
4966 arrayse
.ss
= arrayss
;
4967 gfc_conv_expr_val (&arrayse
, arrayexpr
);
4968 gfc_add_block_to_block (&block
, &arrayse
.pre
);
4970 gfc_init_se (&backse
, NULL
);
4971 gfc_conv_expr_val (&backse
, backexpr
);
4972 gfc_add_block_to_block (&block
, &backse
.pre
);
4974 /* We do the following if this is a more extreme value. */
4975 gfc_start_block (&ifblock
);
4977 /* Assign the value to the limit... */
4978 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
4980 if (nonempty
== NULL
&& HONOR_NANS (DECL_MODE (limit
)))
4982 stmtblock_t ifblock2
;
4985 gfc_start_block (&ifblock2
);
4986 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
),
4987 loop
.loopvar
[0], offset
);
4988 gfc_add_modify (&ifblock2
, pos
, tmp
);
4989 ifbody2
= gfc_finish_block (&ifblock2
);
4990 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, pos
,
4991 gfc_index_zero_node
);
4992 tmp
= build3_v (COND_EXPR
, cond
, ifbody2
,
4993 build_empty_stmt (input_location
));
4994 gfc_add_expr_to_block (&block
, tmp
);
4997 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
),
4998 loop
.loopvar
[0], offset
);
4999 gfc_add_modify (&ifblock
, pos
, tmp
);
5002 gfc_add_expr_to_block (&ifblock
, build1_v (GOTO_EXPR
, lab1
));
5004 ifbody
= gfc_finish_block (&ifblock
);
5006 if (!lab1
|| HONOR_NANS (DECL_MODE (limit
)))
5009 cond
= fold_build2_loc (input_location
,
5010 op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
5011 logical_type_node
, arrayse
.expr
, limit
);
5014 tree ifbody2
, elsebody2
;
5016 /* We switch to > or >= depending on the value of the BACK argument. */
5017 cond
= gfc_create_var (logical_type_node
, "cond");
5019 gfc_start_block (&ifblock
);
5020 b_if
= fold_build2_loc (input_location
, op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
5021 logical_type_node
, arrayse
.expr
, limit
);
5023 gfc_add_modify (&ifblock
, cond
, b_if
);
5024 ifbody2
= gfc_finish_block (&ifblock
);
5026 gfc_start_block (&elseblock
);
5027 b_else
= fold_build2_loc (input_location
, op
, logical_type_node
,
5028 arrayse
.expr
, limit
);
5030 gfc_add_modify (&elseblock
, cond
, b_else
);
5031 elsebody2
= gfc_finish_block (&elseblock
);
5033 tmp
= fold_build3_loc (input_location
, COND_EXPR
, logical_type_node
,
5034 backse
.expr
, ifbody2
, elsebody2
);
5036 gfc_add_expr_to_block (&block
, tmp
);
5039 cond
= gfc_unlikely (cond
, PRED_BUILTIN_EXPECT
);
5040 ifbody
= build3_v (COND_EXPR
, cond
, ifbody
,
5041 build_empty_stmt (input_location
));
5043 gfc_add_expr_to_block (&block
, ifbody
);
5047 /* We enclose the above in if (mask) {...}. */
5048 tmp
= gfc_finish_block (&block
);
5050 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
5051 build_empty_stmt (input_location
));
5054 tmp
= gfc_finish_block (&block
);
5055 gfc_add_expr_to_block (&body
, tmp
);
5059 gfc_trans_scalarized_loop_boundary (&loop
, &body
);
5061 if (HONOR_NANS (DECL_MODE (limit
)))
5063 if (nonempty
!= NULL
)
5065 ifbody
= build2_v (MODIFY_EXPR
, pos
, gfc_index_one_node
);
5066 tmp
= build3_v (COND_EXPR
, nonempty
, ifbody
,
5067 build_empty_stmt (input_location
));
5068 gfc_add_expr_to_block (&loop
.code
[0], tmp
);
5072 gfc_add_expr_to_block (&loop
.code
[0], build1_v (GOTO_EXPR
, lab2
));
5073 gfc_add_expr_to_block (&loop
.code
[0], build1_v (LABEL_EXPR
, lab1
));
5075 /* If we have a mask, only check this element if the mask is set. */
5078 gfc_init_se (&maskse
, NULL
);
5079 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
5081 gfc_conv_expr_val (&maskse
, maskexpr
);
5082 gfc_add_block_to_block (&body
, &maskse
.pre
);
5084 gfc_start_block (&block
);
5087 gfc_init_block (&block
);
5089 /* Compare with the current limit. */
5090 gfc_init_se (&arrayse
, NULL
);
5091 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
5092 arrayse
.ss
= arrayss
;
5093 gfc_conv_expr_val (&arrayse
, arrayexpr
);
5094 gfc_add_block_to_block (&block
, &arrayse
.pre
);
5096 /* We do the following if this is a more extreme value. */
5097 gfc_start_block (&ifblock
);
5099 /* Assign the value to the limit... */
5100 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
5102 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
),
5103 loop
.loopvar
[0], offset
);
5104 gfc_add_modify (&ifblock
, pos
, tmp
);
5106 ifbody
= gfc_finish_block (&ifblock
);
5108 /* We switch to > or >= depending on the value of the BACK argument. */
5110 tree ifbody2
, elsebody2
;
5112 cond
= gfc_create_var (logical_type_node
, "cond");
5114 gfc_start_block (&ifblock
);
5115 b_if
= fold_build2_loc (input_location
, op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
5116 logical_type_node
, arrayse
.expr
, limit
);
5118 gfc_add_modify (&ifblock
, cond
, b_if
);
5119 ifbody2
= gfc_finish_block (&ifblock
);
5121 gfc_start_block (&elseblock
);
5122 b_else
= fold_build2_loc (input_location
, op
, logical_type_node
,
5123 arrayse
.expr
, limit
);
5125 gfc_add_modify (&elseblock
, cond
, b_else
);
5126 elsebody2
= gfc_finish_block (&elseblock
);
5128 tmp
= fold_build3_loc (input_location
, COND_EXPR
, logical_type_node
,
5129 backse
.expr
, ifbody2
, elsebody2
);
5132 gfc_add_expr_to_block (&block
, tmp
);
5133 cond
= gfc_unlikely (cond
, PRED_BUILTIN_EXPECT
);
5134 tmp
= build3_v (COND_EXPR
, cond
, ifbody
,
5135 build_empty_stmt (input_location
));
5137 gfc_add_expr_to_block (&block
, tmp
);
5141 /* We enclose the above in if (mask) {...}. */
5142 tmp
= gfc_finish_block (&block
);
5144 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
5145 build_empty_stmt (input_location
));
5148 tmp
= gfc_finish_block (&block
);
5149 gfc_add_expr_to_block (&body
, tmp
);
5150 /* Avoid initializing loopvar[0] again, it should be left where
5151 it finished by the first loop. */
5152 loop
.from
[0] = loop
.loopvar
[0];
5155 gfc_trans_scalarizing_loops (&loop
, &body
);
5158 gfc_add_expr_to_block (&loop
.pre
, build1_v (LABEL_EXPR
, lab2
));
5160 /* For a scalar mask, enclose the loop in an if statement. */
5161 if (maskexpr
&& maskss
== NULL
)
5163 gfc_init_se (&maskse
, NULL
);
5164 gfc_conv_expr_val (&maskse
, maskexpr
);
5165 gfc_init_block (&block
);
5166 gfc_add_block_to_block (&block
, &loop
.pre
);
5167 gfc_add_block_to_block (&block
, &loop
.post
);
5168 tmp
= gfc_finish_block (&block
);
5170 /* For the else part of the scalar mask, just initialize
5171 the pos variable the same way as above. */
5173 gfc_init_block (&elseblock
);
5174 gfc_add_modify (&elseblock
, pos
, gfc_index_zero_node
);
5175 elsetmp
= gfc_finish_block (&elseblock
);
5177 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
, elsetmp
);
5178 gfc_add_expr_to_block (&block
, tmp
);
5179 gfc_add_block_to_block (&se
->pre
, &block
);
5183 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
5184 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
5186 gfc_cleanup_loop (&loop
);
5188 se
->expr
= convert (type
, pos
);
5191 /* Emit code for minval or maxval intrinsic. There are many different cases
5192 we need to handle. For performance reasons we sometimes create two
5193 loops instead of one, where the second one is much simpler.
5194 Examples for minval intrinsic:
5195 1) Result is an array, a call is generated
5196 2) Array mask is used and NaNs need to be supported, rank 1:
5201 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
5204 limit = nonempty ? NaN : huge (limit);
5206 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
5207 3) NaNs need to be supported, but it is known at compile time or cheaply
5208 at runtime whether array is nonempty or not, rank 1:
5211 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
5212 limit = (from <= to) ? NaN : huge (limit);
5214 while (S <= to) { limit = min (a[S], limit); S++; }
5215 4) Array mask is used and NaNs need to be supported, rank > 1:
5224 if (fast) limit = min (a[S1][S2], limit);
5227 if (a[S1][S2] <= limit) {
5238 limit = nonempty ? NaN : huge (limit);
5239 5) NaNs need to be supported, but it is known at compile time or cheaply
5240 at runtime whether array is nonempty or not, rank > 1:
5247 if (fast) limit = min (a[S1][S2], limit);
5249 if (a[S1][S2] <= limit) {
5259 limit = (nonempty_array) ? NaN : huge (limit);
5260 6) NaNs aren't supported, but infinities are. Array mask is used:
5265 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
5268 limit = nonempty ? limit : huge (limit);
5269 7) Same without array mask:
5272 while (S <= to) { limit = min (a[S], limit); S++; }
5273 limit = (from <= to) ? limit : huge (limit);
5274 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
5275 limit = huge (limit);
5277 while (S <= to) { limit = min (a[S], limit); S++); }
5279 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
5280 with array mask instead).
5281 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
5282 setting limit = huge (limit); in the else branch. */
5285 gfc_conv_intrinsic_minmaxval (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
5295 tree huge_cst
= NULL
, nan_cst
= NULL
;
5297 stmtblock_t block
, block2
;
5299 gfc_actual_arglist
*actual
;
5304 gfc_expr
*arrayexpr
;
5310 gfc_conv_intrinsic_funcall (se
, expr
);
5314 actual
= expr
->value
.function
.actual
;
5315 arrayexpr
= actual
->expr
;
5317 if (arrayexpr
->ts
.type
== BT_CHARACTER
)
5319 gfc_actual_arglist
*a2
, *a3
;
5320 a2
= actual
->next
; /* dim */
5321 a3
= a2
->next
; /* mask */
5322 if (a2
->expr
== NULL
|| expr
->rank
== 0)
5324 if (a3
->expr
== NULL
)
5325 actual
->next
= NULL
;
5331 gfc_free_actual_arglist (a2
);
5334 if (a3
->expr
== NULL
)
5337 gfc_free_actual_arglist (a3
);
5339 gfc_conv_intrinsic_funcall (se
, expr
);
5342 type
= gfc_typenode_for_spec (&expr
->ts
);
5343 /* Initialize the result. */
5344 limit
= gfc_create_var (type
, "limit");
5345 n
= gfc_validate_kind (expr
->ts
.type
, expr
->ts
.kind
, false);
5346 switch (expr
->ts
.type
)
5349 huge_cst
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[n
].huge
,
5351 if (HONOR_INFINITIES (DECL_MODE (limit
)))
5353 REAL_VALUE_TYPE real
;
5355 tmp
= build_real (type
, real
);
5359 if (HONOR_NANS (DECL_MODE (limit
)))
5360 nan_cst
= gfc_build_nan (type
, "");
5364 tmp
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
, expr
->ts
.kind
);
5371 /* We start with the most negative possible value for MAXVAL, and the most
5372 positive possible value for MINVAL. The most negative possible value is
5373 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
5374 possible value is HUGE in both cases. */
5377 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (tmp
), tmp
);
5379 huge_cst
= fold_build1_loc (input_location
, NEGATE_EXPR
,
5380 TREE_TYPE (huge_cst
), huge_cst
);
5383 if (op
== GT_EXPR
&& expr
->ts
.type
== BT_INTEGER
)
5384 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (tmp
),
5385 tmp
, build_int_cst (type
, 1));
5387 gfc_add_modify (&se
->pre
, limit
, tmp
);
5389 /* Walk the arguments. */
5390 arrayss
= gfc_walk_expr (arrayexpr
);
5391 gcc_assert (arrayss
!= gfc_ss_terminator
);
5393 actual
= actual
->next
->next
;
5394 gcc_assert (actual
);
5395 maskexpr
= actual
->expr
;
5397 if (maskexpr
&& maskexpr
->rank
!= 0)
5399 maskss
= gfc_walk_expr (maskexpr
);
5400 gcc_assert (maskss
!= gfc_ss_terminator
);
5405 if (gfc_array_size (arrayexpr
, &asize
))
5407 nonempty
= gfc_conv_mpz_to_tree (asize
, gfc_index_integer_kind
);
5409 nonempty
= fold_build2_loc (input_location
, GT_EXPR
,
5410 logical_type_node
, nonempty
,
5411 gfc_index_zero_node
);
5416 /* Initialize the scalarizer. */
5417 gfc_init_loopinfo (&loop
);
5418 gfc_add_ss_to_loop (&loop
, arrayss
);
5420 gfc_add_ss_to_loop (&loop
, maskss
);
5422 /* Initialize the loop. */
5423 gfc_conv_ss_startstride (&loop
);
5425 /* The code generated can have more than one loop in sequence (see the
5426 comment at the function header). This doesn't work well with the
5427 scalarizer, which changes arrays' offset when the scalarization loops
5428 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
5429 are currently inlined in the scalar case only. As there is no dependency
5430 to care about in that case, there is no temporary, so that we can use the
5431 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
5432 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
5433 gfc_trans_scalarized_loop_boundary even later to restore offset.
5434 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
5435 should eventually go away. We could either create two loops properly,
5436 or find another way to save/restore the array offsets between the two
5437 loops (without conflicting with temporary management), or use a single
5438 loop minmaxval implementation. See PR 31067. */
5439 loop
.temp_dim
= loop
.dimen
;
5440 gfc_conv_loop_setup (&loop
, &expr
->where
);
5442 if (nonempty
== NULL
&& maskss
== NULL
5443 && loop
.dimen
== 1 && loop
.from
[0] && loop
.to
[0])
5444 nonempty
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
,
5445 loop
.from
[0], loop
.to
[0]);
5446 nonempty_var
= NULL
;
5447 if (nonempty
== NULL
5448 && (HONOR_INFINITIES (DECL_MODE (limit
))
5449 || HONOR_NANS (DECL_MODE (limit
))))
5451 nonempty_var
= gfc_create_var (logical_type_node
, "nonempty");
5452 gfc_add_modify (&se
->pre
, nonempty_var
, logical_false_node
);
5453 nonempty
= nonempty_var
;
5457 if (HONOR_NANS (DECL_MODE (limit
)))
5459 if (loop
.dimen
== 1)
5461 lab
= gfc_build_label_decl (NULL_TREE
);
5462 TREE_USED (lab
) = 1;
5466 fast
= gfc_create_var (logical_type_node
, "fast");
5467 gfc_add_modify (&se
->pre
, fast
, logical_false_node
);
5471 gfc_mark_ss_chain_used (arrayss
, lab
? 3 : 1);
5473 gfc_mark_ss_chain_used (maskss
, lab
? 3 : 1);
5474 /* Generate the loop body. */
5475 gfc_start_scalarized_body (&loop
, &body
);
5477 /* If we have a mask, only add this element if the mask is set. */
5480 gfc_init_se (&maskse
, NULL
);
5481 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
5483 gfc_conv_expr_val (&maskse
, maskexpr
);
5484 gfc_add_block_to_block (&body
, &maskse
.pre
);
5486 gfc_start_block (&block
);
5489 gfc_init_block (&block
);
5491 /* Compare with the current limit. */
5492 gfc_init_se (&arrayse
, NULL
);
5493 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
5494 arrayse
.ss
= arrayss
;
5495 gfc_conv_expr_val (&arrayse
, arrayexpr
);
5496 gfc_add_block_to_block (&block
, &arrayse
.pre
);
5498 gfc_init_block (&block2
);
5501 gfc_add_modify (&block2
, nonempty_var
, logical_true_node
);
5503 if (HONOR_NANS (DECL_MODE (limit
)))
5505 tmp
= fold_build2_loc (input_location
, op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
5506 logical_type_node
, arrayse
.expr
, limit
);
5508 ifbody
= build1_v (GOTO_EXPR
, lab
);
5511 stmtblock_t ifblock
;
5513 gfc_init_block (&ifblock
);
5514 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
5515 gfc_add_modify (&ifblock
, fast
, logical_true_node
);
5516 ifbody
= gfc_finish_block (&ifblock
);
5518 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
5519 build_empty_stmt (input_location
));
5520 gfc_add_expr_to_block (&block2
, tmp
);
5524 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5526 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit
)))
5528 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
,
5529 arrayse
.expr
, limit
);
5530 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
5531 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
5532 build_empty_stmt (input_location
));
5533 gfc_add_expr_to_block (&block2
, tmp
);
5537 tmp
= fold_build2_loc (input_location
,
5538 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
5539 type
, arrayse
.expr
, limit
);
5540 gfc_add_modify (&block2
, limit
, tmp
);
5546 tree elsebody
= gfc_finish_block (&block2
);
5548 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5550 if (HONOR_NANS (DECL_MODE (limit
))
5551 || HONOR_SIGNED_ZEROS (DECL_MODE (limit
)))
5553 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
,
5554 arrayse
.expr
, limit
);
5555 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
5556 ifbody
= build3_v (COND_EXPR
, tmp
, ifbody
,
5557 build_empty_stmt (input_location
));
5561 tmp
= fold_build2_loc (input_location
,
5562 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
5563 type
, arrayse
.expr
, limit
);
5564 ifbody
= build2_v (MODIFY_EXPR
, limit
, tmp
);
5566 tmp
= build3_v (COND_EXPR
, fast
, ifbody
, elsebody
);
5567 gfc_add_expr_to_block (&block
, tmp
);
5570 gfc_add_block_to_block (&block
, &block2
);
5572 gfc_add_block_to_block (&block
, &arrayse
.post
);
5574 tmp
= gfc_finish_block (&block
);
5576 /* We enclose the above in if (mask) {...}. */
5577 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
5578 build_empty_stmt (input_location
));
5579 gfc_add_expr_to_block (&body
, tmp
);
5583 gfc_trans_scalarized_loop_boundary (&loop
, &body
);
5585 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
,
5587 gfc_add_modify (&loop
.code
[0], limit
, tmp
);
5588 gfc_add_expr_to_block (&loop
.code
[0], build1_v (LABEL_EXPR
, lab
));
5590 /* If we have a mask, only add this element if the mask is set. */
5593 gfc_init_se (&maskse
, NULL
);
5594 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
5596 gfc_conv_expr_val (&maskse
, maskexpr
);
5597 gfc_add_block_to_block (&body
, &maskse
.pre
);
5599 gfc_start_block (&block
);
5602 gfc_init_block (&block
);
5604 /* Compare with the current limit. */
5605 gfc_init_se (&arrayse
, NULL
);
5606 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
5607 arrayse
.ss
= arrayss
;
5608 gfc_conv_expr_val (&arrayse
, arrayexpr
);
5609 gfc_add_block_to_block (&block
, &arrayse
.pre
);
5611 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
5613 if (HONOR_NANS (DECL_MODE (limit
))
5614 || HONOR_SIGNED_ZEROS (DECL_MODE (limit
)))
5616 tmp
= fold_build2_loc (input_location
, op
, logical_type_node
,
5617 arrayse
.expr
, limit
);
5618 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
5619 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
5620 build_empty_stmt (input_location
));
5621 gfc_add_expr_to_block (&block
, tmp
);
5625 tmp
= fold_build2_loc (input_location
,
5626 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
5627 type
, arrayse
.expr
, limit
);
5628 gfc_add_modify (&block
, limit
, tmp
);
5631 gfc_add_block_to_block (&block
, &arrayse
.post
);
5633 tmp
= gfc_finish_block (&block
);
5635 /* We enclose the above in if (mask) {...}. */
5636 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
5637 build_empty_stmt (input_location
));
5638 gfc_add_expr_to_block (&body
, tmp
);
5639 /* Avoid initializing loopvar[0] again, it should be left where
5640 it finished by the first loop. */
5641 loop
.from
[0] = loop
.loopvar
[0];
5643 gfc_trans_scalarizing_loops (&loop
, &body
);
5647 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
,
5649 ifbody
= build2_v (MODIFY_EXPR
, limit
, tmp
);
5650 tmp
= build3_v (COND_EXPR
, fast
, build_empty_stmt (input_location
),
5652 gfc_add_expr_to_block (&loop
.pre
, tmp
);
5654 else if (HONOR_INFINITIES (DECL_MODE (limit
)) && !lab
)
5656 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
, limit
,
5658 gfc_add_modify (&loop
.pre
, limit
, tmp
);
5661 /* For a scalar mask, enclose the loop in an if statement. */
5662 if (maskexpr
&& maskss
== NULL
)
5666 gfc_init_se (&maskse
, NULL
);
5667 gfc_conv_expr_val (&maskse
, maskexpr
);
5668 gfc_init_block (&block
);
5669 gfc_add_block_to_block (&block
, &loop
.pre
);
5670 gfc_add_block_to_block (&block
, &loop
.post
);
5671 tmp
= gfc_finish_block (&block
);
5673 if (HONOR_INFINITIES (DECL_MODE (limit
)))
5674 else_stmt
= build2_v (MODIFY_EXPR
, limit
, huge_cst
);
5676 else_stmt
= build_empty_stmt (input_location
);
5677 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
, else_stmt
);
5678 gfc_add_expr_to_block (&block
, tmp
);
5679 gfc_add_block_to_block (&se
->pre
, &block
);
5683 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
5684 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
5687 gfc_cleanup_loop (&loop
);
5692 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
5694 gfc_conv_intrinsic_btest (gfc_se
* se
, gfc_expr
* expr
)
5700 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5701 type
= TREE_TYPE (args
[0]);
5703 tmp
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
5704 build_int_cst (type
, 1), args
[1]);
5705 tmp
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[0], tmp
);
5706 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, tmp
,
5707 build_int_cst (type
, 0));
5708 type
= gfc_typenode_for_spec (&expr
->ts
);
5709 se
->expr
= convert (type
, tmp
);
5713 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
5715 gfc_conv_intrinsic_bitcomp (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
5719 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5721 /* Convert both arguments to the unsigned type of the same size. */
5722 args
[0] = fold_convert (unsigned_type_for (TREE_TYPE (args
[0])), args
[0]);
5723 args
[1] = fold_convert (unsigned_type_for (TREE_TYPE (args
[1])), args
[1]);
5725 /* If they have unequal type size, convert to the larger one. */
5726 if (TYPE_PRECISION (TREE_TYPE (args
[0]))
5727 > TYPE_PRECISION (TREE_TYPE (args
[1])))
5728 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
5729 else if (TYPE_PRECISION (TREE_TYPE (args
[1]))
5730 > TYPE_PRECISION (TREE_TYPE (args
[0])))
5731 args
[0] = fold_convert (TREE_TYPE (args
[1]), args
[0]);
5733 /* Now, we compare them. */
5734 se
->expr
= fold_build2_loc (input_location
, op
, logical_type_node
,
5739 /* Generate code to perform the specified operation. */
5741 gfc_conv_intrinsic_bitop (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
5745 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5746 se
->expr
= fold_build2_loc (input_location
, op
, TREE_TYPE (args
[0]),
5752 gfc_conv_intrinsic_not (gfc_se
* se
, gfc_expr
* expr
)
5756 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
5757 se
->expr
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
5758 TREE_TYPE (arg
), arg
);
5761 /* Set or clear a single bit. */
5763 gfc_conv_intrinsic_singlebitop (gfc_se
* se
, gfc_expr
* expr
, int set
)
5770 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5771 type
= TREE_TYPE (args
[0]);
5773 tmp
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
5774 build_int_cst (type
, 1), args
[1]);
5780 tmp
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, type
, tmp
);
5782 se
->expr
= fold_build2_loc (input_location
, op
, type
, args
[0], tmp
);
5785 /* Extract a sequence of bits.
5786 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
5788 gfc_conv_intrinsic_ibits (gfc_se
* se
, gfc_expr
* expr
)
5795 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
5796 type
= TREE_TYPE (args
[0]);
5798 mask
= build_int_cst (type
, -1);
5799 mask
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
, mask
, args
[2]);
5800 mask
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, type
, mask
);
5802 tmp
= fold_build2_loc (input_location
, RSHIFT_EXPR
, type
, args
[0], args
[1]);
5804 se
->expr
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, tmp
, mask
);
5808 gfc_conv_intrinsic_shape (gfc_se
*se
, gfc_expr
*expr
)
5810 gfc_actual_arglist
*s
, *k
;
5813 /* Remove the KIND argument, if present. */
5814 s
= expr
->value
.function
.actual
;
5820 gfc_conv_intrinsic_funcall (se
, expr
);
5824 gfc_conv_intrinsic_shift (gfc_se
* se
, gfc_expr
* expr
, bool right_shift
,
5827 tree args
[2], type
, num_bits
, cond
;
5829 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5831 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
5832 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
5833 type
= TREE_TYPE (args
[0]);
5836 args
[0] = fold_convert (unsigned_type_for (type
), args
[0]);
5838 gcc_assert (right_shift
);
5840 se
->expr
= fold_build2_loc (input_location
,
5841 right_shift
? RSHIFT_EXPR
: LSHIFT_EXPR
,
5842 TREE_TYPE (args
[0]), args
[0], args
[1]);
5845 se
->expr
= fold_convert (type
, se
->expr
);
5847 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5848 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5850 num_bits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
5851 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
5854 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
5855 build_int_cst (type
, 0), se
->expr
);
5858 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
5860 : ((shift >= 0) ? i << shift : i >> -shift)
5861 where all shifts are logical shifts. */
5863 gfc_conv_intrinsic_ishft (gfc_se
* se
, gfc_expr
* expr
)
5875 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5877 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
5878 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
5880 type
= TREE_TYPE (args
[0]);
5881 utype
= unsigned_type_for (type
);
5883 width
= fold_build1_loc (input_location
, ABS_EXPR
, TREE_TYPE (args
[1]),
5886 /* Left shift if positive. */
5887 lshift
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
, args
[0], width
);
5889 /* Right shift if negative.
5890 We convert to an unsigned type because we want a logical shift.
5891 The standard doesn't define the case of shifting negative
5892 numbers, and we try to be compatible with other compilers, most
5893 notably g77, here. */
5894 rshift
= fold_convert (type
, fold_build2_loc (input_location
, RSHIFT_EXPR
,
5895 utype
, convert (utype
, args
[0]), width
));
5897 tmp
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, args
[1],
5898 build_int_cst (TREE_TYPE (args
[1]), 0));
5899 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, lshift
, rshift
);
5901 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
5902 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
5904 num_bits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
5905 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, width
,
5907 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
5908 build_int_cst (type
, 0), tmp
);
5912 /* Circular shift. AKA rotate or barrel shift. */
5915 gfc_conv_intrinsic_ishftc (gfc_se
* se
, gfc_expr
* expr
)
5923 unsigned int num_args
;
5925 num_args
= gfc_intrinsic_argument_list_length (expr
);
5926 args
= XALLOCAVEC (tree
, num_args
);
5928 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
5932 /* Use a library function for the 3 parameter version. */
5933 tree int4type
= gfc_get_int_type (4);
5935 type
= TREE_TYPE (args
[0]);
5936 /* We convert the first argument to at least 4 bytes, and
5937 convert back afterwards. This removes the need for library
5938 functions for all argument sizes, and function will be
5939 aligned to at least 32 bits, so there's no loss. */
5940 if (expr
->ts
.kind
< 4)
5941 args
[0] = convert (int4type
, args
[0]);
5943 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
5944 need loads of library functions. They cannot have values >
5945 BIT_SIZE (I) so the conversion is safe. */
5946 args
[1] = convert (int4type
, args
[1]);
5947 args
[2] = convert (int4type
, args
[2]);
5949 switch (expr
->ts
.kind
)
5954 tmp
= gfor_fndecl_math_ishftc4
;
5957 tmp
= gfor_fndecl_math_ishftc8
;
5960 tmp
= gfor_fndecl_math_ishftc16
;
5965 se
->expr
= build_call_expr_loc (input_location
,
5966 tmp
, 3, args
[0], args
[1], args
[2]);
5967 /* Convert the result back to the original type, if we extended
5968 the first argument's width above. */
5969 if (expr
->ts
.kind
< 4)
5970 se
->expr
= convert (type
, se
->expr
);
5974 type
= TREE_TYPE (args
[0]);
5976 /* Evaluate arguments only once. */
5977 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
5978 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
5980 /* Rotate left if positive. */
5981 lrot
= fold_build2_loc (input_location
, LROTATE_EXPR
, type
, args
[0], args
[1]);
5983 /* Rotate right if negative. */
5984 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (args
[1]),
5986 rrot
= fold_build2_loc (input_location
,RROTATE_EXPR
, type
, args
[0], tmp
);
5988 zero
= build_int_cst (TREE_TYPE (args
[1]), 0);
5989 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
, args
[1],
5991 rrot
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, lrot
, rrot
);
5993 /* Do nothing if shift == 0. */
5994 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, args
[1],
5996 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, args
[0],
6001 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
6002 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
6004 The conditional expression is necessary because the result of LEADZ(0)
6005 is defined, but the result of __builtin_clz(0) is undefined for most
6008 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
6009 difference in bit size between the argument of LEADZ and the C int. */
6012 gfc_conv_intrinsic_leadz (gfc_se
* se
, gfc_expr
* expr
)
6024 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6025 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
6027 /* Which variant of __builtin_clz* should we call? */
6028 if (argsize
<= INT_TYPE_SIZE
)
6030 arg_type
= unsigned_type_node
;
6031 func
= builtin_decl_explicit (BUILT_IN_CLZ
);
6033 else if (argsize
<= LONG_TYPE_SIZE
)
6035 arg_type
= long_unsigned_type_node
;
6036 func
= builtin_decl_explicit (BUILT_IN_CLZL
);
6038 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
6040 arg_type
= long_long_unsigned_type_node
;
6041 func
= builtin_decl_explicit (BUILT_IN_CLZLL
);
6045 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
6046 arg_type
= gfc_build_uint_type (argsize
);
6050 /* Convert the actual argument twice: first, to the unsigned type of the
6051 same size; then, to the proper argument type for the built-in
6052 function. But the return type is of the default INTEGER kind. */
6053 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
6054 arg
= fold_convert (arg_type
, arg
);
6055 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6056 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
6058 /* Compute LEADZ for the case i .ne. 0. */
6061 s
= TYPE_PRECISION (arg_type
) - argsize
;
6062 tmp
= fold_convert (result_type
,
6063 build_call_expr_loc (input_location
, func
,
6065 leadz
= fold_build2_loc (input_location
, MINUS_EXPR
, result_type
,
6066 tmp
, build_int_cst (result_type
, s
));
6070 /* We end up here if the argument type is larger than 'long long'.
6071 We generate this code:
6073 if (x & (ULL_MAX << ULL_SIZE) != 0)
6074 return clzll ((unsigned long long) (x >> ULLSIZE));
6076 return ULL_SIZE + clzll ((unsigned long long) x);
6077 where ULL_MAX is the largest value that a ULL_MAX can hold
6078 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
6079 is the bit-size of the long long type (64 in this example). */
6080 tree ullsize
, ullmax
, tmp1
, tmp2
, btmp
;
6082 ullsize
= build_int_cst (result_type
, LONG_LONG_TYPE_SIZE
);
6083 ullmax
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
6084 long_long_unsigned_type_node
,
6085 build_int_cst (long_long_unsigned_type_node
,
6088 cond
= fold_build2_loc (input_location
, LSHIFT_EXPR
, arg_type
,
6089 fold_convert (arg_type
, ullmax
), ullsize
);
6090 cond
= fold_build2_loc (input_location
, BIT_AND_EXPR
, arg_type
,
6092 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
6093 cond
, build_int_cst (arg_type
, 0));
6095 tmp1
= fold_build2_loc (input_location
, RSHIFT_EXPR
, arg_type
,
6097 tmp1
= fold_convert (long_long_unsigned_type_node
, tmp1
);
6098 btmp
= builtin_decl_explicit (BUILT_IN_CLZLL
);
6099 tmp1
= fold_convert (result_type
,
6100 build_call_expr_loc (input_location
, btmp
, 1, tmp1
));
6102 tmp2
= fold_convert (long_long_unsigned_type_node
, arg
);
6103 btmp
= builtin_decl_explicit (BUILT_IN_CLZLL
);
6104 tmp2
= fold_convert (result_type
,
6105 build_call_expr_loc (input_location
, btmp
, 1, tmp2
));
6106 tmp2
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
6109 leadz
= fold_build3_loc (input_location
, COND_EXPR
, result_type
,
6113 /* Build BIT_SIZE. */
6114 bit_size
= build_int_cst (result_type
, argsize
);
6116 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
6117 arg
, build_int_cst (arg_type
, 0));
6118 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, result_type
, cond
,
6123 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
6125 The conditional expression is necessary because the result of TRAILZ(0)
6126 is defined, but the result of __builtin_ctz(0) is undefined for most
6130 gfc_conv_intrinsic_trailz (gfc_se
* se
, gfc_expr
*expr
)
6141 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6142 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
6144 /* Which variant of __builtin_ctz* should we call? */
6145 if (argsize
<= INT_TYPE_SIZE
)
6147 arg_type
= unsigned_type_node
;
6148 func
= builtin_decl_explicit (BUILT_IN_CTZ
);
6150 else if (argsize
<= LONG_TYPE_SIZE
)
6152 arg_type
= long_unsigned_type_node
;
6153 func
= builtin_decl_explicit (BUILT_IN_CTZL
);
6155 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
6157 arg_type
= long_long_unsigned_type_node
;
6158 func
= builtin_decl_explicit (BUILT_IN_CTZLL
);
6162 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
6163 arg_type
= gfc_build_uint_type (argsize
);
6167 /* Convert the actual argument twice: first, to the unsigned type of the
6168 same size; then, to the proper argument type for the built-in
6169 function. But the return type is of the default INTEGER kind. */
6170 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
6171 arg
= fold_convert (arg_type
, arg
);
6172 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6173 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
6175 /* Compute TRAILZ for the case i .ne. 0. */
6177 trailz
= fold_convert (result_type
, build_call_expr_loc (input_location
,
6181 /* We end up here if the argument type is larger than 'long long'.
6182 We generate this code:
6184 if ((x & ULL_MAX) == 0)
6185 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
6187 return ctzll ((unsigned long long) x);
6189 where ULL_MAX is the largest value that a ULL_MAX can hold
6190 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
6191 is the bit-size of the long long type (64 in this example). */
6192 tree ullsize
, ullmax
, tmp1
, tmp2
, btmp
;
6194 ullsize
= build_int_cst (result_type
, LONG_LONG_TYPE_SIZE
);
6195 ullmax
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
6196 long_long_unsigned_type_node
,
6197 build_int_cst (long_long_unsigned_type_node
, 0));
6199 cond
= fold_build2_loc (input_location
, BIT_AND_EXPR
, arg_type
, arg
,
6200 fold_convert (arg_type
, ullmax
));
6201 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, cond
,
6202 build_int_cst (arg_type
, 0));
6204 tmp1
= fold_build2_loc (input_location
, RSHIFT_EXPR
, arg_type
,
6206 tmp1
= fold_convert (long_long_unsigned_type_node
, tmp1
);
6207 btmp
= builtin_decl_explicit (BUILT_IN_CTZLL
);
6208 tmp1
= fold_convert (result_type
,
6209 build_call_expr_loc (input_location
, btmp
, 1, tmp1
));
6210 tmp1
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
6213 tmp2
= fold_convert (long_long_unsigned_type_node
, arg
);
6214 btmp
= builtin_decl_explicit (BUILT_IN_CTZLL
);
6215 tmp2
= fold_convert (result_type
,
6216 build_call_expr_loc (input_location
, btmp
, 1, tmp2
));
6218 trailz
= fold_build3_loc (input_location
, COND_EXPR
, result_type
,
6222 /* Build BIT_SIZE. */
6223 bit_size
= build_int_cst (result_type
, argsize
);
6225 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
6226 arg
, build_int_cst (arg_type
, 0));
6227 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, result_type
, cond
,
6231 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
6232 for types larger than "long long", we call the long long built-in for
6233 the lower and higher bits and combine the result. */
6236 gfc_conv_intrinsic_popcnt_poppar (gfc_se
* se
, gfc_expr
*expr
, int parity
)
6244 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6245 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
6246 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
6248 /* Which variant of the builtin should we call? */
6249 if (argsize
<= INT_TYPE_SIZE
)
6251 arg_type
= unsigned_type_node
;
6252 func
= builtin_decl_explicit (parity
6254 : BUILT_IN_POPCOUNT
);
6256 else if (argsize
<= LONG_TYPE_SIZE
)
6258 arg_type
= long_unsigned_type_node
;
6259 func
= builtin_decl_explicit (parity
6261 : BUILT_IN_POPCOUNTL
);
6263 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
6265 arg_type
= long_long_unsigned_type_node
;
6266 func
= builtin_decl_explicit (parity
6268 : BUILT_IN_POPCOUNTLL
);
6272 /* Our argument type is larger than 'long long', which mean none
6273 of the POPCOUNT builtins covers it. We thus call the 'long long'
6274 variant multiple times, and add the results. */
6275 tree utype
, arg2
, call1
, call2
;
6277 /* For now, we only cover the case where argsize is twice as large
6279 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
6281 func
= builtin_decl_explicit (parity
6283 : BUILT_IN_POPCOUNTLL
);
6285 /* Convert it to an integer, and store into a variable. */
6286 utype
= gfc_build_uint_type (argsize
);
6287 arg
= fold_convert (utype
, arg
);
6288 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6290 /* Call the builtin twice. */
6291 call1
= build_call_expr_loc (input_location
, func
, 1,
6292 fold_convert (long_long_unsigned_type_node
,
6295 arg2
= fold_build2_loc (input_location
, RSHIFT_EXPR
, utype
, arg
,
6296 build_int_cst (utype
, LONG_LONG_TYPE_SIZE
));
6297 call2
= build_call_expr_loc (input_location
, func
, 1,
6298 fold_convert (long_long_unsigned_type_node
,
6301 /* Combine the results. */
6303 se
->expr
= fold_build2_loc (input_location
, BIT_XOR_EXPR
, result_type
,
6306 se
->expr
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
6312 /* Convert the actual argument twice: first, to the unsigned type of the
6313 same size; then, to the proper argument type for the built-in
6315 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
6316 arg
= fold_convert (arg_type
, arg
);
6318 se
->expr
= fold_convert (result_type
,
6319 build_call_expr_loc (input_location
, func
, 1, arg
));
6323 /* Process an intrinsic with unspecified argument-types that has an optional
6324 argument (which could be of type character), e.g. EOSHIFT. For those, we
6325 need to append the string length of the optional argument if it is not
6326 present and the type is really character.
6327 primary specifies the position (starting at 1) of the non-optional argument
6328 specifying the type and optional gives the position of the optional
6329 argument in the arglist. */
6332 conv_generic_with_optional_char_arg (gfc_se
* se
, gfc_expr
* expr
,
6333 unsigned primary
, unsigned optional
)
6335 gfc_actual_arglist
* prim_arg
;
6336 gfc_actual_arglist
* opt_arg
;
6338 gfc_actual_arglist
* arg
;
6340 vec
<tree
, va_gc
> *append_args
;
6342 /* Find the two arguments given as position. */
6346 for (arg
= expr
->value
.function
.actual
; arg
; arg
= arg
->next
)
6350 if (cur_pos
== primary
)
6352 if (cur_pos
== optional
)
6355 if (cur_pos
>= primary
&& cur_pos
>= optional
)
6358 gcc_assert (prim_arg
);
6359 gcc_assert (prim_arg
->expr
);
6360 gcc_assert (opt_arg
);
6362 /* If we do have type CHARACTER and the optional argument is really absent,
6363 append a dummy 0 as string length. */
6365 if (prim_arg
->expr
->ts
.type
== BT_CHARACTER
&& !opt_arg
->expr
)
6369 dummy
= build_int_cst (gfc_charlen_type_node
, 0);
6370 vec_alloc (append_args
, 1);
6371 append_args
->quick_push (dummy
);
6374 /* Build the call itself. */
6375 gcc_assert (!se
->ignore_optional
);
6376 sym
= gfc_get_symbol_for_expr (expr
, false);
6377 gfc_conv_procedure_call (se
, sym
, expr
->value
.function
.actual
, expr
,
6379 gfc_free_symbol (sym
);
6382 /* The length of a character string. */
6384 gfc_conv_intrinsic_len (gfc_se
* se
, gfc_expr
* expr
)
6393 gcc_assert (!se
->ss
);
6395 arg
= expr
->value
.function
.actual
->expr
;
6397 type
= gfc_typenode_for_spec (&expr
->ts
);
6398 switch (arg
->expr_type
)
6401 len
= build_int_cst (gfc_charlen_type_node
, arg
->value
.character
.length
);
6405 /* Obtain the string length from the function used by
6406 trans-array.c(gfc_trans_array_constructor). */
6408 get_array_ctor_strlen (&se
->pre
, arg
->value
.constructor
, &len
);
6412 if (arg
->ref
== NULL
6413 || (arg
->ref
->next
== NULL
&& arg
->ref
->type
== REF_ARRAY
))
6415 /* This doesn't catch all cases.
6416 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
6417 and the surrounding thread. */
6418 sym
= arg
->symtree
->n
.sym
;
6419 decl
= gfc_get_symbol_decl (sym
);
6420 if (decl
== current_function_decl
&& sym
->attr
.function
6421 && (sym
->result
== sym
))
6422 decl
= gfc_get_fake_result_decl (sym
, 0);
6424 len
= sym
->ts
.u
.cl
->backend_decl
;
6432 /* Anybody stupid enough to do this deserves inefficient code. */
6433 gfc_init_se (&argse
, se
);
6435 gfc_conv_expr (&argse
, arg
);
6437 gfc_conv_expr_descriptor (&argse
, arg
);
6438 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6439 gfc_add_block_to_block (&se
->post
, &argse
.post
);
6440 len
= argse
.string_length
;
6443 se
->expr
= convert (type
, len
);
6446 /* The length of a character string not including trailing blanks. */
6448 gfc_conv_intrinsic_len_trim (gfc_se
* se
, gfc_expr
* expr
)
6450 int kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
6451 tree args
[2], type
, fndecl
;
6453 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6454 type
= gfc_typenode_for_spec (&expr
->ts
);
6457 fndecl
= gfor_fndecl_string_len_trim
;
6459 fndecl
= gfor_fndecl_string_len_trim_char4
;
6463 se
->expr
= build_call_expr_loc (input_location
,
6464 fndecl
, 2, args
[0], args
[1]);
6465 se
->expr
= convert (type
, se
->expr
);
6469 /* Returns the starting position of a substring within a string. */
6472 gfc_conv_intrinsic_index_scan_verify (gfc_se
* se
, gfc_expr
* expr
,
6475 tree logical4_type_node
= gfc_get_logical_type (4);
6479 unsigned int num_args
;
6481 args
= XALLOCAVEC (tree
, 5);
6483 /* Get number of arguments; characters count double due to the
6484 string length argument. Kind= is not passed to the library
6485 and thus ignored. */
6486 if (expr
->value
.function
.actual
->next
->next
->expr
== NULL
)
6491 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
6492 type
= gfc_typenode_for_spec (&expr
->ts
);
6495 args
[4] = build_int_cst (logical4_type_node
, 0);
6497 args
[4] = convert (logical4_type_node
, args
[4]);
6499 fndecl
= build_addr (function
);
6500 se
->expr
= build_call_array_loc (input_location
,
6501 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
6503 se
->expr
= convert (type
, se
->expr
);
6507 /* The ascii value for a single character. */
6509 gfc_conv_intrinsic_ichar (gfc_se
* se
, gfc_expr
* expr
)
6511 tree args
[3], type
, pchartype
;
6514 nargs
= gfc_intrinsic_argument_list_length (expr
);
6515 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
6516 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args
[1])));
6517 pchartype
= gfc_get_pchar_type (expr
->value
.function
.actual
->expr
->ts
.kind
);
6518 args
[1] = fold_build1_loc (input_location
, NOP_EXPR
, pchartype
, args
[1]);
6519 type
= gfc_typenode_for_spec (&expr
->ts
);
6521 se
->expr
= build_fold_indirect_ref_loc (input_location
,
6523 se
->expr
= convert (type
, se
->expr
);
6527 /* Intrinsic ISNAN calls __builtin_isnan. */
6530 gfc_conv_intrinsic_isnan (gfc_se
* se
, gfc_expr
* expr
)
6534 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6535 se
->expr
= build_call_expr_loc (input_location
,
6536 builtin_decl_explicit (BUILT_IN_ISNAN
),
6538 STRIP_TYPE_NOPS (se
->expr
);
6539 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
6543 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
6544 their argument against a constant integer value. */
6547 gfc_conv_has_intvalue (gfc_se
* se
, gfc_expr
* expr
, const int value
)
6551 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6552 se
->expr
= fold_build2_loc (input_location
, EQ_EXPR
,
6553 gfc_typenode_for_spec (&expr
->ts
),
6554 arg
, build_int_cst (TREE_TYPE (arg
), value
));
6559 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
6562 gfc_conv_intrinsic_merge (gfc_se
* se
, gfc_expr
* expr
)
6570 unsigned int num_args
;
6572 num_args
= gfc_intrinsic_argument_list_length (expr
);
6573 args
= XALLOCAVEC (tree
, num_args
);
6575 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
6576 if (expr
->ts
.type
!= BT_CHARACTER
)
6584 /* We do the same as in the non-character case, but the argument
6585 list is different because of the string length arguments. We
6586 also have to set the string length for the result. */
6593 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr
->where
, len
, len2
,
6595 se
->string_length
= len
;
6597 type
= TREE_TYPE (tsource
);
6598 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, mask
, tsource
,
6599 fold_convert (type
, fsource
));
6603 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
6606 gfc_conv_intrinsic_merge_bits (gfc_se
* se
, gfc_expr
* expr
)
6608 tree args
[3], mask
, type
;
6610 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
6611 mask
= gfc_evaluate_now (args
[2], &se
->pre
);
6613 type
= TREE_TYPE (args
[0]);
6614 gcc_assert (TREE_TYPE (args
[1]) == type
);
6615 gcc_assert (TREE_TYPE (mask
) == type
);
6617 args
[0] = fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[0], mask
);
6618 args
[1] = fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[1],
6619 fold_build1_loc (input_location
, BIT_NOT_EXPR
,
6621 se
->expr
= fold_build2_loc (input_location
, BIT_IOR_EXPR
, type
,
6626 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
6627 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
6630 gfc_conv_intrinsic_mask (gfc_se
* se
, gfc_expr
* expr
, int left
)
6632 tree arg
, allones
, type
, utype
, res
, cond
, bitsize
;
6635 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6636 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6638 type
= gfc_get_int_type (expr
->ts
.kind
);
6639 utype
= unsigned_type_for (type
);
6641 i
= gfc_validate_kind (BT_INTEGER
, expr
->ts
.kind
, false);
6642 bitsize
= build_int_cst (TREE_TYPE (arg
), gfc_integer_kinds
[i
].bit_size
);
6644 allones
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, utype
,
6645 build_int_cst (utype
, 0));
6649 /* Left-justified mask. */
6650 res
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (arg
),
6652 res
= fold_build2_loc (input_location
, LSHIFT_EXPR
, utype
, allones
,
6653 fold_convert (utype
, res
));
6655 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
6656 smaller than type width. */
6657 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, arg
,
6658 build_int_cst (TREE_TYPE (arg
), 0));
6659 res
= fold_build3_loc (input_location
, COND_EXPR
, utype
, cond
,
6660 build_int_cst (utype
, 0), res
);
6664 /* Right-justified mask. */
6665 res
= fold_build2_loc (input_location
, LSHIFT_EXPR
, utype
, allones
,
6666 fold_convert (utype
, arg
));
6667 res
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, utype
, res
);
6669 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
6670 strictly smaller than type width. */
6671 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
6673 res
= fold_build3_loc (input_location
, COND_EXPR
, utype
,
6674 cond
, allones
, res
);
6677 se
->expr
= fold_convert (type
, res
);
6681 /* FRACTION (s) is translated into:
6682 isfinite (s) ? frexp (s, &dummy_int) : NaN */
6684 gfc_conv_intrinsic_fraction (gfc_se
* se
, gfc_expr
* expr
)
6686 tree arg
, type
, tmp
, res
, frexp
, cond
;
6688 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
6690 type
= gfc_typenode_for_spec (&expr
->ts
);
6691 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6692 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6694 cond
= build_call_expr_loc (input_location
,
6695 builtin_decl_explicit (BUILT_IN_ISFINITE
),
6698 tmp
= gfc_create_var (integer_type_node
, NULL
);
6699 res
= build_call_expr_loc (input_location
, frexp
, 2,
6700 fold_convert (type
, arg
),
6701 gfc_build_addr_expr (NULL_TREE
, tmp
));
6702 res
= fold_convert (type
, res
);
6704 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
,
6705 cond
, res
, gfc_build_nan (type
, ""));
6709 /* NEAREST (s, dir) is translated into
6710 tmp = copysign (HUGE_VAL, dir);
6711 return nextafter (s, tmp);
6714 gfc_conv_intrinsic_nearest (gfc_se
* se
, gfc_expr
* expr
)
6716 tree args
[2], type
, tmp
, nextafter
, copysign
, huge_val
;
6718 nextafter
= gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER
, expr
->ts
.kind
);
6719 copysign
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
, expr
->ts
.kind
);
6721 type
= gfc_typenode_for_spec (&expr
->ts
);
6722 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6724 huge_val
= gfc_build_inf_or_huge (type
, expr
->ts
.kind
);
6725 tmp
= build_call_expr_loc (input_location
, copysign
, 2, huge_val
,
6726 fold_convert (type
, args
[1]));
6727 se
->expr
= build_call_expr_loc (input_location
, nextafter
, 2,
6728 fold_convert (type
, args
[0]), tmp
);
6729 se
->expr
= fold_convert (type
, se
->expr
);
6733 /* SPACING (s) is translated into
6743 e = MAX_EXPR (e, emin);
6744 res = scalbn (1., e);
6748 where prec is the precision of s, gfc_real_kinds[k].digits,
6749 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
6750 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
6753 gfc_conv_intrinsic_spacing (gfc_se
* se
, gfc_expr
* expr
)
6755 tree arg
, type
, prec
, emin
, tiny
, res
, e
;
6756 tree cond
, nan
, tmp
, frexp
, scalbn
;
6760 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
6761 prec
= build_int_cst (integer_type_node
, gfc_real_kinds
[k
].digits
);
6762 emin
= build_int_cst (integer_type_node
, gfc_real_kinds
[k
].min_exponent
- 1);
6763 tiny
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[k
].tiny
, expr
->ts
.kind
, 0);
6765 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
6766 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
6768 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6769 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6771 type
= gfc_typenode_for_spec (&expr
->ts
);
6772 e
= gfc_create_var (integer_type_node
, NULL
);
6773 res
= gfc_create_var (type
, NULL
);
6776 /* Build the block for s /= 0. */
6777 gfc_start_block (&block
);
6778 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
6779 gfc_build_addr_expr (NULL_TREE
, e
));
6780 gfc_add_expr_to_block (&block
, tmp
);
6782 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, integer_type_node
, e
,
6784 gfc_add_modify (&block
, e
, fold_build2_loc (input_location
, MAX_EXPR
,
6785 integer_type_node
, tmp
, emin
));
6787 tmp
= build_call_expr_loc (input_location
, scalbn
, 2,
6788 build_real_from_int_cst (type
, integer_one_node
), e
);
6789 gfc_add_modify (&block
, res
, tmp
);
6791 /* Finish by building the IF statement for value zero. */
6792 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, arg
,
6793 build_real_from_int_cst (type
, integer_zero_node
));
6794 tmp
= build3_v (COND_EXPR
, cond
, build2_v (MODIFY_EXPR
, res
, tiny
),
6795 gfc_finish_block (&block
));
6797 /* And deal with infinities and NaNs. */
6798 cond
= build_call_expr_loc (input_location
,
6799 builtin_decl_explicit (BUILT_IN_ISFINITE
),
6801 nan
= gfc_build_nan (type
, "");
6802 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build2_v (MODIFY_EXPR
, res
, nan
));
6804 gfc_add_expr_to_block (&se
->pre
, tmp
);
6809 /* RRSPACING (s) is translated into
6818 x = scalbn (x, precision - e);
6825 where precision is gfc_real_kinds[k].digits. */
6828 gfc_conv_intrinsic_rrspacing (gfc_se
* se
, gfc_expr
* expr
)
6830 tree arg
, type
, e
, x
, cond
, nan
, stmt
, tmp
, frexp
, scalbn
, fabs
;
6834 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
6835 prec
= gfc_real_kinds
[k
].digits
;
6837 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
6838 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
6839 fabs
= gfc_builtin_decl_for_float_kind (BUILT_IN_FABS
, expr
->ts
.kind
);
6841 type
= gfc_typenode_for_spec (&expr
->ts
);
6842 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6843 arg
= gfc_evaluate_now (arg
, &se
->pre
);
6845 e
= gfc_create_var (integer_type_node
, NULL
);
6846 x
= gfc_create_var (type
, NULL
);
6847 gfc_add_modify (&se
->pre
, x
,
6848 build_call_expr_loc (input_location
, fabs
, 1, arg
));
6851 gfc_start_block (&block
);
6852 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
6853 gfc_build_addr_expr (NULL_TREE
, e
));
6854 gfc_add_expr_to_block (&block
, tmp
);
6856 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, integer_type_node
,
6857 build_int_cst (integer_type_node
, prec
), e
);
6858 tmp
= build_call_expr_loc (input_location
, scalbn
, 2, x
, tmp
);
6859 gfc_add_modify (&block
, x
, tmp
);
6860 stmt
= gfc_finish_block (&block
);
6863 cond
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, x
,
6864 build_real_from_int_cst (type
, integer_zero_node
));
6865 tmp
= build3_v (COND_EXPR
, cond
, stmt
, build_empty_stmt (input_location
));
6867 /* And deal with infinities and NaNs. */
6868 cond
= build_call_expr_loc (input_location
,
6869 builtin_decl_explicit (BUILT_IN_ISFINITE
),
6871 nan
= gfc_build_nan (type
, "");
6872 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build2_v (MODIFY_EXPR
, x
, nan
));
6874 gfc_add_expr_to_block (&se
->pre
, tmp
);
6875 se
->expr
= fold_convert (type
, x
);
6879 /* SCALE (s, i) is translated into scalbn (s, i). */
6881 gfc_conv_intrinsic_scale (gfc_se
* se
, gfc_expr
* expr
)
6883 tree args
[2], type
, scalbn
;
6885 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
6887 type
= gfc_typenode_for_spec (&expr
->ts
);
6888 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6889 se
->expr
= build_call_expr_loc (input_location
, scalbn
, 2,
6890 fold_convert (type
, args
[0]),
6891 fold_convert (integer_type_node
, args
[1]));
6892 se
->expr
= fold_convert (type
, se
->expr
);
6896 /* SET_EXPONENT (s, i) is translated into
6897 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
6899 gfc_conv_intrinsic_set_exponent (gfc_se
* se
, gfc_expr
* expr
)
6901 tree args
[2], type
, tmp
, frexp
, scalbn
, cond
, nan
, res
;
6903 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
6904 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
6906 type
= gfc_typenode_for_spec (&expr
->ts
);
6907 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6908 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
6910 tmp
= gfc_create_var (integer_type_node
, NULL
);
6911 tmp
= build_call_expr_loc (input_location
, frexp
, 2,
6912 fold_convert (type
, args
[0]),
6913 gfc_build_addr_expr (NULL_TREE
, tmp
));
6914 res
= build_call_expr_loc (input_location
, scalbn
, 2, tmp
,
6915 fold_convert (integer_type_node
, args
[1]));
6916 res
= fold_convert (type
, res
);
6918 /* Call to isfinite */
6919 cond
= build_call_expr_loc (input_location
,
6920 builtin_decl_explicit (BUILT_IN_ISFINITE
),
6922 nan
= gfc_build_nan (type
, "");
6924 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
6930 gfc_conv_intrinsic_size (gfc_se
* se
, gfc_expr
* expr
)
6932 gfc_actual_arglist
*actual
;
6939 gfc_init_se (&argse
, NULL
);
6940 actual
= expr
->value
.function
.actual
;
6942 if (actual
->expr
->ts
.type
== BT_CLASS
)
6943 gfc_add_class_array_ref (actual
->expr
);
6945 argse
.data_not_needed
= 1;
6946 if (gfc_is_class_array_function (actual
->expr
))
6948 /* For functions that return a class array conv_expr_descriptor is not
6949 able to get the descriptor right. Therefore this special case. */
6950 gfc_conv_expr_reference (&argse
, actual
->expr
);
6951 argse
.expr
= gfc_build_addr_expr (NULL_TREE
,
6952 gfc_class_data_get (argse
.expr
));
6956 argse
.want_pointer
= 1;
6957 gfc_conv_expr_descriptor (&argse
, actual
->expr
);
6959 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6960 gfc_add_block_to_block (&se
->post
, &argse
.post
);
6961 arg1
= gfc_evaluate_now (argse
.expr
, &se
->pre
);
6963 /* Build the call to size0. */
6964 fncall0
= build_call_expr_loc (input_location
,
6965 gfor_fndecl_size0
, 1, arg1
);
6967 actual
= actual
->next
;
6971 gfc_init_se (&argse
, NULL
);
6972 gfc_conv_expr_type (&argse
, actual
->expr
,
6973 gfc_array_index_type
);
6974 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6976 /* Unusually, for an intrinsic, size does not exclude
6977 an optional arg2, so we must test for it. */
6978 if (actual
->expr
->expr_type
== EXPR_VARIABLE
6979 && actual
->expr
->symtree
->n
.sym
->attr
.dummy
6980 && actual
->expr
->symtree
->n
.sym
->attr
.optional
)
6983 /* Build the call to size1. */
6984 fncall1
= build_call_expr_loc (input_location
,
6985 gfor_fndecl_size1
, 2,
6988 gfc_init_se (&argse
, NULL
);
6989 argse
.want_pointer
= 1;
6990 argse
.data_not_needed
= 1;
6991 gfc_conv_expr (&argse
, actual
->expr
);
6992 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6993 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
6994 argse
.expr
, null_pointer_node
);
6995 tmp
= gfc_evaluate_now (tmp
, &se
->pre
);
6996 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
6997 pvoid_type_node
, tmp
, fncall1
, fncall0
);
7001 se
->expr
= NULL_TREE
;
7002 argse
.expr
= fold_build2_loc (input_location
, MINUS_EXPR
,
7003 gfc_array_index_type
,
7004 argse
.expr
, gfc_index_one_node
);
7007 else if (expr
->value
.function
.actual
->expr
->rank
== 1)
7009 argse
.expr
= gfc_index_zero_node
;
7010 se
->expr
= NULL_TREE
;
7015 if (se
->expr
== NULL_TREE
)
7017 tree ubound
, lbound
;
7019 arg1
= build_fold_indirect_ref_loc (input_location
,
7021 ubound
= gfc_conv_descriptor_ubound_get (arg1
, argse
.expr
);
7022 lbound
= gfc_conv_descriptor_lbound_get (arg1
, argse
.expr
);
7023 se
->expr
= fold_build2_loc (input_location
, MINUS_EXPR
,
7024 gfc_array_index_type
, ubound
, lbound
);
7025 se
->expr
= fold_build2_loc (input_location
, PLUS_EXPR
,
7026 gfc_array_index_type
,
7027 se
->expr
, gfc_index_one_node
);
7028 se
->expr
= fold_build2_loc (input_location
, MAX_EXPR
,
7029 gfc_array_index_type
, se
->expr
,
7030 gfc_index_zero_node
);
7033 type
= gfc_typenode_for_spec (&expr
->ts
);
7034 se
->expr
= convert (type
, se
->expr
);
7038 /* Helper function to compute the size of a character variable,
7039 excluding the terminating null characters. The result has
7040 gfc_array_index_type type. */
7043 size_of_string_in_bytes (int kind
, tree string_length
)
7046 int i
= gfc_validate_kind (BT_CHARACTER
, kind
, false);
7048 bytesize
= build_int_cst (gfc_array_index_type
,
7049 gfc_character_kinds
[i
].bit_size
/ 8);
7051 return fold_build2_loc (input_location
, MULT_EXPR
, gfc_array_index_type
,
7053 fold_convert (gfc_array_index_type
, string_length
));
7058 gfc_conv_intrinsic_sizeof (gfc_se
*se
, gfc_expr
*expr
)
7070 gfc_init_se (&argse
, NULL
);
7071 arg
= expr
->value
.function
.actual
->expr
;
7073 if (arg
->rank
|| arg
->ts
.type
== BT_ASSUMED
)
7074 gfc_conv_expr_descriptor (&argse
, arg
);
7076 gfc_conv_expr_reference (&argse
, arg
);
7078 if (arg
->ts
.type
== BT_ASSUMED
)
7080 /* This only works if an array descriptor has been passed; thus, extract
7081 the size from the descriptor. */
7082 gcc_assert (TYPE_PRECISION (gfc_array_index_type
)
7083 == TYPE_PRECISION (size_type_node
));
7084 tmp
= arg
->symtree
->n
.sym
->backend_decl
;
7085 tmp
= DECL_LANG_SPECIFIC (tmp
)
7086 && GFC_DECL_SAVED_DESCRIPTOR (tmp
) != NULL_TREE
7087 ? GFC_DECL_SAVED_DESCRIPTOR (tmp
) : tmp
;
7088 if (POINTER_TYPE_P (TREE_TYPE (tmp
)))
7089 tmp
= build_fold_indirect_ref_loc (input_location
, tmp
);
7091 tmp
= gfc_conv_descriptor_dtype (tmp
);
7092 field
= gfc_advance_chain (TYPE_FIELDS (get_dtype_type_node ()),
7093 GFC_DTYPE_ELEM_LEN
);
7094 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
7095 tmp
, field
, NULL_TREE
);
7097 byte_size
= fold_convert (gfc_array_index_type
, tmp
);
7099 else if (arg
->ts
.type
== BT_CLASS
)
7101 /* Conv_expr_descriptor returns a component_ref to _data component of the
7102 class object. The class object may be a non-pointer object, e.g.
7103 located on the stack, or a memory location pointed to, e.g. a
7104 parameter, i.e., an indirect_ref. */
7106 || (arg
->rank
> 0 && !VAR_P (argse
.expr
)
7107 && ((INDIRECT_REF_P (TREE_OPERAND (argse
.expr
, 0))
7108 && GFC_DECL_CLASS (TREE_OPERAND (
7109 TREE_OPERAND (argse
.expr
, 0), 0)))
7110 || GFC_DECL_CLASS (TREE_OPERAND (argse
.expr
, 0)))))
7111 byte_size
= gfc_class_vtab_size_get (TREE_OPERAND (argse
.expr
, 0));
7112 else if (arg
->rank
> 0
7114 && arg
->ref
&& arg
->ref
->type
== REF_COMPONENT
))
7115 /* The scalarizer added an additional temp. To get the class' vptr
7116 one has to look at the original backend_decl. */
7117 byte_size
= gfc_class_vtab_size_get (
7118 GFC_DECL_SAVED_DESCRIPTOR (arg
->symtree
->n
.sym
->backend_decl
));
7120 byte_size
= gfc_class_vtab_size_get (argse
.expr
);
7124 if (arg
->ts
.type
== BT_CHARACTER
)
7125 byte_size
= size_of_string_in_bytes (arg
->ts
.kind
, argse
.string_length
);
7129 byte_size
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
7132 byte_size
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
7133 byte_size
= fold_convert (gfc_array_index_type
,
7134 size_in_bytes (byte_size
));
7139 se
->expr
= byte_size
;
7142 source_bytes
= gfc_create_var (gfc_array_index_type
, "bytes");
7143 gfc_add_modify (&argse
.pre
, source_bytes
, byte_size
);
7145 if (arg
->rank
== -1)
7147 tree cond
, loop_var
, exit_label
;
7150 tmp
= fold_convert (gfc_array_index_type
,
7151 gfc_conv_descriptor_rank (argse
.expr
));
7152 loop_var
= gfc_create_var (gfc_array_index_type
, "i");
7153 gfc_add_modify (&argse
.pre
, loop_var
, gfc_index_zero_node
);
7154 exit_label
= gfc_build_label_decl (NULL_TREE
);
7161 source_bytes = source_bytes * array.dim[i].extent;
7165 gfc_start_block (&body
);
7166 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
,
7168 tmp
= build1_v (GOTO_EXPR
, exit_label
);
7169 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
7170 cond
, tmp
, build_empty_stmt (input_location
));
7171 gfc_add_expr_to_block (&body
, tmp
);
7173 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, loop_var
);
7174 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, loop_var
);
7175 tmp
= gfc_conv_array_extent_dim (lower
, upper
, NULL
);
7176 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
7177 gfc_array_index_type
, tmp
, source_bytes
);
7178 gfc_add_modify (&body
, source_bytes
, tmp
);
7180 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
7181 gfc_array_index_type
, loop_var
,
7182 gfc_index_one_node
);
7183 gfc_add_modify_loc (input_location
, &body
, loop_var
, tmp
);
7185 tmp
= gfc_finish_block (&body
);
7187 tmp
= fold_build1_loc (input_location
, LOOP_EXPR
, void_type_node
,
7189 gfc_add_expr_to_block (&argse
.pre
, tmp
);
7191 tmp
= build1_v (LABEL_EXPR
, exit_label
);
7192 gfc_add_expr_to_block (&argse
.pre
, tmp
);
7196 /* Obtain the size of the array in bytes. */
7197 for (n
= 0; n
< arg
->rank
; n
++)
7200 idx
= gfc_rank_cst
[n
];
7201 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, idx
);
7202 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, idx
);
7203 tmp
= gfc_conv_array_extent_dim (lower
, upper
, NULL
);
7204 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
7205 gfc_array_index_type
, tmp
, source_bytes
);
7206 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
7209 se
->expr
= source_bytes
;
7212 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7217 gfc_conv_intrinsic_storage_size (gfc_se
*se
, gfc_expr
*expr
)
7221 tree type
, result_type
, tmp
;
7223 arg
= expr
->value
.function
.actual
->expr
;
7225 gfc_init_se (&argse
, NULL
);
7226 result_type
= gfc_get_int_type (expr
->ts
.kind
);
7230 if (arg
->ts
.type
== BT_CLASS
)
7232 gfc_add_vptr_component (arg
);
7233 gfc_add_size_component (arg
);
7234 gfc_conv_expr (&argse
, arg
);
7235 tmp
= fold_convert (result_type
, argse
.expr
);
7239 gfc_conv_expr_reference (&argse
, arg
);
7240 type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
7245 argse
.want_pointer
= 0;
7246 gfc_conv_expr_descriptor (&argse
, arg
);
7247 if (arg
->ts
.type
== BT_CLASS
)
7250 tmp
= gfc_class_vtab_size_get (
7251 GFC_DECL_SAVED_DESCRIPTOR (arg
->symtree
->n
.sym
->backend_decl
));
7253 tmp
= gfc_class_vtab_size_get (TREE_OPERAND (argse
.expr
, 0));
7254 tmp
= fold_convert (result_type
, tmp
);
7257 type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
7260 /* Obtain the argument's word length. */
7261 if (arg
->ts
.type
== BT_CHARACTER
)
7262 tmp
= size_of_string_in_bytes (arg
->ts
.kind
, argse
.string_length
);
7264 tmp
= size_in_bytes (type
);
7265 tmp
= fold_convert (result_type
, tmp
);
7268 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, result_type
, tmp
,
7269 build_int_cst (result_type
, BITS_PER_UNIT
));
7270 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7274 /* Intrinsic string comparison functions. */
7277 gfc_conv_intrinsic_strcmp (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
7281 gfc_conv_intrinsic_function_args (se
, expr
, args
, 4);
7284 = gfc_build_compare_string (args
[0], args
[1], args
[2], args
[3],
7285 expr
->value
.function
.actual
->expr
->ts
.kind
,
7287 se
->expr
= fold_build2_loc (input_location
, op
,
7288 gfc_typenode_for_spec (&expr
->ts
), se
->expr
,
7289 build_int_cst (TREE_TYPE (se
->expr
), 0));
7292 /* Generate a call to the adjustl/adjustr library function. */
7294 gfc_conv_intrinsic_adjust (gfc_se
* se
, gfc_expr
* expr
, tree fndecl
)
7302 gfc_conv_intrinsic_function_args (se
, expr
, &args
[1], 2);
7305 type
= TREE_TYPE (args
[2]);
7306 var
= gfc_conv_string_tmp (se
, type
, len
);
7309 tmp
= build_call_expr_loc (input_location
,
7310 fndecl
, 3, args
[0], args
[1], args
[2]);
7311 gfc_add_expr_to_block (&se
->pre
, tmp
);
7313 se
->string_length
= len
;
7317 /* Generate code for the TRANSFER intrinsic:
7319 DEST = TRANSFER (SOURCE, MOLD)
7321 typeof<DEST> = typeof<MOLD>
7326 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
7328 typeof<DEST> = typeof<MOLD>
7330 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
7331 sizeof (DEST(0) * SIZE). */
7333 gfc_conv_intrinsic_transfer (gfc_se
* se
, gfc_expr
* expr
)
7349 gfc_actual_arglist
*arg
;
7351 gfc_array_info
*info
;
7355 gfc_expr
*source_expr
, *mold_expr
;
7359 info
= &se
->ss
->info
->data
.array
;
7361 /* Convert SOURCE. The output from this stage is:-
7362 source_bytes = length of the source in bytes
7363 source = pointer to the source data. */
7364 arg
= expr
->value
.function
.actual
;
7365 source_expr
= arg
->expr
;
7367 /* Ensure double transfer through LOGICAL preserves all
7369 if (arg
->expr
->expr_type
== EXPR_FUNCTION
7370 && arg
->expr
->value
.function
.esym
== NULL
7371 && arg
->expr
->value
.function
.isym
!= NULL
7372 && arg
->expr
->value
.function
.isym
->id
== GFC_ISYM_TRANSFER
7373 && arg
->expr
->ts
.type
== BT_LOGICAL
7374 && expr
->ts
.type
!= arg
->expr
->ts
.type
)
7375 arg
->expr
->value
.function
.name
= "__transfer_in_transfer";
7377 gfc_init_se (&argse
, NULL
);
7379 source_bytes
= gfc_create_var (gfc_array_index_type
, NULL
);
7381 /* Obtain the pointer to source and the length of source in bytes. */
7382 if (arg
->expr
->rank
== 0)
7384 gfc_conv_expr_reference (&argse
, arg
->expr
);
7385 if (arg
->expr
->ts
.type
== BT_CLASS
)
7386 source
= gfc_class_data_get (argse
.expr
);
7388 source
= argse
.expr
;
7390 /* Obtain the source word length. */
7391 switch (arg
->expr
->ts
.type
)
7394 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
,
7395 argse
.string_length
);
7398 tmp
= gfc_class_vtab_size_get (argse
.expr
);
7401 source_type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
7403 tmp
= fold_convert (gfc_array_index_type
,
7404 size_in_bytes (source_type
));
7410 argse
.want_pointer
= 0;
7411 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
7412 source
= gfc_conv_descriptor_data_get (argse
.expr
);
7413 source_type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
7415 /* Repack the source if not simply contiguous. */
7416 if (!gfc_is_simply_contiguous (arg
->expr
, false, true))
7418 tmp
= gfc_build_addr_expr (NULL_TREE
, argse
.expr
);
7420 if (warn_array_temporaries
)
7421 gfc_warning (OPT_Warray_temporaries
,
7422 "Creating array temporary at %L", &expr
->where
);
7424 source
= build_call_expr_loc (input_location
,
7425 gfor_fndecl_in_pack
, 1, tmp
);
7426 source
= gfc_evaluate_now (source
, &argse
.pre
);
7428 /* Free the temporary. */
7429 gfc_start_block (&block
);
7430 tmp
= gfc_call_free (source
);
7431 gfc_add_expr_to_block (&block
, tmp
);
7432 stmt
= gfc_finish_block (&block
);
7434 /* Clean up if it was repacked. */
7435 gfc_init_block (&block
);
7436 tmp
= gfc_conv_array_data (argse
.expr
);
7437 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
7439 tmp
= build3_v (COND_EXPR
, tmp
, stmt
,
7440 build_empty_stmt (input_location
));
7441 gfc_add_expr_to_block (&block
, tmp
);
7442 gfc_add_block_to_block (&block
, &se
->post
);
7443 gfc_init_block (&se
->post
);
7444 gfc_add_block_to_block (&se
->post
, &block
);
7447 /* Obtain the source word length. */
7448 if (arg
->expr
->ts
.type
== BT_CHARACTER
)
7449 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
,
7450 argse
.string_length
);
7452 tmp
= fold_convert (gfc_array_index_type
,
7453 size_in_bytes (source_type
));
7455 /* Obtain the size of the array in bytes. */
7456 extent
= gfc_create_var (gfc_array_index_type
, NULL
);
7457 for (n
= 0; n
< arg
->expr
->rank
; n
++)
7460 idx
= gfc_rank_cst
[n
];
7461 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
7462 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, idx
);
7463 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, idx
);
7464 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
7465 gfc_array_index_type
, upper
, lower
);
7466 gfc_add_modify (&argse
.pre
, extent
, tmp
);
7467 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
7468 gfc_array_index_type
, extent
,
7469 gfc_index_one_node
);
7470 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
7471 gfc_array_index_type
, tmp
, source_bytes
);
7475 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
7476 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7477 gfc_add_block_to_block (&se
->post
, &argse
.post
);
7479 /* Now convert MOLD. The outputs are:
7480 mold_type = the TREE type of MOLD
7481 dest_word_len = destination word length in bytes. */
7483 mold_expr
= arg
->expr
;
7485 gfc_init_se (&argse
, NULL
);
7487 scalar_mold
= arg
->expr
->rank
== 0;
7489 if (arg
->expr
->rank
== 0)
7491 gfc_conv_expr_reference (&argse
, arg
->expr
);
7492 mold_type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
7497 gfc_init_se (&argse
, NULL
);
7498 argse
.want_pointer
= 0;
7499 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
7500 mold_type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
7503 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7504 gfc_add_block_to_block (&se
->post
, &argse
.post
);
7506 if (strcmp (expr
->value
.function
.name
, "__transfer_in_transfer") == 0)
7508 /* If this TRANSFER is nested in another TRANSFER, use a type
7509 that preserves all bits. */
7510 if (arg
->expr
->ts
.type
== BT_LOGICAL
)
7511 mold_type
= gfc_get_int_type (arg
->expr
->ts
.kind
);
7514 /* Obtain the destination word length. */
7515 switch (arg
->expr
->ts
.type
)
7518 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
, argse
.string_length
);
7519 mold_type
= gfc_get_character_type_len (arg
->expr
->ts
.kind
, tmp
);
7522 tmp
= gfc_class_vtab_size_get (argse
.expr
);
7525 tmp
= fold_convert (gfc_array_index_type
, size_in_bytes (mold_type
));
7528 dest_word_len
= gfc_create_var (gfc_array_index_type
, NULL
);
7529 gfc_add_modify (&se
->pre
, dest_word_len
, tmp
);
7531 /* Finally convert SIZE, if it is present. */
7533 size_words
= gfc_create_var (gfc_array_index_type
, NULL
);
7537 gfc_init_se (&argse
, NULL
);
7538 gfc_conv_expr_reference (&argse
, arg
->expr
);
7539 tmp
= convert (gfc_array_index_type
,
7540 build_fold_indirect_ref_loc (input_location
,
7542 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7543 gfc_add_block_to_block (&se
->post
, &argse
.post
);
7548 /* Separate array and scalar results. */
7549 if (scalar_mold
&& tmp
== NULL_TREE
)
7550 goto scalar_transfer
;
7552 size_bytes
= gfc_create_var (gfc_array_index_type
, NULL
);
7553 if (tmp
!= NULL_TREE
)
7554 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, gfc_array_index_type
,
7555 tmp
, dest_word_len
);
7559 gfc_add_modify (&se
->pre
, size_bytes
, tmp
);
7560 gfc_add_modify (&se
->pre
, size_words
,
7561 fold_build2_loc (input_location
, CEIL_DIV_EXPR
,
7562 gfc_array_index_type
,
7563 size_bytes
, dest_word_len
));
7565 /* Evaluate the bounds of the result. If the loop range exists, we have
7566 to check if it is too large. If so, we modify loop->to be consistent
7567 with min(size, size(source)). Otherwise, size is made consistent with
7568 the loop range, so that the right number of bytes is transferred.*/
7569 n
= se
->loop
->order
[0];
7570 if (se
->loop
->to
[n
] != NULL_TREE
)
7572 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
7573 se
->loop
->to
[n
], se
->loop
->from
[n
]);
7574 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
7575 tmp
, gfc_index_one_node
);
7576 tmp
= fold_build2_loc (input_location
, MIN_EXPR
, gfc_array_index_type
,
7578 gfc_add_modify (&se
->pre
, size_words
, tmp
);
7579 gfc_add_modify (&se
->pre
, size_bytes
,
7580 fold_build2_loc (input_location
, MULT_EXPR
,
7581 gfc_array_index_type
,
7582 size_words
, dest_word_len
));
7583 upper
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
7584 size_words
, se
->loop
->from
[n
]);
7585 upper
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
7586 upper
, gfc_index_one_node
);
7590 upper
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
7591 size_words
, gfc_index_one_node
);
7592 se
->loop
->from
[n
] = gfc_index_zero_node
;
7595 se
->loop
->to
[n
] = upper
;
7597 /* Build a destination descriptor, using the pointer, source, as the
7599 gfc_trans_create_temp_array (&se
->pre
, &se
->post
, se
->ss
, mold_type
,
7600 NULL_TREE
, false, true, false, &expr
->where
);
7602 /* Cast the pointer to the result. */
7603 tmp
= gfc_conv_descriptor_data_get (info
->descriptor
);
7604 tmp
= fold_convert (pvoid_type_node
, tmp
);
7606 /* Use memcpy to do the transfer. */
7608 = build_call_expr_loc (input_location
,
7609 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3, tmp
,
7610 fold_convert (pvoid_type_node
, source
),
7611 fold_convert (size_type_node
,
7612 fold_build2_loc (input_location
,
7614 gfc_array_index_type
,
7617 gfc_add_expr_to_block (&se
->pre
, tmp
);
7619 se
->expr
= info
->descriptor
;
7620 if (expr
->ts
.type
== BT_CHARACTER
)
7621 se
->string_length
= fold_convert (gfc_charlen_type_node
, dest_word_len
);
7625 /* Deal with scalar results. */
7627 extent
= fold_build2_loc (input_location
, MIN_EXPR
, gfc_array_index_type
,
7628 dest_word_len
, source_bytes
);
7629 extent
= fold_build2_loc (input_location
, MAX_EXPR
, gfc_array_index_type
,
7630 extent
, gfc_index_zero_node
);
7632 if (expr
->ts
.type
== BT_CHARACTER
)
7634 tree direct
, indirect
, free
;
7636 ptr
= convert (gfc_get_pchar_type (expr
->ts
.kind
), source
);
7637 tmpdecl
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
),
7640 /* If source is longer than the destination, use a pointer to
7641 the source directly. */
7642 gfc_init_block (&block
);
7643 gfc_add_modify (&block
, tmpdecl
, ptr
);
7644 direct
= gfc_finish_block (&block
);
7646 /* Otherwise, allocate a string with the length of the destination
7647 and copy the source into it. */
7648 gfc_init_block (&block
);
7649 tmp
= gfc_get_pchar_type (expr
->ts
.kind
);
7650 tmp
= gfc_call_malloc (&block
, tmp
, dest_word_len
);
7651 gfc_add_modify (&block
, tmpdecl
,
7652 fold_convert (TREE_TYPE (ptr
), tmp
));
7653 tmp
= build_call_expr_loc (input_location
,
7654 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3,
7655 fold_convert (pvoid_type_node
, tmpdecl
),
7656 fold_convert (pvoid_type_node
, ptr
),
7657 fold_convert (size_type_node
, extent
));
7658 gfc_add_expr_to_block (&block
, tmp
);
7659 indirect
= gfc_finish_block (&block
);
7661 /* Wrap it up with the condition. */
7662 tmp
= fold_build2_loc (input_location
, LE_EXPR
, logical_type_node
,
7663 dest_word_len
, source_bytes
);
7664 tmp
= build3_v (COND_EXPR
, tmp
, direct
, indirect
);
7665 gfc_add_expr_to_block (&se
->pre
, tmp
);
7667 /* Free the temporary string, if necessary. */
7668 free
= gfc_call_free (tmpdecl
);
7669 tmp
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
7670 dest_word_len
, source_bytes
);
7671 tmp
= build3_v (COND_EXPR
, tmp
, free
, build_empty_stmt (input_location
));
7672 gfc_add_expr_to_block (&se
->post
, tmp
);
7675 se
->string_length
= fold_convert (gfc_charlen_type_node
, dest_word_len
);
7679 tmpdecl
= gfc_create_var (mold_type
, "transfer");
7681 ptr
= convert (build_pointer_type (mold_type
), source
);
7683 /* For CLASS results, allocate the needed memory first. */
7684 if (mold_expr
->ts
.type
== BT_CLASS
)
7687 cdata
= gfc_class_data_get (tmpdecl
);
7688 tmp
= gfc_call_malloc (&se
->pre
, TREE_TYPE (cdata
), dest_word_len
);
7689 gfc_add_modify (&se
->pre
, cdata
, tmp
);
7692 /* Use memcpy to do the transfer. */
7693 if (mold_expr
->ts
.type
== BT_CLASS
)
7694 tmp
= gfc_class_data_get (tmpdecl
);
7696 tmp
= gfc_build_addr_expr (NULL_TREE
, tmpdecl
);
7698 tmp
= build_call_expr_loc (input_location
,
7699 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3,
7700 fold_convert (pvoid_type_node
, tmp
),
7701 fold_convert (pvoid_type_node
, ptr
),
7702 fold_convert (size_type_node
, extent
));
7703 gfc_add_expr_to_block (&se
->pre
, tmp
);
7705 /* For CLASS results, set the _vptr. */
7706 if (mold_expr
->ts
.type
== BT_CLASS
)
7710 vptr
= gfc_class_vptr_get (tmpdecl
);
7711 vtab
= gfc_find_derived_vtab (source_expr
->ts
.u
.derived
);
7713 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
7714 gfc_add_modify (&se
->pre
, vptr
, fold_convert (TREE_TYPE (vptr
), tmp
));
7722 /* Generate a call to caf_is_present. */
7725 trans_caf_is_present (gfc_se
*se
, gfc_expr
*expr
)
7727 tree caf_reference
, caf_decl
, token
, image_index
;
7729 /* Compile the reference chain. */
7730 caf_reference
= conv_expr_ref_to_caf_ref (&se
->pre
, expr
);
7731 gcc_assert (caf_reference
!= NULL_TREE
);
7733 caf_decl
= gfc_get_tree_for_caf_expr (expr
);
7734 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
7735 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
7736 image_index
= gfc_caf_get_image_index (&se
->pre
, expr
, caf_decl
);
7737 gfc_get_caf_token_offset (se
, &token
, NULL
, caf_decl
, NULL
,
7740 return build_call_expr_loc (input_location
, gfor_fndecl_caf_is_present
,
7741 3, token
, image_index
, caf_reference
);
7745 /* Test whether this ref-chain refs this image only. */
7748 caf_this_image_ref (gfc_ref
*ref
)
7750 for ( ; ref
; ref
= ref
->next
)
7751 if (ref
->type
== REF_ARRAY
&& ref
->u
.ar
.codimen
)
7752 return ref
->u
.ar
.dimen_type
[ref
->u
.ar
.dimen
] == DIMEN_THIS_IMAGE
;
7758 /* Generate code for the ALLOCATED intrinsic.
7759 Generate inline code that directly check the address of the argument. */
7762 gfc_conv_allocated (gfc_se
*se
, gfc_expr
*expr
)
7764 gfc_actual_arglist
*arg1
;
7767 symbol_attribute caf_attr
;
7769 gfc_init_se (&arg1se
, NULL
);
7770 arg1
= expr
->value
.function
.actual
;
7772 if (arg1
->expr
->ts
.type
== BT_CLASS
)
7774 /* Make sure that class array expressions have both a _data
7775 component reference and an array reference.... */
7776 if (CLASS_DATA (arg1
->expr
)->attr
.dimension
)
7777 gfc_add_class_array_ref (arg1
->expr
);
7778 /* .... whilst scalars only need the _data component. */
7780 gfc_add_data_component (arg1
->expr
);
7783 /* When arg1 references an allocatable component in a coarray, then call
7784 the caf-library function caf_is_present (). */
7785 if (flag_coarray
== GFC_FCOARRAY_LIB
&& arg1
->expr
->expr_type
== EXPR_FUNCTION
7786 && arg1
->expr
->value
.function
.isym
7787 && arg1
->expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
7788 caf_attr
= gfc_caf_attr (arg1
->expr
->value
.function
.actual
->expr
);
7790 gfc_clear_attr (&caf_attr
);
7791 if (flag_coarray
== GFC_FCOARRAY_LIB
&& caf_attr
.codimension
7792 && !caf_this_image_ref (arg1
->expr
->value
.function
.actual
->expr
->ref
))
7793 tmp
= trans_caf_is_present (se
, arg1
->expr
->value
.function
.actual
->expr
);
7796 if (arg1
->expr
->rank
== 0)
7798 /* Allocatable scalar. */
7799 arg1se
.want_pointer
= 1;
7800 gfc_conv_expr (&arg1se
, arg1
->expr
);
7805 /* Allocatable array. */
7806 arg1se
.descriptor_only
= 1;
7807 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
7808 tmp
= gfc_conv_descriptor_data_get (arg1se
.expr
);
7811 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, tmp
,
7812 fold_convert (TREE_TYPE (tmp
), null_pointer_node
));
7815 /* Components of pointer array references sometimes come back with a pre block. */
7816 if (arg1se
.pre
.head
)
7817 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
7819 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), tmp
);
7823 /* Generate code for the ASSOCIATED intrinsic.
7824 If both POINTER and TARGET are arrays, generate a call to library function
7825 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
7826 In other cases, generate inline code that directly compare the address of
7827 POINTER with the address of TARGET. */
7830 gfc_conv_associated (gfc_se
*se
, gfc_expr
*expr
)
7832 gfc_actual_arglist
*arg1
;
7833 gfc_actual_arglist
*arg2
;
7838 tree nonzero_charlen
;
7839 tree nonzero_arraylen
;
7843 gfc_init_se (&arg1se
, NULL
);
7844 gfc_init_se (&arg2se
, NULL
);
7845 arg1
= expr
->value
.function
.actual
;
7848 /* Check whether the expression is a scalar or not; we cannot use
7849 arg1->expr->rank as it can be nonzero for proc pointers. */
7850 ss
= gfc_walk_expr (arg1
->expr
);
7851 scalar
= ss
== gfc_ss_terminator
;
7853 gfc_free_ss_chain (ss
);
7857 /* No optional target. */
7860 /* A pointer to a scalar. */
7861 arg1se
.want_pointer
= 1;
7862 gfc_conv_expr (&arg1se
, arg1
->expr
);
7863 if (arg1
->expr
->symtree
->n
.sym
->attr
.proc_pointer
7864 && arg1
->expr
->symtree
->n
.sym
->attr
.dummy
)
7865 arg1se
.expr
= build_fold_indirect_ref_loc (input_location
,
7867 if (arg1
->expr
->ts
.type
== BT_CLASS
)
7869 tmp2
= gfc_class_data_get (arg1se
.expr
);
7870 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2
)))
7871 tmp2
= gfc_conv_descriptor_data_get (tmp2
);
7878 /* A pointer to an array. */
7879 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
7880 tmp2
= gfc_conv_descriptor_data_get (arg1se
.expr
);
7882 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
7883 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
7884 tmp
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
, tmp2
,
7885 fold_convert (TREE_TYPE (tmp2
), null_pointer_node
));
7890 /* An optional target. */
7891 if (arg2
->expr
->ts
.type
== BT_CLASS
)
7892 gfc_add_data_component (arg2
->expr
);
7894 nonzero_charlen
= NULL_TREE
;
7895 if (arg1
->expr
->ts
.type
== BT_CHARACTER
)
7896 nonzero_charlen
= fold_build2_loc (input_location
, NE_EXPR
,
7898 arg1
->expr
->ts
.u
.cl
->backend_decl
,
7900 (TREE_TYPE (arg1
->expr
->ts
.u
.cl
->backend_decl
)));
7903 /* A pointer to a scalar. */
7904 arg1se
.want_pointer
= 1;
7905 gfc_conv_expr (&arg1se
, arg1
->expr
);
7906 if (arg1
->expr
->symtree
->n
.sym
->attr
.proc_pointer
7907 && arg1
->expr
->symtree
->n
.sym
->attr
.dummy
)
7908 arg1se
.expr
= build_fold_indirect_ref_loc (input_location
,
7910 if (arg1
->expr
->ts
.type
== BT_CLASS
)
7911 arg1se
.expr
= gfc_class_data_get (arg1se
.expr
);
7913 arg2se
.want_pointer
= 1;
7914 gfc_conv_expr (&arg2se
, arg2
->expr
);
7915 if (arg2
->expr
->symtree
->n
.sym
->attr
.proc_pointer
7916 && arg2
->expr
->symtree
->n
.sym
->attr
.dummy
)
7917 arg2se
.expr
= build_fold_indirect_ref_loc (input_location
,
7919 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
7920 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
7921 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
7922 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
7923 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
7924 arg1se
.expr
, arg2se
.expr
);
7925 tmp2
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
7926 arg1se
.expr
, null_pointer_node
);
7927 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
7928 logical_type_node
, tmp
, tmp2
);
7932 /* An array pointer of zero length is not associated if target is
7934 arg1se
.descriptor_only
= 1;
7935 gfc_conv_expr_lhs (&arg1se
, arg1
->expr
);
7936 if (arg1
->expr
->rank
== -1)
7938 tmp
= gfc_conv_descriptor_rank (arg1se
.expr
);
7939 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
7940 TREE_TYPE (tmp
), tmp
, gfc_index_one_node
);
7943 tmp
= gfc_rank_cst
[arg1
->expr
->rank
- 1];
7944 tmp
= gfc_conv_descriptor_stride_get (arg1se
.expr
, tmp
);
7945 nonzero_arraylen
= fold_build2_loc (input_location
, NE_EXPR
,
7946 logical_type_node
, tmp
,
7947 build_int_cst (TREE_TYPE (tmp
), 0));
7949 /* A pointer to an array, call library function _gfor_associated. */
7950 arg1se
.want_pointer
= 1;
7951 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
7952 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
7953 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
7955 arg2se
.want_pointer
= 1;
7956 gfc_conv_expr_descriptor (&arg2se
, arg2
->expr
);
7957 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
7958 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
7959 se
->expr
= build_call_expr_loc (input_location
,
7960 gfor_fndecl_associated
, 2,
7961 arg1se
.expr
, arg2se
.expr
);
7962 se
->expr
= convert (logical_type_node
, se
->expr
);
7963 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
7964 logical_type_node
, se
->expr
,
7968 /* If target is present zero character length pointers cannot
7970 if (nonzero_charlen
!= NULL_TREE
)
7971 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
7973 se
->expr
, nonzero_charlen
);
7976 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
7980 /* Generate code for the SAME_TYPE_AS intrinsic.
7981 Generate inline code that directly checks the vindices. */
7984 gfc_conv_same_type_as (gfc_se
*se
, gfc_expr
*expr
)
7989 tree conda
= NULL_TREE
, condb
= NULL_TREE
;
7991 gfc_init_se (&se1
, NULL
);
7992 gfc_init_se (&se2
, NULL
);
7994 a
= expr
->value
.function
.actual
->expr
;
7995 b
= expr
->value
.function
.actual
->next
->expr
;
7997 if (UNLIMITED_POLY (a
))
7999 tmp
= gfc_class_vptr_get (a
->symtree
->n
.sym
->backend_decl
);
8000 conda
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
8001 tmp
, build_int_cst (TREE_TYPE (tmp
), 0));
8004 if (UNLIMITED_POLY (b
))
8006 tmp
= gfc_class_vptr_get (b
->symtree
->n
.sym
->backend_decl
);
8007 condb
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
8008 tmp
, build_int_cst (TREE_TYPE (tmp
), 0));
8011 if (a
->ts
.type
== BT_CLASS
)
8013 gfc_add_vptr_component (a
);
8014 gfc_add_hash_component (a
);
8016 else if (a
->ts
.type
== BT_DERIVED
)
8017 a
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
,
8018 a
->ts
.u
.derived
->hash_value
);
8020 if (b
->ts
.type
== BT_CLASS
)
8022 gfc_add_vptr_component (b
);
8023 gfc_add_hash_component (b
);
8025 else if (b
->ts
.type
== BT_DERIVED
)
8026 b
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
,
8027 b
->ts
.u
.derived
->hash_value
);
8029 gfc_conv_expr (&se1
, a
);
8030 gfc_conv_expr (&se2
, b
);
8032 tmp
= fold_build2_loc (input_location
, EQ_EXPR
,
8033 logical_type_node
, se1
.expr
,
8034 fold_convert (TREE_TYPE (se1
.expr
), se2
.expr
));
8037 tmp
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
8038 logical_type_node
, conda
, tmp
);
8041 tmp
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
8042 logical_type_node
, condb
, tmp
);
8044 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), tmp
);
8048 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
8051 gfc_conv_intrinsic_sc_kind (gfc_se
*se
, gfc_expr
*expr
)
8055 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
8056 se
->expr
= build_call_expr_loc (input_location
,
8057 gfor_fndecl_sc_kind
, 2, args
[0], args
[1]);
8058 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
8062 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
8065 gfc_conv_intrinsic_si_kind (gfc_se
*se
, gfc_expr
*expr
)
8069 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
8071 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
8072 type
= gfc_get_int_type (4);
8073 arg
= gfc_build_addr_expr (NULL_TREE
, fold_convert (type
, arg
));
8075 /* Convert it to the required type. */
8076 type
= gfc_typenode_for_spec (&expr
->ts
);
8077 se
->expr
= build_call_expr_loc (input_location
,
8078 gfor_fndecl_si_kind
, 1, arg
);
8079 se
->expr
= fold_convert (type
, se
->expr
);
8083 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
8086 gfc_conv_intrinsic_sr_kind (gfc_se
*se
, gfc_expr
*expr
)
8088 gfc_actual_arglist
*actual
;
8091 vec
<tree
, va_gc
> *args
= NULL
;
8093 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
8095 gfc_init_se (&argse
, se
);
8097 /* Pass a NULL pointer for an absent arg. */
8098 if (actual
->expr
== NULL
)
8099 argse
.expr
= null_pointer_node
;
8105 if (actual
->expr
->ts
.kind
!= gfc_c_int_kind
)
8107 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
8108 ts
.type
= BT_INTEGER
;
8109 ts
.kind
= gfc_c_int_kind
;
8110 gfc_convert_type (actual
->expr
, &ts
, 2);
8112 gfc_conv_expr_reference (&argse
, actual
->expr
);
8115 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8116 gfc_add_block_to_block (&se
->post
, &argse
.post
);
8117 vec_safe_push (args
, argse
.expr
);
8120 /* Convert it to the required type. */
8121 type
= gfc_typenode_for_spec (&expr
->ts
);
8122 se
->expr
= build_call_expr_loc_vec (input_location
,
8123 gfor_fndecl_sr_kind
, args
);
8124 se
->expr
= fold_convert (type
, se
->expr
);
8128 /* Generate code for TRIM (A) intrinsic function. */
8131 gfc_conv_intrinsic_trim (gfc_se
* se
, gfc_expr
* expr
)
8141 unsigned int num_args
;
8143 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
8144 args
= XALLOCAVEC (tree
, num_args
);
8146 var
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
), "pstr");
8147 addr
= gfc_build_addr_expr (ppvoid_type_node
, var
);
8148 len
= gfc_create_var (gfc_charlen_type_node
, "len");
8150 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
8151 args
[0] = gfc_build_addr_expr (NULL_TREE
, len
);
8154 if (expr
->ts
.kind
== 1)
8155 function
= gfor_fndecl_string_trim
;
8156 else if (expr
->ts
.kind
== 4)
8157 function
= gfor_fndecl_string_trim_char4
;
8161 fndecl
= build_addr (function
);
8162 tmp
= build_call_array_loc (input_location
,
8163 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
8165 gfc_add_expr_to_block (&se
->pre
, tmp
);
8167 /* Free the temporary afterwards, if necessary. */
8168 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
8169 len
, build_int_cst (TREE_TYPE (len
), 0));
8170 tmp
= gfc_call_free (var
);
8171 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
8172 gfc_add_expr_to_block (&se
->post
, tmp
);
8175 se
->string_length
= len
;
8179 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
8182 gfc_conv_intrinsic_repeat (gfc_se
* se
, gfc_expr
* expr
)
8184 tree args
[3], ncopies
, dest
, dlen
, src
, slen
, ncopies_type
;
8185 tree type
, cond
, tmp
, count
, exit_label
, n
, max
, largest
;
8187 stmtblock_t block
, body
;
8190 /* We store in charsize the size of a character. */
8191 i
= gfc_validate_kind (BT_CHARACTER
, expr
->ts
.kind
, false);
8192 size
= build_int_cst (sizetype
, gfc_character_kinds
[i
].bit_size
/ 8);
8194 /* Get the arguments. */
8195 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
8196 slen
= fold_convert (sizetype
, gfc_evaluate_now (args
[0], &se
->pre
));
8198 ncopies
= gfc_evaluate_now (args
[2], &se
->pre
);
8199 ncopies_type
= TREE_TYPE (ncopies
);
8201 /* Check that NCOPIES is not negative. */
8202 cond
= fold_build2_loc (input_location
, LT_EXPR
, logical_type_node
, ncopies
,
8203 build_int_cst (ncopies_type
, 0));
8204 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
8205 "Argument NCOPIES of REPEAT intrinsic is negative "
8206 "(its value is %ld)",
8207 fold_convert (long_integer_type_node
, ncopies
));
8209 /* If the source length is zero, any non negative value of NCOPIES
8210 is valid, and nothing happens. */
8211 n
= gfc_create_var (ncopies_type
, "ncopies");
8212 cond
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, slen
,
8214 tmp
= fold_build3_loc (input_location
, COND_EXPR
, ncopies_type
, cond
,
8215 build_int_cst (ncopies_type
, 0), ncopies
);
8216 gfc_add_modify (&se
->pre
, n
, tmp
);
8219 /* Check that ncopies is not too large: ncopies should be less than
8220 (or equal to) MAX / slen, where MAX is the maximal integer of
8221 the gfc_charlen_type_node type. If slen == 0, we need a special
8222 case to avoid the division by zero. */
8223 max
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
, sizetype
,
8224 fold_convert (sizetype
,
8225 TYPE_MAX_VALUE (gfc_charlen_type_node
)),
8227 largest
= TYPE_PRECISION (sizetype
) > TYPE_PRECISION (ncopies_type
)
8228 ? sizetype
: ncopies_type
;
8229 cond
= fold_build2_loc (input_location
, GT_EXPR
, logical_type_node
,
8230 fold_convert (largest
, ncopies
),
8231 fold_convert (largest
, max
));
8232 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, slen
,
8234 cond
= fold_build3_loc (input_location
, COND_EXPR
, logical_type_node
, tmp
,
8235 logical_false_node
, cond
);
8236 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
8237 "Argument NCOPIES of REPEAT intrinsic is too large");
8239 /* Compute the destination length. */
8240 dlen
= fold_build2_loc (input_location
, MULT_EXPR
, gfc_charlen_type_node
,
8241 fold_convert (gfc_charlen_type_node
, slen
),
8242 fold_convert (gfc_charlen_type_node
, ncopies
));
8243 type
= gfc_get_character_type (expr
->ts
.kind
, expr
->ts
.u
.cl
);
8244 dest
= gfc_conv_string_tmp (se
, build_pointer_type (type
), dlen
);
8246 /* Generate the code to do the repeat operation:
8247 for (i = 0; i < ncopies; i++)
8248 memmove (dest + (i * slen * size), src, slen*size); */
8249 gfc_start_block (&block
);
8250 count
= gfc_create_var (sizetype
, "count");
8251 gfc_add_modify (&block
, count
, size_zero_node
);
8252 exit_label
= gfc_build_label_decl (NULL_TREE
);
8254 /* Start the loop body. */
8255 gfc_start_block (&body
);
8257 /* Exit the loop if count >= ncopies. */
8258 cond
= fold_build2_loc (input_location
, GE_EXPR
, logical_type_node
, count
,
8259 fold_convert (sizetype
, ncopies
));
8260 tmp
= build1_v (GOTO_EXPR
, exit_label
);
8261 TREE_USED (exit_label
) = 1;
8262 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
, tmp
,
8263 build_empty_stmt (input_location
));
8264 gfc_add_expr_to_block (&body
, tmp
);
8266 /* Call memmove (dest + (i*slen*size), src, slen*size). */
8267 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, sizetype
, slen
,
8269 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, sizetype
, tmp
,
8271 tmp
= fold_build_pointer_plus_loc (input_location
,
8272 fold_convert (pvoid_type_node
, dest
), tmp
);
8273 tmp
= build_call_expr_loc (input_location
,
8274 builtin_decl_explicit (BUILT_IN_MEMMOVE
),
8276 fold_build2_loc (input_location
, MULT_EXPR
,
8277 size_type_node
, slen
, size
));
8278 gfc_add_expr_to_block (&body
, tmp
);
8280 /* Increment count. */
8281 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, sizetype
,
8282 count
, size_one_node
);
8283 gfc_add_modify (&body
, count
, tmp
);
8285 /* Build the loop. */
8286 tmp
= build1_v (LOOP_EXPR
, gfc_finish_block (&body
));
8287 gfc_add_expr_to_block (&block
, tmp
);
8289 /* Add the exit label. */
8290 tmp
= build1_v (LABEL_EXPR
, exit_label
);
8291 gfc_add_expr_to_block (&block
, tmp
);
8293 /* Finish the block. */
8294 tmp
= gfc_finish_block (&block
);
8295 gfc_add_expr_to_block (&se
->pre
, tmp
);
8297 /* Set the result value. */
8299 se
->string_length
= dlen
;
8303 /* Generate code for the IARGC intrinsic. */
8306 gfc_conv_intrinsic_iargc (gfc_se
* se
, gfc_expr
* expr
)
8312 /* Call the library function. This always returns an INTEGER(4). */
8313 fndecl
= gfor_fndecl_iargc
;
8314 tmp
= build_call_expr_loc (input_location
,
8317 /* Convert it to the required type. */
8318 type
= gfc_typenode_for_spec (&expr
->ts
);
8319 tmp
= fold_convert (type
, tmp
);
8325 /* Generate code for the KILL intrinsic. */
8328 conv_intrinsic_kill (gfc_se
*se
, gfc_expr
*expr
)
8331 tree int4_type_node
= gfc_get_int_type (4);
8335 unsigned int num_args
;
8337 num_args
= gfc_intrinsic_argument_list_length (expr
);
8338 args
= XALLOCAVEC (tree
, num_args
);
8339 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
8341 /* Convert PID to a INTEGER(4) entity. */
8342 pid
= convert (int4_type_node
, args
[0]);
8344 /* Convert SIG to a INTEGER(4) entity. */
8345 sig
= convert (int4_type_node
, args
[1]);
8347 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_kill
, 2, pid
, sig
);
8349 se
->expr
= fold_convert (TREE_TYPE (args
[0]), tmp
);
8354 conv_intrinsic_kill_sub (gfc_code
*code
)
8358 tree int4_type_node
= gfc_get_int_type (4);
8364 /* Make the function call. */
8365 gfc_init_block (&block
);
8366 gfc_init_se (&se
, NULL
);
8368 /* Convert PID to a INTEGER(4) entity. */
8369 gfc_conv_expr (&se
, code
->ext
.actual
->expr
);
8370 gfc_add_block_to_block (&block
, &se
.pre
);
8371 pid
= fold_convert (int4_type_node
, gfc_evaluate_now (se
.expr
, &block
));
8372 gfc_add_block_to_block (&block
, &se
.post
);
8374 /* Convert SIG to a INTEGER(4) entity. */
8375 gfc_conv_expr (&se
, code
->ext
.actual
->next
->expr
);
8376 gfc_add_block_to_block (&block
, &se
.pre
);
8377 sig
= fold_convert (int4_type_node
, gfc_evaluate_now (se
.expr
, &block
));
8378 gfc_add_block_to_block (&block
, &se
.post
);
8380 /* Deal with an optional STATUS. */
8381 if (code
->ext
.actual
->next
->next
->expr
)
8383 gfc_init_se (&se_stat
, NULL
);
8384 gfc_conv_expr (&se_stat
, code
->ext
.actual
->next
->next
->expr
);
8385 statp
= gfc_create_var (gfc_get_int_type (4), "_statp");
8390 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_kill_sub
, 3, pid
, sig
,
8391 statp
? gfc_build_addr_expr (NULL_TREE
, statp
) : null_pointer_node
);
8393 gfc_add_expr_to_block (&block
, tmp
);
8395 if (statp
&& statp
!= se_stat
.expr
)
8396 gfc_add_modify (&block
, se_stat
.expr
,
8397 fold_convert (TREE_TYPE (se_stat
.expr
), statp
));
8399 return gfc_finish_block (&block
);
8404 /* The loc intrinsic returns the address of its argument as
8405 gfc_index_integer_kind integer. */
8408 gfc_conv_intrinsic_loc (gfc_se
* se
, gfc_expr
* expr
)
8413 gcc_assert (!se
->ss
);
8415 arg_expr
= expr
->value
.function
.actual
->expr
;
8416 if (arg_expr
->rank
== 0)
8418 if (arg_expr
->ts
.type
== BT_CLASS
)
8419 gfc_add_data_component (arg_expr
);
8420 gfc_conv_expr_reference (se
, arg_expr
);
8423 gfc_conv_array_parameter (se
, arg_expr
, true, NULL
, NULL
, NULL
);
8424 se
->expr
= convert (gfc_get_int_type (gfc_index_integer_kind
), se
->expr
);
8426 /* Create a temporary variable for loc return value. Without this,
8427 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
8428 temp_var
= gfc_create_var (gfc_get_int_type (gfc_index_integer_kind
), NULL
);
8429 gfc_add_modify (&se
->pre
, temp_var
, se
->expr
);
8430 se
->expr
= temp_var
;
8434 /* The following routine generates code for the intrinsic
8435 functions from the ISO_C_BINDING module:
8441 conv_isocbinding_function (gfc_se
*se
, gfc_expr
*expr
)
8443 gfc_actual_arglist
*arg
= expr
->value
.function
.actual
;
8445 if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_LOC
)
8447 if (arg
->expr
->rank
== 0)
8448 gfc_conv_expr_reference (se
, arg
->expr
);
8449 else if (gfc_is_simply_contiguous (arg
->expr
, false, false))
8450 gfc_conv_array_parameter (se
, arg
->expr
, true, NULL
, NULL
, NULL
);
8453 gfc_conv_expr_descriptor (se
, arg
->expr
);
8454 se
->expr
= gfc_conv_descriptor_data_get (se
->expr
);
8457 /* TODO -- the following two lines shouldn't be necessary, but if
8458 they're removed, a bug is exposed later in the code path.
8459 This workaround was thus introduced, but will have to be
8460 removed; please see PR 35150 for details about the issue. */
8461 se
->expr
= convert (pvoid_type_node
, se
->expr
);
8462 se
->expr
= gfc_evaluate_now (se
->expr
, &se
->pre
);
8464 else if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_FUNLOC
)
8465 gfc_conv_expr_reference (se
, arg
->expr
);
8466 else if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_ASSOCIATED
)
8471 /* Build the addr_expr for the first argument. The argument is
8472 already an *address* so we don't need to set want_pointer in
8474 gfc_init_se (&arg1se
, NULL
);
8475 gfc_conv_expr (&arg1se
, arg
->expr
);
8476 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
8477 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
8479 /* See if we were given two arguments. */
8480 if (arg
->next
->expr
== NULL
)
8481 /* Only given one arg so generate a null and do a
8482 not-equal comparison against the first arg. */
8483 se
->expr
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
8485 fold_convert (TREE_TYPE (arg1se
.expr
),
8486 null_pointer_node
));
8492 /* Given two arguments so build the arg2se from second arg. */
8493 gfc_init_se (&arg2se
, NULL
);
8494 gfc_conv_expr (&arg2se
, arg
->next
->expr
);
8495 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
8496 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
8498 /* Generate test to compare that the two args are equal. */
8499 eq_expr
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
,
8500 arg1se
.expr
, arg2se
.expr
);
8501 /* Generate test to ensure that the first arg is not null. */
8502 not_null_expr
= fold_build2_loc (input_location
, NE_EXPR
,
8504 arg1se
.expr
, null_pointer_node
);
8506 /* Finally, the generated test must check that both arg1 is not
8507 NULL and that it is equal to the second arg. */
8508 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
8510 not_null_expr
, eq_expr
);
8518 /* The following routine generates code for the intrinsic
8519 subroutines from the ISO_C_BINDING module:
8521 * C_F_PROCPOINTER. */
8524 conv_isocbinding_subroutine (gfc_code
*code
)
8531 tree desc
, dim
, tmp
, stride
, offset
;
8532 stmtblock_t body
, block
;
8534 gfc_actual_arglist
*arg
= code
->ext
.actual
;
8536 gfc_init_se (&se
, NULL
);
8537 gfc_init_se (&cptrse
, NULL
);
8538 gfc_conv_expr (&cptrse
, arg
->expr
);
8539 gfc_add_block_to_block (&se
.pre
, &cptrse
.pre
);
8540 gfc_add_block_to_block (&se
.post
, &cptrse
.post
);
8542 gfc_init_se (&fptrse
, NULL
);
8543 if (arg
->next
->expr
->rank
== 0)
8545 fptrse
.want_pointer
= 1;
8546 gfc_conv_expr (&fptrse
, arg
->next
->expr
);
8547 gfc_add_block_to_block (&se
.pre
, &fptrse
.pre
);
8548 gfc_add_block_to_block (&se
.post
, &fptrse
.post
);
8549 if (arg
->next
->expr
->symtree
->n
.sym
->attr
.proc_pointer
8550 && arg
->next
->expr
->symtree
->n
.sym
->attr
.dummy
)
8551 fptrse
.expr
= build_fold_indirect_ref_loc (input_location
,
8553 se
.expr
= fold_build2_loc (input_location
, MODIFY_EXPR
,
8554 TREE_TYPE (fptrse
.expr
),
8556 fold_convert (TREE_TYPE (fptrse
.expr
),
8558 gfc_add_expr_to_block (&se
.pre
, se
.expr
);
8559 gfc_add_block_to_block (&se
.pre
, &se
.post
);
8560 return gfc_finish_block (&se
.pre
);
8563 gfc_start_block (&block
);
8565 /* Get the descriptor of the Fortran pointer. */
8566 fptrse
.descriptor_only
= 1;
8567 gfc_conv_expr_descriptor (&fptrse
, arg
->next
->expr
);
8568 gfc_add_block_to_block (&block
, &fptrse
.pre
);
8571 /* Set the span field. */
8572 tmp
= TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc
)));
8573 tmp
= fold_convert (gfc_array_index_type
, tmp
);
8574 gfc_conv_descriptor_span_set (&block
, desc
, tmp
);
8576 /* Set data value, dtype, and offset. */
8577 tmp
= GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc
));
8578 gfc_conv_descriptor_data_set (&block
, desc
, fold_convert (tmp
, cptrse
.expr
));
8579 gfc_add_modify (&block
, gfc_conv_descriptor_dtype (desc
),
8580 gfc_get_dtype (TREE_TYPE (desc
)));
8582 /* Start scalarization of the bounds, using the shape argument. */
8584 shape_ss
= gfc_walk_expr (arg
->next
->next
->expr
);
8585 gcc_assert (shape_ss
!= gfc_ss_terminator
);
8586 gfc_init_se (&shapese
, NULL
);
8588 gfc_init_loopinfo (&loop
);
8589 gfc_add_ss_to_loop (&loop
, shape_ss
);
8590 gfc_conv_ss_startstride (&loop
);
8591 gfc_conv_loop_setup (&loop
, &arg
->next
->expr
->where
);
8592 gfc_mark_ss_chain_used (shape_ss
, 1);
8594 gfc_copy_loopinfo_to_se (&shapese
, &loop
);
8595 shapese
.ss
= shape_ss
;
8597 stride
= gfc_create_var (gfc_array_index_type
, "stride");
8598 offset
= gfc_create_var (gfc_array_index_type
, "offset");
8599 gfc_add_modify (&block
, stride
, gfc_index_one_node
);
8600 gfc_add_modify (&block
, offset
, gfc_index_zero_node
);
8603 gfc_start_scalarized_body (&loop
, &body
);
8605 dim
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
8606 loop
.loopvar
[0], loop
.from
[0]);
8608 /* Set bounds and stride. */
8609 gfc_conv_descriptor_lbound_set (&body
, desc
, dim
, gfc_index_one_node
);
8610 gfc_conv_descriptor_stride_set (&body
, desc
, dim
, stride
);
8612 gfc_conv_expr (&shapese
, arg
->next
->next
->expr
);
8613 gfc_add_block_to_block (&body
, &shapese
.pre
);
8614 gfc_conv_descriptor_ubound_set (&body
, desc
, dim
, shapese
.expr
);
8615 gfc_add_block_to_block (&body
, &shapese
.post
);
8617 /* Calculate offset. */
8618 gfc_add_modify (&body
, offset
,
8619 fold_build2_loc (input_location
, PLUS_EXPR
,
8620 gfc_array_index_type
, offset
, stride
));
8621 /* Update stride. */
8622 gfc_add_modify (&body
, stride
,
8623 fold_build2_loc (input_location
, MULT_EXPR
,
8624 gfc_array_index_type
, stride
,
8625 fold_convert (gfc_array_index_type
,
8627 /* Finish scalarization loop. */
8628 gfc_trans_scalarizing_loops (&loop
, &body
);
8629 gfc_add_block_to_block (&block
, &loop
.pre
);
8630 gfc_add_block_to_block (&block
, &loop
.post
);
8631 gfc_add_block_to_block (&block
, &fptrse
.post
);
8632 gfc_cleanup_loop (&loop
);
8634 gfc_add_modify (&block
, offset
,
8635 fold_build1_loc (input_location
, NEGATE_EXPR
,
8636 gfc_array_index_type
, offset
));
8637 gfc_conv_descriptor_offset_set (&block
, desc
, offset
);
8639 gfc_add_expr_to_block (&se
.pre
, gfc_finish_block (&block
));
8640 gfc_add_block_to_block (&se
.pre
, &se
.post
);
8641 return gfc_finish_block (&se
.pre
);
8645 /* Save and restore floating-point state. */
8648 gfc_save_fp_state (stmtblock_t
*block
)
8650 tree type
, fpstate
, tmp
;
8652 type
= build_array_type (char_type_node
,
8653 build_range_type (size_type_node
, size_zero_node
,
8654 size_int (GFC_FPE_STATE_BUFFER_SIZE
)));
8655 fpstate
= gfc_create_var (type
, "fpstate");
8656 fpstate
= gfc_build_addr_expr (pvoid_type_node
, fpstate
);
8658 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_ieee_procedure_entry
,
8660 gfc_add_expr_to_block (block
, tmp
);
8667 gfc_restore_fp_state (stmtblock_t
*block
, tree fpstate
)
8671 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_ieee_procedure_exit
,
8673 gfc_add_expr_to_block (block
, tmp
);
8677 /* Generate code for arguments of IEEE functions. */
8680 conv_ieee_function_args (gfc_se
*se
, gfc_expr
*expr
, tree
*argarray
,
8683 gfc_actual_arglist
*actual
;
8688 actual
= expr
->value
.function
.actual
;
8689 for (arg
= 0; arg
< nargs
; arg
++, actual
= actual
->next
)
8691 gcc_assert (actual
);
8694 gfc_init_se (&argse
, se
);
8695 gfc_conv_expr_val (&argse
, e
);
8697 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
8698 gfc_add_block_to_block (&se
->post
, &argse
.post
);
8699 argarray
[arg
] = argse
.expr
;
8704 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
8705 and IEEE_UNORDERED, which translate directly to GCC type-generic
8709 conv_intrinsic_ieee_builtin (gfc_se
* se
, gfc_expr
* expr
,
8710 enum built_in_function code
, int nargs
)
8713 gcc_assert ((unsigned) nargs
<= sizeof(args
)/sizeof(args
[0]));
8715 conv_ieee_function_args (se
, expr
, args
, nargs
);
8716 se
->expr
= build_call_expr_loc_array (input_location
,
8717 builtin_decl_explicit (code
),
8719 STRIP_TYPE_NOPS (se
->expr
);
8720 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
8724 /* Generate code for IEEE_IS_NORMAL intrinsic:
8725 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
8728 conv_intrinsic_ieee_is_normal (gfc_se
* se
, gfc_expr
* expr
)
8730 tree arg
, isnormal
, iszero
;
8732 /* Convert arg, evaluate it only once. */
8733 conv_ieee_function_args (se
, expr
, &arg
, 1);
8734 arg
= gfc_evaluate_now (arg
, &se
->pre
);
8736 isnormal
= build_call_expr_loc (input_location
,
8737 builtin_decl_explicit (BUILT_IN_ISNORMAL
),
8739 iszero
= fold_build2_loc (input_location
, EQ_EXPR
, logical_type_node
, arg
,
8740 build_real_from_int_cst (TREE_TYPE (arg
),
8741 integer_zero_node
));
8742 se
->expr
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
8743 logical_type_node
, isnormal
, iszero
);
8744 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
8748 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
8749 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
8752 conv_intrinsic_ieee_is_negative (gfc_se
* se
, gfc_expr
* expr
)
8754 tree arg
, signbit
, isnan
;
8756 /* Convert arg, evaluate it only once. */
8757 conv_ieee_function_args (se
, expr
, &arg
, 1);
8758 arg
= gfc_evaluate_now (arg
, &se
->pre
);
8760 isnan
= build_call_expr_loc (input_location
,
8761 builtin_decl_explicit (BUILT_IN_ISNAN
),
8763 STRIP_TYPE_NOPS (isnan
);
8765 signbit
= build_call_expr_loc (input_location
,
8766 builtin_decl_explicit (BUILT_IN_SIGNBIT
),
8768 signbit
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
8769 signbit
, integer_zero_node
);
8771 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
8772 logical_type_node
, signbit
,
8773 fold_build1_loc (input_location
, TRUTH_NOT_EXPR
,
8774 TREE_TYPE(isnan
), isnan
));
8776 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
8780 /* Generate code for IEEE_LOGB and IEEE_RINT. */
8783 conv_intrinsic_ieee_logb_rint (gfc_se
* se
, gfc_expr
* expr
,
8784 enum built_in_function code
)
8786 tree arg
, decl
, call
, fpstate
;
8789 conv_ieee_function_args (se
, expr
, &arg
, 1);
8790 argprec
= TYPE_PRECISION (TREE_TYPE (arg
));
8791 decl
= builtin_decl_for_precision (code
, argprec
);
8793 /* Save floating-point state. */
8794 fpstate
= gfc_save_fp_state (&se
->pre
);
8796 /* Make the function call. */
8797 call
= build_call_expr_loc (input_location
, decl
, 1, arg
);
8798 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), call
);
8800 /* Restore floating-point state. */
8801 gfc_restore_fp_state (&se
->post
, fpstate
);
8805 /* Generate code for IEEE_REM. */
8808 conv_intrinsic_ieee_rem (gfc_se
* se
, gfc_expr
* expr
)
8810 tree args
[2], decl
, call
, fpstate
;
8813 conv_ieee_function_args (se
, expr
, args
, 2);
8815 /* If arguments have unequal size, convert them to the larger. */
8816 if (TYPE_PRECISION (TREE_TYPE (args
[0]))
8817 > TYPE_PRECISION (TREE_TYPE (args
[1])))
8818 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
8819 else if (TYPE_PRECISION (TREE_TYPE (args
[1]))
8820 > TYPE_PRECISION (TREE_TYPE (args
[0])))
8821 args
[0] = fold_convert (TREE_TYPE (args
[1]), args
[0]);
8823 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
8824 decl
= builtin_decl_for_precision (BUILT_IN_REMAINDER
, argprec
);
8826 /* Save floating-point state. */
8827 fpstate
= gfc_save_fp_state (&se
->pre
);
8829 /* Make the function call. */
8830 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
8831 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
8833 /* Restore floating-point state. */
8834 gfc_restore_fp_state (&se
->post
, fpstate
);
8838 /* Generate code for IEEE_NEXT_AFTER. */
8841 conv_intrinsic_ieee_next_after (gfc_se
* se
, gfc_expr
* expr
)
8843 tree args
[2], decl
, call
, fpstate
;
8846 conv_ieee_function_args (se
, expr
, args
, 2);
8848 /* Result has the characteristics of first argument. */
8849 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
8850 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
8851 decl
= builtin_decl_for_precision (BUILT_IN_NEXTAFTER
, argprec
);
8853 /* Save floating-point state. */
8854 fpstate
= gfc_save_fp_state (&se
->pre
);
8856 /* Make the function call. */
8857 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
8858 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
8860 /* Restore floating-point state. */
8861 gfc_restore_fp_state (&se
->post
, fpstate
);
8865 /* Generate code for IEEE_SCALB. */
8868 conv_intrinsic_ieee_scalb (gfc_se
* se
, gfc_expr
* expr
)
8870 tree args
[2], decl
, call
, huge
, type
;
8873 conv_ieee_function_args (se
, expr
, args
, 2);
8875 /* Result has the characteristics of first argument. */
8876 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
8877 decl
= builtin_decl_for_precision (BUILT_IN_SCALBN
, argprec
);
8879 if (TYPE_PRECISION (TREE_TYPE (args
[1])) > TYPE_PRECISION (integer_type_node
))
8881 /* We need to fold the integer into the range of a C int. */
8882 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
8883 type
= TREE_TYPE (args
[1]);
8885 n
= gfc_validate_kind (BT_INTEGER
, gfc_c_int_kind
, false);
8886 huge
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
,
8888 huge
= fold_convert (type
, huge
);
8889 args
[1] = fold_build2_loc (input_location
, MIN_EXPR
, type
, args
[1],
8891 args
[1] = fold_build2_loc (input_location
, MAX_EXPR
, type
, args
[1],
8892 fold_build1_loc (input_location
, NEGATE_EXPR
,
8896 args
[1] = fold_convert (integer_type_node
, args
[1]);
8898 /* Make the function call. */
8899 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
8900 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
8904 /* Generate code for IEEE_COPY_SIGN. */
8907 conv_intrinsic_ieee_copy_sign (gfc_se
* se
, gfc_expr
* expr
)
8909 tree args
[2], decl
, sign
;
8912 conv_ieee_function_args (se
, expr
, args
, 2);
8914 /* Get the sign of the second argument. */
8915 sign
= build_call_expr_loc (input_location
,
8916 builtin_decl_explicit (BUILT_IN_SIGNBIT
),
8918 sign
= fold_build2_loc (input_location
, NE_EXPR
, logical_type_node
,
8919 sign
, integer_zero_node
);
8921 /* Create a value of one, with the right sign. */
8922 sign
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
8924 fold_build1_loc (input_location
, NEGATE_EXPR
,
8928 args
[1] = fold_convert (TREE_TYPE (args
[0]), sign
);
8930 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
8931 decl
= builtin_decl_for_precision (BUILT_IN_COPYSIGN
, argprec
);
8933 se
->expr
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
8937 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
8941 gfc_conv_ieee_arithmetic_function (gfc_se
* se
, gfc_expr
* expr
)
8943 const char *name
= expr
->value
.function
.name
;
8945 #define STARTS_WITH(A,B) (strncmp((A), (B), strlen(B)) == 0)
8947 if (STARTS_WITH (name
, "_gfortran_ieee_is_nan"))
8948 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISNAN
, 1);
8949 else if (STARTS_WITH (name
, "_gfortran_ieee_is_finite"))
8950 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISFINITE
, 1);
8951 else if (STARTS_WITH (name
, "_gfortran_ieee_unordered"))
8952 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISUNORDERED
, 2);
8953 else if (STARTS_WITH (name
, "_gfortran_ieee_is_normal"))
8954 conv_intrinsic_ieee_is_normal (se
, expr
);
8955 else if (STARTS_WITH (name
, "_gfortran_ieee_is_negative"))
8956 conv_intrinsic_ieee_is_negative (se
, expr
);
8957 else if (STARTS_WITH (name
, "_gfortran_ieee_copy_sign"))
8958 conv_intrinsic_ieee_copy_sign (se
, expr
);
8959 else if (STARTS_WITH (name
, "_gfortran_ieee_scalb"))
8960 conv_intrinsic_ieee_scalb (se
, expr
);
8961 else if (STARTS_WITH (name
, "_gfortran_ieee_next_after"))
8962 conv_intrinsic_ieee_next_after (se
, expr
);
8963 else if (STARTS_WITH (name
, "_gfortran_ieee_rem"))
8964 conv_intrinsic_ieee_rem (se
, expr
);
8965 else if (STARTS_WITH (name
, "_gfortran_ieee_logb"))
8966 conv_intrinsic_ieee_logb_rint (se
, expr
, BUILT_IN_LOGB
);
8967 else if (STARTS_WITH (name
, "_gfortran_ieee_rint"))
8968 conv_intrinsic_ieee_logb_rint (se
, expr
, BUILT_IN_RINT
);
8970 /* It is not among the functions we translate directly. We return
8971 false, so a library function call is emitted. */
8980 /* Generate a direct call to malloc() for the MALLOC intrinsic. */
8983 gfc_conv_intrinsic_malloc (gfc_se
* se
, gfc_expr
* expr
)
8985 tree arg
, res
, restype
;
8987 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
8988 arg
= fold_convert (size_type_node
, arg
);
8989 res
= build_call_expr_loc (input_location
,
8990 builtin_decl_explicit (BUILT_IN_MALLOC
), 1, arg
);
8991 restype
= gfc_typenode_for_spec (&expr
->ts
);
8992 se
->expr
= fold_convert (restype
, res
);
8996 /* Generate code for an intrinsic function. Some map directly to library
8997 calls, others get special handling. In some cases the name of the function
8998 used depends on the type specifiers. */
9001 gfc_conv_intrinsic_function (gfc_se
* se
, gfc_expr
* expr
)
9007 name
= &expr
->value
.function
.name
[2];
9011 lib
= gfc_is_intrinsic_libcall (expr
);
9015 se
->ignore_optional
= 1;
9017 switch (expr
->value
.function
.isym
->id
)
9019 case GFC_ISYM_EOSHIFT
:
9021 case GFC_ISYM_RESHAPE
:
9022 /* For all of those the first argument specifies the type and the
9023 third is optional. */
9024 conv_generic_with_optional_char_arg (se
, expr
, 1, 3);
9027 case GFC_ISYM_MINLOC
:
9028 gfc_conv_intrinsic_minmaxloc (se
, expr
, LT_EXPR
);
9031 case GFC_ISYM_MAXLOC
:
9032 gfc_conv_intrinsic_minmaxloc (se
, expr
, GT_EXPR
);
9035 case GFC_ISYM_SHAPE
:
9036 gfc_conv_intrinsic_shape (se
, expr
);
9040 gfc_conv_intrinsic_funcall (se
, expr
);
9048 switch (expr
->value
.function
.isym
->id
)
9053 case GFC_ISYM_REPEAT
:
9054 gfc_conv_intrinsic_repeat (se
, expr
);
9058 gfc_conv_intrinsic_trim (se
, expr
);
9061 case GFC_ISYM_SC_KIND
:
9062 gfc_conv_intrinsic_sc_kind (se
, expr
);
9065 case GFC_ISYM_SI_KIND
:
9066 gfc_conv_intrinsic_si_kind (se
, expr
);
9069 case GFC_ISYM_SR_KIND
:
9070 gfc_conv_intrinsic_sr_kind (se
, expr
);
9073 case GFC_ISYM_EXPONENT
:
9074 gfc_conv_intrinsic_exponent (se
, expr
);
9078 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
9080 fndecl
= gfor_fndecl_string_scan
;
9082 fndecl
= gfor_fndecl_string_scan_char4
;
9086 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
9089 case GFC_ISYM_VERIFY
:
9090 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
9092 fndecl
= gfor_fndecl_string_verify
;
9094 fndecl
= gfor_fndecl_string_verify_char4
;
9098 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
9101 case GFC_ISYM_ALLOCATED
:
9102 gfc_conv_allocated (se
, expr
);
9105 case GFC_ISYM_ASSOCIATED
:
9106 gfc_conv_associated(se
, expr
);
9109 case GFC_ISYM_SAME_TYPE_AS
:
9110 gfc_conv_same_type_as (se
, expr
);
9114 gfc_conv_intrinsic_abs (se
, expr
);
9117 case GFC_ISYM_ADJUSTL
:
9118 if (expr
->ts
.kind
== 1)
9119 fndecl
= gfor_fndecl_adjustl
;
9120 else if (expr
->ts
.kind
== 4)
9121 fndecl
= gfor_fndecl_adjustl_char4
;
9125 gfc_conv_intrinsic_adjust (se
, expr
, fndecl
);
9128 case GFC_ISYM_ADJUSTR
:
9129 if (expr
->ts
.kind
== 1)
9130 fndecl
= gfor_fndecl_adjustr
;
9131 else if (expr
->ts
.kind
== 4)
9132 fndecl
= gfor_fndecl_adjustr_char4
;
9136 gfc_conv_intrinsic_adjust (se
, expr
, fndecl
);
9139 case GFC_ISYM_AIMAG
:
9140 gfc_conv_intrinsic_imagpart (se
, expr
);
9144 gfc_conv_intrinsic_aint (se
, expr
, RND_TRUNC
);
9148 gfc_conv_intrinsic_anyall (se
, expr
, EQ_EXPR
);
9151 case GFC_ISYM_ANINT
:
9152 gfc_conv_intrinsic_aint (se
, expr
, RND_ROUND
);
9156 gfc_conv_intrinsic_bitop (se
, expr
, BIT_AND_EXPR
);
9160 gfc_conv_intrinsic_anyall (se
, expr
, NE_EXPR
);
9163 case GFC_ISYM_BTEST
:
9164 gfc_conv_intrinsic_btest (se
, expr
);
9168 gfc_conv_intrinsic_bitcomp (se
, expr
, GE_EXPR
);
9172 gfc_conv_intrinsic_bitcomp (se
, expr
, GT_EXPR
);
9176 gfc_conv_intrinsic_bitcomp (se
, expr
, LE_EXPR
);
9180 gfc_conv_intrinsic_bitcomp (se
, expr
, LT_EXPR
);
9183 case GFC_ISYM_C_ASSOCIATED
:
9184 case GFC_ISYM_C_FUNLOC
:
9185 case GFC_ISYM_C_LOC
:
9186 conv_isocbinding_function (se
, expr
);
9189 case GFC_ISYM_ACHAR
:
9191 gfc_conv_intrinsic_char (se
, expr
);
9194 case GFC_ISYM_CONVERSION
:
9196 case GFC_ISYM_LOGICAL
:
9198 gfc_conv_intrinsic_conversion (se
, expr
);
9201 /* Integer conversions are handled separately to make sure we get the
9202 correct rounding mode. */
9207 gfc_conv_intrinsic_int (se
, expr
, RND_TRUNC
);
9211 gfc_conv_intrinsic_int (se
, expr
, RND_ROUND
);
9214 case GFC_ISYM_CEILING
:
9215 gfc_conv_intrinsic_int (se
, expr
, RND_CEIL
);
9218 case GFC_ISYM_FLOOR
:
9219 gfc_conv_intrinsic_int (se
, expr
, RND_FLOOR
);
9223 gfc_conv_intrinsic_mod (se
, expr
, 0);
9226 case GFC_ISYM_MODULO
:
9227 gfc_conv_intrinsic_mod (se
, expr
, 1);
9230 case GFC_ISYM_CAF_GET
:
9231 gfc_conv_intrinsic_caf_get (se
, expr
, NULL_TREE
, NULL_TREE
, NULL_TREE
,
9235 case GFC_ISYM_CMPLX
:
9236 gfc_conv_intrinsic_cmplx (se
, expr
, name
[5] == '1');
9239 case GFC_ISYM_COMMAND_ARGUMENT_COUNT
:
9240 gfc_conv_intrinsic_iargc (se
, expr
);
9243 case GFC_ISYM_COMPLEX
:
9244 gfc_conv_intrinsic_cmplx (se
, expr
, 1);
9247 case GFC_ISYM_CONJG
:
9248 gfc_conv_intrinsic_conjg (se
, expr
);
9251 case GFC_ISYM_COUNT
:
9252 gfc_conv_intrinsic_count (se
, expr
);
9255 case GFC_ISYM_CTIME
:
9256 gfc_conv_intrinsic_ctime (se
, expr
);
9260 gfc_conv_intrinsic_dim (se
, expr
);
9263 case GFC_ISYM_DOT_PRODUCT
:
9264 gfc_conv_intrinsic_dot_product (se
, expr
);
9267 case GFC_ISYM_DPROD
:
9268 gfc_conv_intrinsic_dprod (se
, expr
);
9271 case GFC_ISYM_DSHIFTL
:
9272 gfc_conv_intrinsic_dshift (se
, expr
, true);
9275 case GFC_ISYM_DSHIFTR
:
9276 gfc_conv_intrinsic_dshift (se
, expr
, false);
9279 case GFC_ISYM_FDATE
:
9280 gfc_conv_intrinsic_fdate (se
, expr
);
9283 case GFC_ISYM_FRACTION
:
9284 gfc_conv_intrinsic_fraction (se
, expr
);
9288 gfc_conv_intrinsic_arith (se
, expr
, BIT_AND_EXPR
, false);
9292 gfc_conv_intrinsic_bitop (se
, expr
, BIT_AND_EXPR
);
9296 gfc_conv_intrinsic_arith (se
, expr
, BIT_IOR_EXPR
, false);
9299 case GFC_ISYM_IBCLR
:
9300 gfc_conv_intrinsic_singlebitop (se
, expr
, 0);
9303 case GFC_ISYM_IBITS
:
9304 gfc_conv_intrinsic_ibits (se
, expr
);
9307 case GFC_ISYM_IBSET
:
9308 gfc_conv_intrinsic_singlebitop (se
, expr
, 1);
9311 case GFC_ISYM_IACHAR
:
9312 case GFC_ISYM_ICHAR
:
9313 /* We assume ASCII character sequence. */
9314 gfc_conv_intrinsic_ichar (se
, expr
);
9317 case GFC_ISYM_IARGC
:
9318 gfc_conv_intrinsic_iargc (se
, expr
);
9322 gfc_conv_intrinsic_bitop (se
, expr
, BIT_XOR_EXPR
);
9325 case GFC_ISYM_INDEX
:
9326 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
9328 fndecl
= gfor_fndecl_string_index
;
9330 fndecl
= gfor_fndecl_string_index_char4
;
9334 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
9338 gfc_conv_intrinsic_bitop (se
, expr
, BIT_IOR_EXPR
);
9341 case GFC_ISYM_IPARITY
:
9342 gfc_conv_intrinsic_arith (se
, expr
, BIT_XOR_EXPR
, false);
9345 case GFC_ISYM_IS_IOSTAT_END
:
9346 gfc_conv_has_intvalue (se
, expr
, LIBERROR_END
);
9349 case GFC_ISYM_IS_IOSTAT_EOR
:
9350 gfc_conv_has_intvalue (se
, expr
, LIBERROR_EOR
);
9353 case GFC_ISYM_ISNAN
:
9354 gfc_conv_intrinsic_isnan (se
, expr
);
9358 conv_intrinsic_kill (se
, expr
);
9361 case GFC_ISYM_LSHIFT
:
9362 gfc_conv_intrinsic_shift (se
, expr
, false, false);
9365 case GFC_ISYM_RSHIFT
:
9366 gfc_conv_intrinsic_shift (se
, expr
, true, true);
9369 case GFC_ISYM_SHIFTA
:
9370 gfc_conv_intrinsic_shift (se
, expr
, true, true);
9373 case GFC_ISYM_SHIFTL
:
9374 gfc_conv_intrinsic_shift (se
, expr
, false, false);
9377 case GFC_ISYM_SHIFTR
:
9378 gfc_conv_intrinsic_shift (se
, expr
, true, false);
9381 case GFC_ISYM_ISHFT
:
9382 gfc_conv_intrinsic_ishft (se
, expr
);
9385 case GFC_ISYM_ISHFTC
:
9386 gfc_conv_intrinsic_ishftc (se
, expr
);
9389 case GFC_ISYM_LEADZ
:
9390 gfc_conv_intrinsic_leadz (se
, expr
);
9393 case GFC_ISYM_TRAILZ
:
9394 gfc_conv_intrinsic_trailz (se
, expr
);
9397 case GFC_ISYM_POPCNT
:
9398 gfc_conv_intrinsic_popcnt_poppar (se
, expr
, 0);
9401 case GFC_ISYM_POPPAR
:
9402 gfc_conv_intrinsic_popcnt_poppar (se
, expr
, 1);
9405 case GFC_ISYM_LBOUND
:
9406 gfc_conv_intrinsic_bound (se
, expr
, 0);
9409 case GFC_ISYM_LCOBOUND
:
9410 conv_intrinsic_cobound (se
, expr
);
9413 case GFC_ISYM_TRANSPOSE
:
9414 /* The scalarizer has already been set up for reversed dimension access
9415 order ; now we just get the argument value normally. */
9416 gfc_conv_expr (se
, expr
->value
.function
.actual
->expr
);
9420 gfc_conv_intrinsic_len (se
, expr
);
9423 case GFC_ISYM_LEN_TRIM
:
9424 gfc_conv_intrinsic_len_trim (se
, expr
);
9428 gfc_conv_intrinsic_strcmp (se
, expr
, GE_EXPR
);
9432 gfc_conv_intrinsic_strcmp (se
, expr
, GT_EXPR
);
9436 gfc_conv_intrinsic_strcmp (se
, expr
, LE_EXPR
);
9440 gfc_conv_intrinsic_strcmp (se
, expr
, LT_EXPR
);
9443 case GFC_ISYM_MALLOC
:
9444 gfc_conv_intrinsic_malloc (se
, expr
);
9447 case GFC_ISYM_MASKL
:
9448 gfc_conv_intrinsic_mask (se
, expr
, 1);
9451 case GFC_ISYM_MASKR
:
9452 gfc_conv_intrinsic_mask (se
, expr
, 0);
9456 if (expr
->ts
.type
== BT_CHARACTER
)
9457 gfc_conv_intrinsic_minmax_char (se
, expr
, 1);
9459 gfc_conv_intrinsic_minmax (se
, expr
, GT_EXPR
);
9462 case GFC_ISYM_MAXLOC
:
9463 gfc_conv_intrinsic_minmaxloc (se
, expr
, GT_EXPR
);
9466 case GFC_ISYM_MAXVAL
:
9467 gfc_conv_intrinsic_minmaxval (se
, expr
, GT_EXPR
);
9470 case GFC_ISYM_MERGE
:
9471 gfc_conv_intrinsic_merge (se
, expr
);
9474 case GFC_ISYM_MERGE_BITS
:
9475 gfc_conv_intrinsic_merge_bits (se
, expr
);
9479 if (expr
->ts
.type
== BT_CHARACTER
)
9480 gfc_conv_intrinsic_minmax_char (se
, expr
, -1);
9482 gfc_conv_intrinsic_minmax (se
, expr
, LT_EXPR
);
9485 case GFC_ISYM_MINLOC
:
9486 gfc_conv_intrinsic_minmaxloc (se
, expr
, LT_EXPR
);
9489 case GFC_ISYM_MINVAL
:
9490 gfc_conv_intrinsic_minmaxval (se
, expr
, LT_EXPR
);
9493 case GFC_ISYM_NEAREST
:
9494 gfc_conv_intrinsic_nearest (se
, expr
);
9497 case GFC_ISYM_NORM2
:
9498 gfc_conv_intrinsic_arith (se
, expr
, PLUS_EXPR
, true);
9502 gfc_conv_intrinsic_not (se
, expr
);
9506 gfc_conv_intrinsic_bitop (se
, expr
, BIT_IOR_EXPR
);
9509 case GFC_ISYM_PARITY
:
9510 gfc_conv_intrinsic_arith (se
, expr
, NE_EXPR
, false);
9513 case GFC_ISYM_PRESENT
:
9514 gfc_conv_intrinsic_present (se
, expr
);
9517 case GFC_ISYM_PRODUCT
:
9518 gfc_conv_intrinsic_arith (se
, expr
, MULT_EXPR
, false);
9522 gfc_conv_intrinsic_rank (se
, expr
);
9525 case GFC_ISYM_RRSPACING
:
9526 gfc_conv_intrinsic_rrspacing (se
, expr
);
9529 case GFC_ISYM_SET_EXPONENT
:
9530 gfc_conv_intrinsic_set_exponent (se
, expr
);
9533 case GFC_ISYM_SCALE
:
9534 gfc_conv_intrinsic_scale (se
, expr
);
9538 gfc_conv_intrinsic_sign (se
, expr
);
9542 gfc_conv_intrinsic_size (se
, expr
);
9545 case GFC_ISYM_SIZEOF
:
9546 case GFC_ISYM_C_SIZEOF
:
9547 gfc_conv_intrinsic_sizeof (se
, expr
);
9550 case GFC_ISYM_STORAGE_SIZE
:
9551 gfc_conv_intrinsic_storage_size (se
, expr
);
9554 case GFC_ISYM_SPACING
:
9555 gfc_conv_intrinsic_spacing (se
, expr
);
9558 case GFC_ISYM_STRIDE
:
9559 conv_intrinsic_stride (se
, expr
);
9563 gfc_conv_intrinsic_arith (se
, expr
, PLUS_EXPR
, false);
9566 case GFC_ISYM_TEAM_NUMBER
:
9567 conv_intrinsic_team_number (se
, expr
);
9570 case GFC_ISYM_TRANSFER
:
9571 if (se
->ss
&& se
->ss
->info
->useflags
)
9572 /* Access the previously obtained result. */
9573 gfc_conv_tmp_array_ref (se
);
9575 gfc_conv_intrinsic_transfer (se
, expr
);
9578 case GFC_ISYM_TTYNAM
:
9579 gfc_conv_intrinsic_ttynam (se
, expr
);
9582 case GFC_ISYM_UBOUND
:
9583 gfc_conv_intrinsic_bound (se
, expr
, 1);
9586 case GFC_ISYM_UCOBOUND
:
9587 conv_intrinsic_cobound (se
, expr
);
9591 gfc_conv_intrinsic_bitop (se
, expr
, BIT_XOR_EXPR
);
9595 gfc_conv_intrinsic_loc (se
, expr
);
9598 case GFC_ISYM_THIS_IMAGE
:
9599 /* For num_images() == 1, handle as LCOBOUND. */
9600 if (expr
->value
.function
.actual
->expr
9601 && flag_coarray
== GFC_FCOARRAY_SINGLE
)
9602 conv_intrinsic_cobound (se
, expr
);
9604 trans_this_image (se
, expr
);
9607 case GFC_ISYM_IMAGE_INDEX
:
9608 trans_image_index (se
, expr
);
9611 case GFC_ISYM_IMAGE_STATUS
:
9612 conv_intrinsic_image_status (se
, expr
);
9615 case GFC_ISYM_NUM_IMAGES
:
9616 trans_num_images (se
, expr
);
9619 case GFC_ISYM_ACCESS
:
9620 case GFC_ISYM_CHDIR
:
9621 case GFC_ISYM_CHMOD
:
9622 case GFC_ISYM_DTIME
:
9623 case GFC_ISYM_ETIME
:
9624 case GFC_ISYM_EXTENDS_TYPE_OF
:
9626 case GFC_ISYM_FGETC
:
9629 case GFC_ISYM_FPUTC
:
9630 case GFC_ISYM_FSTAT
:
9631 case GFC_ISYM_FTELL
:
9632 case GFC_ISYM_GETCWD
:
9633 case GFC_ISYM_GETGID
:
9634 case GFC_ISYM_GETPID
:
9635 case GFC_ISYM_GETUID
:
9636 case GFC_ISYM_HOSTNM
:
9637 case GFC_ISYM_IERRNO
:
9638 case GFC_ISYM_IRAND
:
9639 case GFC_ISYM_ISATTY
:
9642 case GFC_ISYM_LSTAT
:
9643 case GFC_ISYM_MATMUL
:
9644 case GFC_ISYM_MCLOCK
:
9645 case GFC_ISYM_MCLOCK8
:
9647 case GFC_ISYM_RENAME
:
9648 case GFC_ISYM_SECOND
:
9649 case GFC_ISYM_SECNDS
:
9650 case GFC_ISYM_SIGNAL
:
9652 case GFC_ISYM_SYMLNK
:
9653 case GFC_ISYM_SYSTEM
:
9655 case GFC_ISYM_TIME8
:
9656 case GFC_ISYM_UMASK
:
9657 case GFC_ISYM_UNLINK
:
9659 gfc_conv_intrinsic_funcall (se
, expr
);
9662 case GFC_ISYM_EOSHIFT
:
9664 case GFC_ISYM_RESHAPE
:
9665 /* For those, expr->rank should always be >0 and thus the if above the
9666 switch should have matched. */
9671 gfc_conv_intrinsic_lib_function (se
, expr
);
9678 walk_inline_intrinsic_transpose (gfc_ss
*ss
, gfc_expr
*expr
)
9680 gfc_ss
*arg_ss
, *tmp_ss
;
9681 gfc_actual_arglist
*arg
;
9683 arg
= expr
->value
.function
.actual
;
9685 gcc_assert (arg
->expr
);
9687 arg_ss
= gfc_walk_subexpr (gfc_ss_terminator
, arg
->expr
);
9688 gcc_assert (arg_ss
!= gfc_ss_terminator
);
9690 for (tmp_ss
= arg_ss
; ; tmp_ss
= tmp_ss
->next
)
9692 if (tmp_ss
->info
->type
!= GFC_SS_SCALAR
9693 && tmp_ss
->info
->type
!= GFC_SS_REFERENCE
)
9695 gcc_assert (tmp_ss
->dimen
== 2);
9697 /* We just invert dimensions. */
9698 std::swap (tmp_ss
->dim
[0], tmp_ss
->dim
[1]);
9701 /* Stop when tmp_ss points to the last valid element of the chain... */
9702 if (tmp_ss
->next
== gfc_ss_terminator
)
9706 /* ... so that we can attach the rest of the chain to it. */
9713 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
9714 This has the side effect of reversing the nested list, so there is no
9715 need to call gfc_reverse_ss on it (the given list is assumed not to be
9719 nest_loop_dimension (gfc_ss
*ss
, int dim
)
9722 gfc_ss
*new_ss
, *prev_ss
= gfc_ss_terminator
;
9723 gfc_loopinfo
*new_loop
;
9725 gcc_assert (ss
!= gfc_ss_terminator
);
9727 for (; ss
!= gfc_ss_terminator
; ss
= ss
->next
)
9729 new_ss
= gfc_get_ss ();
9730 new_ss
->next
= prev_ss
;
9731 new_ss
->parent
= ss
;
9732 new_ss
->info
= ss
->info
;
9733 new_ss
->info
->refcount
++;
9736 gcc_assert (ss
->info
->type
!= GFC_SS_SCALAR
9737 && ss
->info
->type
!= GFC_SS_REFERENCE
);
9740 new_ss
->dim
[0] = ss
->dim
[dim
];
9742 gcc_assert (dim
< ss
->dimen
);
9744 ss_dim
= --ss
->dimen
;
9745 for (i
= dim
; i
< ss_dim
; i
++)
9746 ss
->dim
[i
] = ss
->dim
[i
+ 1];
9748 ss
->dim
[ss_dim
] = 0;
9754 ss
->nested_ss
->parent
= new_ss
;
9755 new_ss
->nested_ss
= ss
->nested_ss
;
9757 ss
->nested_ss
= new_ss
;
9760 new_loop
= gfc_get_loopinfo ();
9761 gfc_init_loopinfo (new_loop
);
9763 gcc_assert (prev_ss
!= NULL
);
9764 gcc_assert (prev_ss
!= gfc_ss_terminator
);
9765 gfc_add_ss_to_loop (new_loop
, prev_ss
);
9766 return new_ss
->parent
;
9770 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
9771 is to be inlined. */
9774 walk_inline_intrinsic_arith (gfc_ss
*ss
, gfc_expr
*expr
)
9776 gfc_ss
*tmp_ss
, *tail
, *array_ss
;
9777 gfc_actual_arglist
*arg1
, *arg2
, *arg3
;
9779 bool scalar_mask
= false;
9781 /* The rank of the result will be determined later. */
9782 arg1
= expr
->value
.function
.actual
;
9785 gcc_assert (arg3
!= NULL
);
9787 if (expr
->rank
== 0)
9790 tmp_ss
= gfc_ss_terminator
;
9796 mask_ss
= gfc_walk_subexpr (tmp_ss
, arg3
->expr
);
9797 if (mask_ss
== tmp_ss
)
9803 array_ss
= gfc_walk_subexpr (tmp_ss
, arg1
->expr
);
9804 gcc_assert (array_ss
!= tmp_ss
);
9806 /* Odd thing: If the mask is scalar, it is used by the frontend after
9807 the array (to make an if around the nested loop). Thus it shall
9808 be after array_ss once the gfc_ss list is reversed. */
9810 tmp_ss
= gfc_get_scalar_ss (array_ss
, arg3
->expr
);
9814 /* "Hide" the dimension on which we will sum in the first arg's scalarization
9816 sum_dim
= mpz_get_si (arg2
->expr
->value
.integer
) - 1;
9817 tail
= nest_loop_dimension (tmp_ss
, sum_dim
);
9825 walk_inline_intrinsic_function (gfc_ss
* ss
, gfc_expr
* expr
)
9828 switch (expr
->value
.function
.isym
->id
)
9830 case GFC_ISYM_PRODUCT
:
9832 return walk_inline_intrinsic_arith (ss
, expr
);
9834 case GFC_ISYM_TRANSPOSE
:
9835 return walk_inline_intrinsic_transpose (ss
, expr
);
9844 /* This generates code to execute before entering the scalarization loop.
9845 Currently does nothing. */
9848 gfc_add_intrinsic_ss_code (gfc_loopinfo
* loop ATTRIBUTE_UNUSED
, gfc_ss
* ss
)
9850 switch (ss
->info
->expr
->value
.function
.isym
->id
)
9852 case GFC_ISYM_UBOUND
:
9853 case GFC_ISYM_LBOUND
:
9854 case GFC_ISYM_UCOBOUND
:
9855 case GFC_ISYM_LCOBOUND
:
9856 case GFC_ISYM_THIS_IMAGE
:
9865 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
9866 are expanded into code inside the scalarization loop. */
9869 gfc_walk_intrinsic_bound (gfc_ss
* ss
, gfc_expr
* expr
)
9871 if (expr
->value
.function
.actual
->expr
->ts
.type
== BT_CLASS
)
9872 gfc_add_class_array_ref (expr
->value
.function
.actual
->expr
);
9874 /* The two argument version returns a scalar. */
9875 if (expr
->value
.function
.actual
->next
->expr
)
9878 return gfc_get_array_ss (ss
, expr
, 1, GFC_SS_INTRINSIC
);
9882 /* Walk an intrinsic array libcall. */
9885 gfc_walk_intrinsic_libfunc (gfc_ss
* ss
, gfc_expr
* expr
)
9887 gcc_assert (expr
->rank
> 0);
9888 return gfc_get_array_ss (ss
, expr
, expr
->rank
, GFC_SS_FUNCTION
);
9892 /* Return whether the function call expression EXPR will be expanded
9893 inline by gfc_conv_intrinsic_function. */
9896 gfc_inline_intrinsic_function_p (gfc_expr
*expr
)
9898 gfc_actual_arglist
*args
;
9900 if (!expr
->value
.function
.isym
)
9903 switch (expr
->value
.function
.isym
->id
)
9905 case GFC_ISYM_PRODUCT
:
9907 /* Disable inline expansion if code size matters. */
9911 args
= expr
->value
.function
.actual
;
9912 /* We need to be able to subset the SUM argument at compile-time. */
9913 if (args
->next
->expr
&& args
->next
->expr
->expr_type
!= EXPR_CONSTANT
)
9918 case GFC_ISYM_TRANSPOSE
:
9927 /* Returns nonzero if the specified intrinsic function call maps directly to
9928 an external library call. Should only be used for functions that return
9932 gfc_is_intrinsic_libcall (gfc_expr
* expr
)
9934 gcc_assert (expr
->expr_type
== EXPR_FUNCTION
&& expr
->value
.function
.isym
);
9935 gcc_assert (expr
->rank
> 0);
9937 if (gfc_inline_intrinsic_function_p (expr
))
9940 switch (expr
->value
.function
.isym
->id
)
9944 case GFC_ISYM_COUNT
:
9948 case GFC_ISYM_IPARITY
:
9949 case GFC_ISYM_MATMUL
:
9950 case GFC_ISYM_MAXLOC
:
9951 case GFC_ISYM_MAXVAL
:
9952 case GFC_ISYM_MINLOC
:
9953 case GFC_ISYM_MINVAL
:
9954 case GFC_ISYM_NORM2
:
9955 case GFC_ISYM_PARITY
:
9956 case GFC_ISYM_PRODUCT
:
9958 case GFC_ISYM_SHAPE
:
9959 case GFC_ISYM_SPREAD
:
9961 /* Ignore absent optional parameters. */
9964 case GFC_ISYM_CSHIFT
:
9965 case GFC_ISYM_EOSHIFT
:
9966 case GFC_ISYM_GET_TEAM
:
9967 case GFC_ISYM_FAILED_IMAGES
:
9968 case GFC_ISYM_STOPPED_IMAGES
:
9970 case GFC_ISYM_RESHAPE
:
9971 case GFC_ISYM_UNPACK
:
9972 /* Pass absent optional parameters. */
9980 /* Walk an intrinsic function. */
9982 gfc_walk_intrinsic_function (gfc_ss
* ss
, gfc_expr
* expr
,
9983 gfc_intrinsic_sym
* isym
)
9987 if (isym
->elemental
)
9988 return gfc_walk_elemental_function_args (ss
, expr
->value
.function
.actual
,
9989 NULL
, GFC_SS_SCALAR
);
9991 if (expr
->rank
== 0)
9994 if (gfc_inline_intrinsic_function_p (expr
))
9995 return walk_inline_intrinsic_function (ss
, expr
);
9997 if (gfc_is_intrinsic_libcall (expr
))
9998 return gfc_walk_intrinsic_libfunc (ss
, expr
);
10000 /* Special cases. */
10003 case GFC_ISYM_LBOUND
:
10004 case GFC_ISYM_LCOBOUND
:
10005 case GFC_ISYM_UBOUND
:
10006 case GFC_ISYM_UCOBOUND
:
10007 case GFC_ISYM_THIS_IMAGE
:
10008 return gfc_walk_intrinsic_bound (ss
, expr
);
10010 case GFC_ISYM_TRANSFER
:
10011 case GFC_ISYM_CAF_GET
:
10012 return gfc_walk_intrinsic_libfunc (ss
, expr
);
10015 /* This probably meant someone forgot to add an intrinsic to the above
10016 list(s) when they implemented it, or something's gone horribly
10018 gcc_unreachable ();
10024 conv_co_collective (gfc_code
*code
)
10027 stmtblock_t block
, post_block
;
10028 tree fndecl
, array
, strlen
, image_index
, stat
, errmsg
, errmsg_len
;
10029 gfc_expr
*image_idx_expr
, *stat_expr
, *errmsg_expr
, *opr_expr
;
10031 gfc_start_block (&block
);
10032 gfc_init_block (&post_block
);
10034 if (code
->resolved_isym
->id
== GFC_ISYM_CO_REDUCE
)
10036 opr_expr
= code
->ext
.actual
->next
->expr
;
10037 image_idx_expr
= code
->ext
.actual
->next
->next
->expr
;
10038 stat_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
10039 errmsg_expr
= code
->ext
.actual
->next
->next
->next
->next
->expr
;
10044 image_idx_expr
= code
->ext
.actual
->next
->expr
;
10045 stat_expr
= code
->ext
.actual
->next
->next
->expr
;
10046 errmsg_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
10052 gfc_init_se (&argse
, NULL
);
10053 gfc_conv_expr (&argse
, stat_expr
);
10054 gfc_add_block_to_block (&block
, &argse
.pre
);
10055 gfc_add_block_to_block (&post_block
, &argse
.post
);
10057 if (flag_coarray
!= GFC_FCOARRAY_SINGLE
)
10058 stat
= gfc_build_addr_expr (NULL_TREE
, stat
);
10060 else if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
10063 stat
= null_pointer_node
;
10065 /* Early exit for GFC_FCOARRAY_SINGLE. */
10066 if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
10068 if (stat
!= NULL_TREE
)
10069 gfc_add_modify (&block
, stat
,
10070 fold_convert (TREE_TYPE (stat
), integer_zero_node
));
10071 return gfc_finish_block (&block
);
10074 /* Handle the array. */
10075 gfc_init_se (&argse
, NULL
);
10076 if (code
->ext
.actual
->expr
->rank
== 0)
10078 symbol_attribute attr
;
10079 gfc_clear_attr (&attr
);
10080 gfc_init_se (&argse
, NULL
);
10081 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
10082 gfc_add_block_to_block (&block
, &argse
.pre
);
10083 gfc_add_block_to_block (&post_block
, &argse
.post
);
10084 array
= gfc_conv_scalar_to_descriptor (&argse
, argse
.expr
, attr
);
10085 array
= gfc_build_addr_expr (NULL_TREE
, array
);
10089 argse
.want_pointer
= 1;
10090 gfc_conv_expr_descriptor (&argse
, code
->ext
.actual
->expr
);
10091 array
= argse
.expr
;
10093 gfc_add_block_to_block (&block
, &argse
.pre
);
10094 gfc_add_block_to_block (&post_block
, &argse
.post
);
10096 if (code
->ext
.actual
->expr
->ts
.type
== BT_CHARACTER
)
10097 strlen
= argse
.string_length
;
10099 strlen
= integer_zero_node
;
10102 if (image_idx_expr
)
10104 gfc_init_se (&argse
, NULL
);
10105 gfc_conv_expr (&argse
, image_idx_expr
);
10106 gfc_add_block_to_block (&block
, &argse
.pre
);
10107 gfc_add_block_to_block (&post_block
, &argse
.post
);
10108 image_index
= fold_convert (integer_type_node
, argse
.expr
);
10111 image_index
= integer_zero_node
;
10116 gfc_init_se (&argse
, NULL
);
10117 gfc_conv_expr (&argse
, errmsg_expr
);
10118 gfc_add_block_to_block (&block
, &argse
.pre
);
10119 gfc_add_block_to_block (&post_block
, &argse
.post
);
10120 errmsg
= argse
.expr
;
10121 errmsg_len
= fold_convert (size_type_node
, argse
.string_length
);
10125 errmsg
= null_pointer_node
;
10126 errmsg_len
= build_zero_cst (size_type_node
);
10129 /* Generate the function call. */
10130 switch (code
->resolved_isym
->id
)
10132 case GFC_ISYM_CO_BROADCAST
:
10133 fndecl
= gfor_fndecl_co_broadcast
;
10135 case GFC_ISYM_CO_MAX
:
10136 fndecl
= gfor_fndecl_co_max
;
10138 case GFC_ISYM_CO_MIN
:
10139 fndecl
= gfor_fndecl_co_min
;
10141 case GFC_ISYM_CO_REDUCE
:
10142 fndecl
= gfor_fndecl_co_reduce
;
10144 case GFC_ISYM_CO_SUM
:
10145 fndecl
= gfor_fndecl_co_sum
;
10148 gcc_unreachable ();
10151 if (code
->resolved_isym
->id
== GFC_ISYM_CO_SUM
10152 || code
->resolved_isym
->id
== GFC_ISYM_CO_BROADCAST
)
10153 fndecl
= build_call_expr_loc (input_location
, fndecl
, 5, array
,
10154 image_index
, stat
, errmsg
, errmsg_len
);
10155 else if (code
->resolved_isym
->id
!= GFC_ISYM_CO_REDUCE
)
10156 fndecl
= build_call_expr_loc (input_location
, fndecl
, 6, array
, image_index
,
10157 stat
, errmsg
, strlen
, errmsg_len
);
10160 tree opr
, opr_flags
;
10162 // FIXME: Handle TS29113's bind(C) strings with descriptor.
10164 if (gfc_is_proc_ptr_comp (opr_expr
))
10166 gfc_symbol
*sym
= gfc_get_proc_ptr_comp (opr_expr
)->ts
.interface
;
10167 opr_flag_int
= sym
->attr
.dimension
10168 || (sym
->ts
.type
== BT_CHARACTER
10169 && !sym
->attr
.is_bind_c
)
10170 ? GFC_CAF_BYREF
: 0;
10171 opr_flag_int
|= opr_expr
->ts
.type
== BT_CHARACTER
10172 && !sym
->attr
.is_bind_c
10173 ? GFC_CAF_HIDDENLEN
: 0;
10174 opr_flag_int
|= sym
->formal
->sym
->attr
.value
? GFC_CAF_ARG_VALUE
: 0;
10178 opr_flag_int
= gfc_return_by_reference (opr_expr
->symtree
->n
.sym
)
10179 ? GFC_CAF_BYREF
: 0;
10180 opr_flag_int
|= opr_expr
->ts
.type
== BT_CHARACTER
10181 && !opr_expr
->symtree
->n
.sym
->attr
.is_bind_c
10182 ? GFC_CAF_HIDDENLEN
: 0;
10183 opr_flag_int
|= opr_expr
->symtree
->n
.sym
->formal
->sym
->attr
.value
10184 ? GFC_CAF_ARG_VALUE
: 0;
10186 opr_flags
= build_int_cst (integer_type_node
, opr_flag_int
);
10187 gfc_conv_expr (&argse
, opr_expr
);
10189 fndecl
= build_call_expr_loc (input_location
, fndecl
, 8, array
, opr
, opr_flags
,
10190 image_index
, stat
, errmsg
, strlen
, errmsg_len
);
10193 gfc_add_expr_to_block (&block
, fndecl
);
10194 gfc_add_block_to_block (&block
, &post_block
);
10196 return gfc_finish_block (&block
);
10201 conv_intrinsic_atomic_op (gfc_code
*code
)
10204 tree tmp
, atom
, value
, old
= NULL_TREE
, stat
= NULL_TREE
;
10205 stmtblock_t block
, post_block
;
10206 gfc_expr
*atom_expr
= code
->ext
.actual
->expr
;
10207 gfc_expr
*stat_expr
;
10208 built_in_function fn
;
10210 if (atom_expr
->expr_type
== EXPR_FUNCTION
10211 && atom_expr
->value
.function
.isym
10212 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
10213 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
10215 gfc_start_block (&block
);
10216 gfc_init_block (&post_block
);
10218 gfc_init_se (&argse
, NULL
);
10219 argse
.want_pointer
= 1;
10220 gfc_conv_expr (&argse
, atom_expr
);
10221 gfc_add_block_to_block (&block
, &argse
.pre
);
10222 gfc_add_block_to_block (&post_block
, &argse
.post
);
10225 gfc_init_se (&argse
, NULL
);
10226 if (flag_coarray
== GFC_FCOARRAY_LIB
10227 && code
->ext
.actual
->next
->expr
->ts
.kind
== atom_expr
->ts
.kind
)
10228 argse
.want_pointer
= 1;
10229 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->expr
);
10230 gfc_add_block_to_block (&block
, &argse
.pre
);
10231 gfc_add_block_to_block (&post_block
, &argse
.post
);
10232 value
= argse
.expr
;
10234 switch (code
->resolved_isym
->id
)
10236 case GFC_ISYM_ATOMIC_ADD
:
10237 case GFC_ISYM_ATOMIC_AND
:
10238 case GFC_ISYM_ATOMIC_DEF
:
10239 case GFC_ISYM_ATOMIC_OR
:
10240 case GFC_ISYM_ATOMIC_XOR
:
10241 stat_expr
= code
->ext
.actual
->next
->next
->expr
;
10242 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10243 old
= null_pointer_node
;
10246 gfc_init_se (&argse
, NULL
);
10247 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10248 argse
.want_pointer
= 1;
10249 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->expr
);
10250 gfc_add_block_to_block (&block
, &argse
.pre
);
10251 gfc_add_block_to_block (&post_block
, &argse
.post
);
10253 stat_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
10257 if (stat_expr
!= NULL
)
10259 gcc_assert (stat_expr
->expr_type
== EXPR_VARIABLE
);
10260 gfc_init_se (&argse
, NULL
);
10261 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10262 argse
.want_pointer
= 1;
10263 gfc_conv_expr_val (&argse
, stat_expr
);
10264 gfc_add_block_to_block (&block
, &argse
.pre
);
10265 gfc_add_block_to_block (&post_block
, &argse
.post
);
10268 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
10269 stat
= null_pointer_node
;
10271 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10273 tree image_index
, caf_decl
, offset
, token
;
10276 switch (code
->resolved_isym
->id
)
10278 case GFC_ISYM_ATOMIC_ADD
:
10279 case GFC_ISYM_ATOMIC_FETCH_ADD
:
10280 op
= (int) GFC_CAF_ATOMIC_ADD
;
10282 case GFC_ISYM_ATOMIC_AND
:
10283 case GFC_ISYM_ATOMIC_FETCH_AND
:
10284 op
= (int) GFC_CAF_ATOMIC_AND
;
10286 case GFC_ISYM_ATOMIC_OR
:
10287 case GFC_ISYM_ATOMIC_FETCH_OR
:
10288 op
= (int) GFC_CAF_ATOMIC_OR
;
10290 case GFC_ISYM_ATOMIC_XOR
:
10291 case GFC_ISYM_ATOMIC_FETCH_XOR
:
10292 op
= (int) GFC_CAF_ATOMIC_XOR
;
10294 case GFC_ISYM_ATOMIC_DEF
:
10295 op
= 0; /* Unused. */
10298 gcc_unreachable ();
10301 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
10302 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
10303 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
10305 if (gfc_is_coindexed (atom_expr
))
10306 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
10308 image_index
= integer_zero_node
;
10310 if (!POINTER_TYPE_P (TREE_TYPE (value
)))
10312 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (atom
)), "value");
10313 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), value
));
10314 value
= gfc_build_addr_expr (NULL_TREE
, tmp
);
10317 gfc_init_se (&argse
, NULL
);
10318 gfc_get_caf_token_offset (&argse
, &token
, &offset
, caf_decl
, atom
,
10321 gfc_add_block_to_block (&block
, &argse
.pre
);
10322 if (code
->resolved_isym
->id
== GFC_ISYM_ATOMIC_DEF
)
10323 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_def
, 7,
10324 token
, offset
, image_index
, value
, stat
,
10325 build_int_cst (integer_type_node
,
10326 (int) atom_expr
->ts
.type
),
10327 build_int_cst (integer_type_node
,
10328 (int) atom_expr
->ts
.kind
));
10330 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_op
, 9,
10331 build_int_cst (integer_type_node
, op
),
10332 token
, offset
, image_index
, value
, old
, stat
,
10333 build_int_cst (integer_type_node
,
10334 (int) atom_expr
->ts
.type
),
10335 build_int_cst (integer_type_node
,
10336 (int) atom_expr
->ts
.kind
));
10338 gfc_add_expr_to_block (&block
, tmp
);
10339 gfc_add_block_to_block (&block
, &argse
.post
);
10340 gfc_add_block_to_block (&block
, &post_block
);
10341 return gfc_finish_block (&block
);
10345 switch (code
->resolved_isym
->id
)
10347 case GFC_ISYM_ATOMIC_ADD
:
10348 case GFC_ISYM_ATOMIC_FETCH_ADD
:
10349 fn
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
10351 case GFC_ISYM_ATOMIC_AND
:
10352 case GFC_ISYM_ATOMIC_FETCH_AND
:
10353 fn
= BUILT_IN_ATOMIC_FETCH_AND_N
;
10355 case GFC_ISYM_ATOMIC_DEF
:
10356 fn
= BUILT_IN_ATOMIC_STORE_N
;
10358 case GFC_ISYM_ATOMIC_OR
:
10359 case GFC_ISYM_ATOMIC_FETCH_OR
:
10360 fn
= BUILT_IN_ATOMIC_FETCH_OR_N
;
10362 case GFC_ISYM_ATOMIC_XOR
:
10363 case GFC_ISYM_ATOMIC_FETCH_XOR
:
10364 fn
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
10367 gcc_unreachable ();
10370 tmp
= TREE_TYPE (TREE_TYPE (atom
));
10371 fn
= (built_in_function
) ((int) fn
10372 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
10374 tmp
= builtin_decl_explicit (fn
);
10375 tree itype
= TREE_TYPE (TREE_TYPE (atom
));
10376 tmp
= builtin_decl_explicit (fn
);
10378 switch (code
->resolved_isym
->id
)
10380 case GFC_ISYM_ATOMIC_ADD
:
10381 case GFC_ISYM_ATOMIC_AND
:
10382 case GFC_ISYM_ATOMIC_DEF
:
10383 case GFC_ISYM_ATOMIC_OR
:
10384 case GFC_ISYM_ATOMIC_XOR
:
10385 tmp
= build_call_expr_loc (input_location
, tmp
, 3, atom
,
10386 fold_convert (itype
, value
),
10387 build_int_cst (NULL
, MEMMODEL_RELAXED
));
10388 gfc_add_expr_to_block (&block
, tmp
);
10391 tmp
= build_call_expr_loc (input_location
, tmp
, 3, atom
,
10392 fold_convert (itype
, value
),
10393 build_int_cst (NULL
, MEMMODEL_RELAXED
));
10394 gfc_add_modify (&block
, old
, fold_convert (TREE_TYPE (old
), tmp
));
10398 if (stat
!= NULL_TREE
)
10399 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
10400 gfc_add_block_to_block (&block
, &post_block
);
10401 return gfc_finish_block (&block
);
10406 conv_intrinsic_atomic_ref (gfc_code
*code
)
10409 tree tmp
, atom
, value
, stat
= NULL_TREE
;
10410 stmtblock_t block
, post_block
;
10411 built_in_function fn
;
10412 gfc_expr
*atom_expr
= code
->ext
.actual
->next
->expr
;
10414 if (atom_expr
->expr_type
== EXPR_FUNCTION
10415 && atom_expr
->value
.function
.isym
10416 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
10417 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
10419 gfc_start_block (&block
);
10420 gfc_init_block (&post_block
);
10421 gfc_init_se (&argse
, NULL
);
10422 argse
.want_pointer
= 1;
10423 gfc_conv_expr (&argse
, atom_expr
);
10424 gfc_add_block_to_block (&block
, &argse
.pre
);
10425 gfc_add_block_to_block (&post_block
, &argse
.post
);
10428 gfc_init_se (&argse
, NULL
);
10429 if (flag_coarray
== GFC_FCOARRAY_LIB
10430 && code
->ext
.actual
->expr
->ts
.kind
== atom_expr
->ts
.kind
)
10431 argse
.want_pointer
= 1;
10432 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
10433 gfc_add_block_to_block (&block
, &argse
.pre
);
10434 gfc_add_block_to_block (&post_block
, &argse
.post
);
10435 value
= argse
.expr
;
10438 if (code
->ext
.actual
->next
->next
->expr
!= NULL
)
10440 gcc_assert (code
->ext
.actual
->next
->next
->expr
->expr_type
10442 gfc_init_se (&argse
, NULL
);
10443 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10444 argse
.want_pointer
= 1;
10445 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->next
->expr
);
10446 gfc_add_block_to_block (&block
, &argse
.pre
);
10447 gfc_add_block_to_block (&post_block
, &argse
.post
);
10450 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
10451 stat
= null_pointer_node
;
10453 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10455 tree image_index
, caf_decl
, offset
, token
;
10456 tree orig_value
= NULL_TREE
, vardecl
= NULL_TREE
;
10458 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
10459 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
10460 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
10462 if (gfc_is_coindexed (atom_expr
))
10463 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
10465 image_index
= integer_zero_node
;
10467 gfc_init_se (&argse
, NULL
);
10468 gfc_get_caf_token_offset (&argse
, &token
, &offset
, caf_decl
, atom
,
10470 gfc_add_block_to_block (&block
, &argse
.pre
);
10472 /* Different type, need type conversion. */
10473 if (!POINTER_TYPE_P (TREE_TYPE (value
)))
10475 vardecl
= gfc_create_var (TREE_TYPE (TREE_TYPE (atom
)), "value");
10476 orig_value
= value
;
10477 value
= gfc_build_addr_expr (NULL_TREE
, vardecl
);
10480 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_ref
, 7,
10481 token
, offset
, image_index
, value
, stat
,
10482 build_int_cst (integer_type_node
,
10483 (int) atom_expr
->ts
.type
),
10484 build_int_cst (integer_type_node
,
10485 (int) atom_expr
->ts
.kind
));
10486 gfc_add_expr_to_block (&block
, tmp
);
10487 if (vardecl
!= NULL_TREE
)
10488 gfc_add_modify (&block
, orig_value
,
10489 fold_convert (TREE_TYPE (orig_value
), vardecl
));
10490 gfc_add_block_to_block (&block
, &argse
.post
);
10491 gfc_add_block_to_block (&block
, &post_block
);
10492 return gfc_finish_block (&block
);
10495 tmp
= TREE_TYPE (TREE_TYPE (atom
));
10496 fn
= (built_in_function
) ((int) BUILT_IN_ATOMIC_LOAD_N
10497 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
10499 tmp
= builtin_decl_explicit (fn
);
10500 tmp
= build_call_expr_loc (input_location
, tmp
, 2, atom
,
10501 build_int_cst (integer_type_node
,
10502 MEMMODEL_RELAXED
));
10503 gfc_add_modify (&block
, value
, fold_convert (TREE_TYPE (value
), tmp
));
10505 if (stat
!= NULL_TREE
)
10506 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
10507 gfc_add_block_to_block (&block
, &post_block
);
10508 return gfc_finish_block (&block
);
10513 conv_intrinsic_atomic_cas (gfc_code
*code
)
10516 tree tmp
, atom
, old
, new_val
, comp
, stat
= NULL_TREE
;
10517 stmtblock_t block
, post_block
;
10518 built_in_function fn
;
10519 gfc_expr
*atom_expr
= code
->ext
.actual
->expr
;
10521 if (atom_expr
->expr_type
== EXPR_FUNCTION
10522 && atom_expr
->value
.function
.isym
10523 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
10524 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
10526 gfc_init_block (&block
);
10527 gfc_init_block (&post_block
);
10528 gfc_init_se (&argse
, NULL
);
10529 argse
.want_pointer
= 1;
10530 gfc_conv_expr (&argse
, atom_expr
);
10533 gfc_init_se (&argse
, NULL
);
10534 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10535 argse
.want_pointer
= 1;
10536 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->expr
);
10537 gfc_add_block_to_block (&block
, &argse
.pre
);
10538 gfc_add_block_to_block (&post_block
, &argse
.post
);
10541 gfc_init_se (&argse
, NULL
);
10542 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10543 argse
.want_pointer
= 1;
10544 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->expr
);
10545 gfc_add_block_to_block (&block
, &argse
.pre
);
10546 gfc_add_block_to_block (&post_block
, &argse
.post
);
10549 gfc_init_se (&argse
, NULL
);
10550 if (flag_coarray
== GFC_FCOARRAY_LIB
10551 && code
->ext
.actual
->next
->next
->next
->expr
->ts
.kind
10552 == atom_expr
->ts
.kind
)
10553 argse
.want_pointer
= 1;
10554 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->next
->expr
);
10555 gfc_add_block_to_block (&block
, &argse
.pre
);
10556 gfc_add_block_to_block (&post_block
, &argse
.post
);
10557 new_val
= argse
.expr
;
10560 if (code
->ext
.actual
->next
->next
->next
->next
->expr
!= NULL
)
10562 gcc_assert (code
->ext
.actual
->next
->next
->next
->next
->expr
->expr_type
10564 gfc_init_se (&argse
, NULL
);
10565 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10566 argse
.want_pointer
= 1;
10567 gfc_conv_expr_val (&argse
,
10568 code
->ext
.actual
->next
->next
->next
->next
->expr
);
10569 gfc_add_block_to_block (&block
, &argse
.pre
);
10570 gfc_add_block_to_block (&post_block
, &argse
.post
);
10573 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
10574 stat
= null_pointer_node
;
10576 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10578 tree image_index
, caf_decl
, offset
, token
;
10580 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
10581 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
10582 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
10584 if (gfc_is_coindexed (atom_expr
))
10585 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
10587 image_index
= integer_zero_node
;
10589 if (TREE_TYPE (TREE_TYPE (new_val
)) != TREE_TYPE (TREE_TYPE (old
)))
10591 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (old
)), "new");
10592 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), new_val
));
10593 new_val
= gfc_build_addr_expr (NULL_TREE
, tmp
);
10596 /* Convert a constant to a pointer. */
10597 if (!POINTER_TYPE_P (TREE_TYPE (comp
)))
10599 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (old
)), "comp");
10600 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), comp
));
10601 comp
= gfc_build_addr_expr (NULL_TREE
, tmp
);
10604 gfc_init_se (&argse
, NULL
);
10605 gfc_get_caf_token_offset (&argse
, &token
, &offset
, caf_decl
, atom
,
10607 gfc_add_block_to_block (&block
, &argse
.pre
);
10609 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_cas
, 9,
10610 token
, offset
, image_index
, old
, comp
, new_val
,
10611 stat
, build_int_cst (integer_type_node
,
10612 (int) atom_expr
->ts
.type
),
10613 build_int_cst (integer_type_node
,
10614 (int) atom_expr
->ts
.kind
));
10615 gfc_add_expr_to_block (&block
, tmp
);
10616 gfc_add_block_to_block (&block
, &argse
.post
);
10617 gfc_add_block_to_block (&block
, &post_block
);
10618 return gfc_finish_block (&block
);
10621 tmp
= TREE_TYPE (TREE_TYPE (atom
));
10622 fn
= (built_in_function
) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
10623 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
10625 tmp
= builtin_decl_explicit (fn
);
10627 gfc_add_modify (&block
, old
, comp
);
10628 tmp
= build_call_expr_loc (input_location
, tmp
, 6, atom
,
10629 gfc_build_addr_expr (NULL
, old
),
10630 fold_convert (TREE_TYPE (old
), new_val
),
10631 boolean_false_node
,
10632 build_int_cst (NULL
, MEMMODEL_RELAXED
),
10633 build_int_cst (NULL
, MEMMODEL_RELAXED
));
10634 gfc_add_expr_to_block (&block
, tmp
);
10636 if (stat
!= NULL_TREE
)
10637 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
10638 gfc_add_block_to_block (&block
, &post_block
);
10639 return gfc_finish_block (&block
);
10643 conv_intrinsic_event_query (gfc_code
*code
)
10646 tree stat
= NULL_TREE
, stat2
= NULL_TREE
;
10647 tree count
= NULL_TREE
, count2
= NULL_TREE
;
10649 gfc_expr
*event_expr
= code
->ext
.actual
->expr
;
10651 if (code
->ext
.actual
->next
->next
->expr
)
10653 gcc_assert (code
->ext
.actual
->next
->next
->expr
->expr_type
10655 gfc_init_se (&argse
, NULL
);
10656 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->next
->expr
);
10659 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
10660 stat
= null_pointer_node
;
10662 if (code
->ext
.actual
->next
->expr
)
10664 gcc_assert (code
->ext
.actual
->next
->expr
->expr_type
== EXPR_VARIABLE
);
10665 gfc_init_se (&argse
, NULL
);
10666 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->expr
);
10667 count
= argse
.expr
;
10670 gfc_start_block (&se
.pre
);
10671 if (flag_coarray
== GFC_FCOARRAY_LIB
)
10673 tree tmp
, token
, image_index
;
10674 tree index
= size_zero_node
;
10676 if (event_expr
->expr_type
== EXPR_FUNCTION
10677 && event_expr
->value
.function
.isym
10678 && event_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
10679 event_expr
= event_expr
->value
.function
.actual
->expr
;
10681 tree caf_decl
= gfc_get_tree_for_caf_expr (event_expr
);
10683 if (event_expr
->symtree
->n
.sym
->ts
.type
!= BT_DERIVED
10684 || event_expr
->symtree
->n
.sym
->ts
.u
.derived
->from_intmod
10685 != INTMOD_ISO_FORTRAN_ENV
10686 || event_expr
->symtree
->n
.sym
->ts
.u
.derived
->intmod_sym_id
10687 != ISOFORTRAN_EVENT_TYPE
)
10689 gfc_error ("Sorry, the event component of derived type at %L is not "
10690 "yet supported", &event_expr
->where
);
10694 if (gfc_is_coindexed (event_expr
))
10696 gfc_error ("The event variable at %L shall not be coindexed",
10697 &event_expr
->where
);
10701 image_index
= integer_zero_node
;
10703 gfc_get_caf_token_offset (&se
, &token
, NULL
, caf_decl
, NULL_TREE
,
10706 /* For arrays, obtain the array index. */
10707 if (gfc_expr_attr (event_expr
).dimension
)
10709 tree desc
, tmp
, extent
, lbound
, ubound
;
10710 gfc_array_ref
*ar
, ar2
;
10713 /* TODO: Extend this, once DT components are supported. */
10714 ar
= &event_expr
->ref
->u
.ar
;
10716 memset (ar
, '\0', sizeof (*ar
));
10718 ar
->type
= AR_FULL
;
10720 gfc_init_se (&argse
, NULL
);
10721 argse
.descriptor_only
= 1;
10722 gfc_conv_expr_descriptor (&argse
, event_expr
);
10723 gfc_add_block_to_block (&se
.pre
, &argse
.pre
);
10727 extent
= integer_one_node
;
10728 for (i
= 0; i
< ar
->dimen
; i
++)
10730 gfc_init_se (&argse
, NULL
);
10731 gfc_conv_expr_type (&argse
, ar
->start
[i
], integer_type_node
);
10732 gfc_add_block_to_block (&argse
.pre
, &argse
.pre
);
10733 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[i
]);
10734 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
10735 integer_type_node
, argse
.expr
,
10736 fold_convert(integer_type_node
, lbound
));
10737 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
10738 integer_type_node
, extent
, tmp
);
10739 index
= fold_build2_loc (input_location
, PLUS_EXPR
,
10740 integer_type_node
, index
, tmp
);
10741 if (i
< ar
->dimen
- 1)
10743 ubound
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[i
]);
10744 tmp
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
10745 tmp
= fold_convert (integer_type_node
, tmp
);
10746 extent
= fold_build2_loc (input_location
, MULT_EXPR
,
10747 integer_type_node
, extent
, tmp
);
10752 if (count
!= null_pointer_node
&& TREE_TYPE (count
) != integer_type_node
)
10755 count
= gfc_create_var (integer_type_node
, "count");
10758 if (stat
!= null_pointer_node
&& TREE_TYPE (stat
) != integer_type_node
)
10761 stat
= gfc_create_var (integer_type_node
, "stat");
10764 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_event_query
, 5,
10765 token
, index
, image_index
, count
10766 ? gfc_build_addr_expr (NULL
, count
) : count
,
10767 stat
!= null_pointer_node
10768 ? gfc_build_addr_expr (NULL
, stat
) : stat
);
10769 gfc_add_expr_to_block (&se
.pre
, tmp
);
10771 if (count2
!= NULL_TREE
)
10772 gfc_add_modify (&se
.pre
, count2
,
10773 fold_convert (TREE_TYPE (count2
), count
));
10775 if (stat2
!= NULL_TREE
)
10776 gfc_add_modify (&se
.pre
, stat2
,
10777 fold_convert (TREE_TYPE (stat2
), stat
));
10779 return gfc_finish_block (&se
.pre
);
10782 gfc_init_se (&argse
, NULL
);
10783 gfc_conv_expr_val (&argse
, code
->ext
.actual
->expr
);
10784 gfc_add_modify (&se
.pre
, count
, fold_convert (TREE_TYPE (count
), argse
.expr
));
10786 if (stat
!= NULL_TREE
)
10787 gfc_add_modify (&se
.pre
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
10789 return gfc_finish_block (&se
.pre
);
10793 conv_intrinsic_move_alloc (gfc_code
*code
)
10796 gfc_expr
*from_expr
, *to_expr
;
10797 gfc_expr
*to_expr2
, *from_expr2
= NULL
;
10798 gfc_se from_se
, to_se
;
10802 gfc_start_block (&block
);
10804 from_expr
= code
->ext
.actual
->expr
;
10805 to_expr
= code
->ext
.actual
->next
->expr
;
10807 gfc_init_se (&from_se
, NULL
);
10808 gfc_init_se (&to_se
, NULL
);
10810 gcc_assert (from_expr
->ts
.type
!= BT_CLASS
10811 || to_expr
->ts
.type
== BT_CLASS
);
10812 coarray
= gfc_get_corank (from_expr
) != 0;
10814 if (from_expr
->rank
== 0 && !coarray
)
10816 if (from_expr
->ts
.type
!= BT_CLASS
)
10817 from_expr2
= from_expr
;
10820 from_expr2
= gfc_copy_expr (from_expr
);
10821 gfc_add_data_component (from_expr2
);
10824 if (to_expr
->ts
.type
!= BT_CLASS
)
10825 to_expr2
= to_expr
;
10828 to_expr2
= gfc_copy_expr (to_expr
);
10829 gfc_add_data_component (to_expr2
);
10832 from_se
.want_pointer
= 1;
10833 to_se
.want_pointer
= 1;
10834 gfc_conv_expr (&from_se
, from_expr2
);
10835 gfc_conv_expr (&to_se
, to_expr2
);
10836 gfc_add_block_to_block (&block
, &from_se
.pre
);
10837 gfc_add_block_to_block (&block
, &to_se
.pre
);
10839 /* Deallocate "to". */
10840 tmp
= gfc_deallocate_scalar_with_status (to_se
.expr
, NULL_TREE
, NULL_TREE
,
10841 true, to_expr
, to_expr
->ts
);
10842 gfc_add_expr_to_block (&block
, tmp
);
10844 /* Assign (_data) pointers. */
10845 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
10846 fold_convert (TREE_TYPE (to_se
.expr
), from_se
.expr
));
10848 /* Set "from" to NULL. */
10849 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
10850 fold_convert (TREE_TYPE (from_se
.expr
), null_pointer_node
));
10852 gfc_add_block_to_block (&block
, &from_se
.post
);
10853 gfc_add_block_to_block (&block
, &to_se
.post
);
10856 if (to_expr
->ts
.type
== BT_CLASS
)
10860 gfc_free_expr (to_expr2
);
10861 gfc_init_se (&to_se
, NULL
);
10862 to_se
.want_pointer
= 1;
10863 gfc_add_vptr_component (to_expr
);
10864 gfc_conv_expr (&to_se
, to_expr
);
10866 if (from_expr
->ts
.type
== BT_CLASS
)
10868 if (UNLIMITED_POLY (from_expr
))
10872 vtab
= gfc_find_derived_vtab (from_expr
->ts
.u
.derived
);
10876 gfc_free_expr (from_expr2
);
10877 gfc_init_se (&from_se
, NULL
);
10878 from_se
.want_pointer
= 1;
10879 gfc_add_vptr_component (from_expr
);
10880 gfc_conv_expr (&from_se
, from_expr
);
10881 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
10882 fold_convert (TREE_TYPE (to_se
.expr
),
10885 /* Reset _vptr component to declared type. */
10887 /* Unlimited polymorphic. */
10888 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
10889 fold_convert (TREE_TYPE (from_se
.expr
),
10890 null_pointer_node
));
10893 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
10894 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
10895 fold_convert (TREE_TYPE (from_se
.expr
), tmp
));
10900 vtab
= gfc_find_vtab (&from_expr
->ts
);
10902 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
10903 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
10904 fold_convert (TREE_TYPE (to_se
.expr
), tmp
));
10908 if (to_expr
->ts
.type
== BT_CHARACTER
&& to_expr
->ts
.deferred
)
10910 gfc_add_modify_loc (input_location
, &block
, to_se
.string_length
,
10911 fold_convert (TREE_TYPE (to_se
.string_length
),
10912 from_se
.string_length
));
10913 if (from_expr
->ts
.deferred
)
10914 gfc_add_modify_loc (input_location
, &block
, from_se
.string_length
,
10915 build_int_cst (TREE_TYPE (from_se
.string_length
), 0));
10918 return gfc_finish_block (&block
);
10921 /* Update _vptr component. */
10922 if (to_expr
->ts
.type
== BT_CLASS
)
10926 to_se
.want_pointer
= 1;
10927 to_expr2
= gfc_copy_expr (to_expr
);
10928 gfc_add_vptr_component (to_expr2
);
10929 gfc_conv_expr (&to_se
, to_expr2
);
10931 if (from_expr
->ts
.type
== BT_CLASS
)
10933 if (UNLIMITED_POLY (from_expr
))
10937 vtab
= gfc_find_derived_vtab (from_expr
->ts
.u
.derived
);
10941 from_se
.want_pointer
= 1;
10942 from_expr2
= gfc_copy_expr (from_expr
);
10943 gfc_add_vptr_component (from_expr2
);
10944 gfc_conv_expr (&from_se
, from_expr2
);
10945 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
10946 fold_convert (TREE_TYPE (to_se
.expr
),
10949 /* Reset _vptr component to declared type. */
10951 /* Unlimited polymorphic. */
10952 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
10953 fold_convert (TREE_TYPE (from_se
.expr
),
10954 null_pointer_node
));
10957 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
10958 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
10959 fold_convert (TREE_TYPE (from_se
.expr
), tmp
));
10964 vtab
= gfc_find_vtab (&from_expr
->ts
);
10966 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
10967 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
10968 fold_convert (TREE_TYPE (to_se
.expr
), tmp
));
10971 gfc_free_expr (to_expr2
);
10972 gfc_init_se (&to_se
, NULL
);
10974 if (from_expr
->ts
.type
== BT_CLASS
)
10976 gfc_free_expr (from_expr2
);
10977 gfc_init_se (&from_se
, NULL
);
10982 /* Deallocate "to". */
10983 if (from_expr
->rank
== 0)
10985 to_se
.want_coarray
= 1;
10986 from_se
.want_coarray
= 1;
10988 gfc_conv_expr_descriptor (&to_se
, to_expr
);
10989 gfc_conv_expr_descriptor (&from_se
, from_expr
);
10991 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
10992 is an image control "statement", cf. IR F08/0040 in 12-006A. */
10993 if (coarray
&& flag_coarray
== GFC_FCOARRAY_LIB
)
10997 tmp
= gfc_deallocate_with_status (to_se
.expr
, NULL_TREE
, NULL_TREE
,
10998 NULL_TREE
, NULL_TREE
, true, to_expr
,
10999 GFC_CAF_COARRAY_DEALLOCATE_ONLY
);
11000 gfc_add_expr_to_block (&block
, tmp
);
11002 tmp
= gfc_conv_descriptor_data_get (to_se
.expr
);
11003 cond
= fold_build2_loc (input_location
, EQ_EXPR
,
11004 logical_type_node
, tmp
,
11005 fold_convert (TREE_TYPE (tmp
),
11006 null_pointer_node
));
11007 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_sync_all
,
11008 3, null_pointer_node
, null_pointer_node
,
11009 build_int_cst (integer_type_node
, 0));
11011 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
,
11012 tmp
, build_empty_stmt (input_location
));
11013 gfc_add_expr_to_block (&block
, tmp
);
11017 if (to_expr
->ts
.type
== BT_DERIVED
11018 && to_expr
->ts
.u
.derived
->attr
.alloc_comp
)
11020 tmp
= gfc_deallocate_alloc_comp (to_expr
->ts
.u
.derived
,
11021 to_se
.expr
, to_expr
->rank
);
11022 gfc_add_expr_to_block (&block
, tmp
);
11025 tmp
= gfc_conv_descriptor_data_get (to_se
.expr
);
11026 tmp
= gfc_deallocate_with_status (tmp
, NULL_TREE
, NULL_TREE
, NULL_TREE
,
11027 NULL_TREE
, true, to_expr
,
11028 GFC_CAF_COARRAY_NOCOARRAY
);
11029 gfc_add_expr_to_block (&block
, tmp
);
11032 /* Move the pointer and update the array descriptor data. */
11033 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
, from_se
.expr
);
11035 /* Set "from" to NULL. */
11036 tmp
= gfc_conv_descriptor_data_get (from_se
.expr
);
11037 gfc_add_modify_loc (input_location
, &block
, tmp
,
11038 fold_convert (TREE_TYPE (tmp
), null_pointer_node
));
11041 if (to_expr
->ts
.type
== BT_CHARACTER
&& to_expr
->ts
.deferred
)
11043 gfc_add_modify_loc (input_location
, &block
, to_se
.string_length
,
11044 fold_convert (TREE_TYPE (to_se
.string_length
),
11045 from_se
.string_length
));
11046 if (from_expr
->ts
.deferred
)
11047 gfc_add_modify_loc (input_location
, &block
, from_se
.string_length
,
11048 build_int_cst (TREE_TYPE (from_se
.string_length
), 0));
11051 return gfc_finish_block (&block
);
11056 gfc_conv_intrinsic_subroutine (gfc_code
*code
)
11060 gcc_assert (code
->resolved_isym
);
11062 switch (code
->resolved_isym
->id
)
11064 case GFC_ISYM_MOVE_ALLOC
:
11065 res
= conv_intrinsic_move_alloc (code
);
11068 case GFC_ISYM_ATOMIC_CAS
:
11069 res
= conv_intrinsic_atomic_cas (code
);
11072 case GFC_ISYM_ATOMIC_ADD
:
11073 case GFC_ISYM_ATOMIC_AND
:
11074 case GFC_ISYM_ATOMIC_DEF
:
11075 case GFC_ISYM_ATOMIC_OR
:
11076 case GFC_ISYM_ATOMIC_XOR
:
11077 case GFC_ISYM_ATOMIC_FETCH_ADD
:
11078 case GFC_ISYM_ATOMIC_FETCH_AND
:
11079 case GFC_ISYM_ATOMIC_FETCH_OR
:
11080 case GFC_ISYM_ATOMIC_FETCH_XOR
:
11081 res
= conv_intrinsic_atomic_op (code
);
11084 case GFC_ISYM_ATOMIC_REF
:
11085 res
= conv_intrinsic_atomic_ref (code
);
11088 case GFC_ISYM_EVENT_QUERY
:
11089 res
= conv_intrinsic_event_query (code
);
11092 case GFC_ISYM_C_F_POINTER
:
11093 case GFC_ISYM_C_F_PROCPOINTER
:
11094 res
= conv_isocbinding_subroutine (code
);
11097 case GFC_ISYM_CAF_SEND
:
11098 res
= conv_caf_send (code
);
11101 case GFC_ISYM_CO_BROADCAST
:
11102 case GFC_ISYM_CO_MIN
:
11103 case GFC_ISYM_CO_MAX
:
11104 case GFC_ISYM_CO_REDUCE
:
11105 case GFC_ISYM_CO_SUM
:
11106 res
= conv_co_collective (code
);
11109 case GFC_ISYM_FREE
:
11110 res
= conv_intrinsic_free (code
);
11113 case GFC_ISYM_RANDOM_INIT
:
11114 res
= conv_intrinsic_random_init (code
);
11117 case GFC_ISYM_KILL
:
11118 res
= conv_intrinsic_kill_sub (code
);
11121 case GFC_ISYM_SYSTEM_CLOCK
:
11122 res
= conv_intrinsic_system_clock (code
);
11133 #include "gt-fortran-trans-intrinsic.h"