1 /* Intrinsic translation
2 Copyright (C) 2002-2015 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"
27 #include "tm.h" /* For UNITS_PER_WORD. */
31 #include "double-int.h"
39 #include "fold-const.h"
40 #include "stringpool.h"
41 #include "tree-nested.h"
42 #include "stor-layout.h"
45 #include "diagnostic-core.h" /* For internal_error. */
46 #include "toplev.h" /* For rest_of_decl_compilation. */
49 #include "intrinsic.h"
51 #include "trans-const.h"
52 #include "trans-types.h"
53 #include "trans-array.h"
54 #include "dependency.h" /* For CAF array alias analysis. */
55 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
56 #include "trans-stmt.h"
57 #include "tree-nested.h"
59 /* This maps Fortran intrinsic math functions to external library or GCC
61 typedef struct GTY(()) gfc_intrinsic_map_t
{
62 /* The explicit enum is required to work around inadequacies in the
63 garbage collection/gengtype parsing mechanism. */
66 /* Enum value from the "language-independent", aka C-centric, part
67 of gcc, or END_BUILTINS of no such value set. */
68 enum built_in_function float_built_in
;
69 enum built_in_function double_built_in
;
70 enum built_in_function long_double_built_in
;
71 enum built_in_function complex_float_built_in
;
72 enum built_in_function complex_double_built_in
;
73 enum built_in_function complex_long_double_built_in
;
75 /* True if the naming pattern is to prepend "c" for complex and
76 append "f" for kind=4. False if the naming pattern is to
77 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
80 /* True if a complex version of the function exists. */
81 bool complex_available
;
83 /* True if the function should be marked const. */
86 /* The base library name of this function. */
89 /* Cache decls created for the various operand types. */
101 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
102 defines complex variants of all of the entries in mathbuiltins.def
104 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
105 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
106 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
107 true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
108 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
110 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
111 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
112 BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
113 BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
114 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
116 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
117 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
118 END_BUILTINS, END_BUILTINS, END_BUILTINS, \
119 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
120 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
122 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
123 { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
124 BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
125 true, false, CONST, NAME, NULL_TREE, NULL_TREE, \
126 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
128 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map
[] =
130 /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
131 DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
132 to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
133 #include "mathbuiltins.def"
135 /* Functions in libgfortran. */
136 LIB_FUNCTION (ERFC_SCALED
, "erfc_scaled", false),
139 LIB_FUNCTION (NONE
, NULL
, false)
144 #undef DEFINE_MATH_BUILTIN
145 #undef DEFINE_MATH_BUILTIN_C
148 enum rounding_mode
{ RND_ROUND
, RND_TRUNC
, RND_CEIL
, RND_FLOOR
};
151 /* Find the correct variant of a given builtin from its argument. */
153 builtin_decl_for_precision (enum built_in_function base_built_in
,
156 enum built_in_function i
= END_BUILTINS
;
158 gfc_intrinsic_map_t
*m
;
159 for (m
= gfc_intrinsic_map
; m
->double_built_in
!= base_built_in
; m
++)
162 if (precision
== TYPE_PRECISION (float_type_node
))
163 i
= m
->float_built_in
;
164 else if (precision
== TYPE_PRECISION (double_type_node
))
165 i
= m
->double_built_in
;
166 else if (precision
== TYPE_PRECISION (long_double_type_node
))
167 i
= m
->long_double_built_in
;
168 else if (precision
== TYPE_PRECISION (float128_type_node
))
170 /* Special treatment, because it is not exactly a built-in, but
171 a library function. */
172 return m
->real16_decl
;
175 return (i
== END_BUILTINS
? NULL_TREE
: builtin_decl_explicit (i
));
180 gfc_builtin_decl_for_float_kind (enum built_in_function double_built_in
,
183 int i
= gfc_validate_kind (BT_REAL
, kind
, false);
185 if (gfc_real_kinds
[i
].c_float128
)
187 /* For __float128, the story is a bit different, because we return
188 a decl to a library function rather than a built-in. */
189 gfc_intrinsic_map_t
*m
;
190 for (m
= gfc_intrinsic_map
; m
->double_built_in
!= double_built_in
; m
++)
193 return m
->real16_decl
;
196 return builtin_decl_for_precision (double_built_in
,
197 gfc_real_kinds
[i
].mode_precision
);
201 /* Evaluate the arguments to an intrinsic function. The value
202 of NARGS may be less than the actual number of arguments in EXPR
203 to allow optional "KIND" arguments that are not included in the
204 generated code to be ignored. */
207 gfc_conv_intrinsic_function_args (gfc_se
*se
, gfc_expr
*expr
,
208 tree
*argarray
, int nargs
)
210 gfc_actual_arglist
*actual
;
212 gfc_intrinsic_arg
*formal
;
216 formal
= expr
->value
.function
.isym
->formal
;
217 actual
= expr
->value
.function
.actual
;
219 for (curr_arg
= 0; curr_arg
< nargs
; curr_arg
++,
220 actual
= actual
->next
,
221 formal
= formal
? formal
->next
: NULL
)
225 /* Skip omitted optional arguments. */
232 /* Evaluate the parameter. This will substitute scalarized
233 references automatically. */
234 gfc_init_se (&argse
, se
);
236 if (e
->ts
.type
== BT_CHARACTER
)
238 gfc_conv_expr (&argse
, e
);
239 gfc_conv_string_parameter (&argse
);
240 argarray
[curr_arg
++] = argse
.string_length
;
241 gcc_assert (curr_arg
< nargs
);
244 gfc_conv_expr_val (&argse
, e
);
246 /* If an optional argument is itself an optional dummy argument,
247 check its presence and substitute a null if absent. */
248 if (e
->expr_type
== EXPR_VARIABLE
249 && e
->symtree
->n
.sym
->attr
.optional
252 gfc_conv_missing_dummy (&argse
, e
, formal
->ts
, 0);
254 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
255 gfc_add_block_to_block (&se
->post
, &argse
.post
);
256 argarray
[curr_arg
] = argse
.expr
;
260 /* Count the number of actual arguments to the intrinsic function EXPR
261 including any "hidden" string length arguments. */
264 gfc_intrinsic_argument_list_length (gfc_expr
*expr
)
267 gfc_actual_arglist
*actual
;
269 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
274 if (actual
->expr
->ts
.type
== BT_CHARACTER
)
284 /* Conversions between different types are output by the frontend as
285 intrinsic functions. We implement these directly with inline code. */
288 gfc_conv_intrinsic_conversion (gfc_se
* se
, gfc_expr
* expr
)
294 nargs
= gfc_intrinsic_argument_list_length (expr
);
295 args
= XALLOCAVEC (tree
, nargs
);
297 /* Evaluate all the arguments passed. Whilst we're only interested in the
298 first one here, there are other parts of the front-end that assume this
299 and will trigger an ICE if it's not the case. */
300 type
= gfc_typenode_for_spec (&expr
->ts
);
301 gcc_assert (expr
->value
.function
.actual
->expr
);
302 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
304 /* Conversion between character kinds involves a call to a library
306 if (expr
->ts
.type
== BT_CHARACTER
)
308 tree fndecl
, var
, addr
, tmp
;
310 if (expr
->ts
.kind
== 1
311 && expr
->value
.function
.actual
->expr
->ts
.kind
== 4)
312 fndecl
= gfor_fndecl_convert_char4_to_char1
;
313 else if (expr
->ts
.kind
== 4
314 && expr
->value
.function
.actual
->expr
->ts
.kind
== 1)
315 fndecl
= gfor_fndecl_convert_char1_to_char4
;
319 /* Create the variable storing the converted value. */
320 type
= gfc_get_pchar_type (expr
->ts
.kind
);
321 var
= gfc_create_var (type
, "str");
322 addr
= gfc_build_addr_expr (build_pointer_type (type
), var
);
324 /* Call the library function that will perform the conversion. */
325 gcc_assert (nargs
>= 2);
326 tmp
= build_call_expr_loc (input_location
,
327 fndecl
, 3, addr
, args
[0], args
[1]);
328 gfc_add_expr_to_block (&se
->pre
, tmp
);
330 /* Free the temporary afterwards. */
331 tmp
= gfc_call_free (var
);
332 gfc_add_expr_to_block (&se
->post
, tmp
);
335 se
->string_length
= args
[0];
340 /* Conversion from complex to non-complex involves taking the real
341 component of the value. */
342 if (TREE_CODE (TREE_TYPE (args
[0])) == COMPLEX_TYPE
343 && expr
->ts
.type
!= BT_COMPLEX
)
347 artype
= TREE_TYPE (TREE_TYPE (args
[0]));
348 args
[0] = fold_build1_loc (input_location
, REALPART_EXPR
, artype
,
352 se
->expr
= convert (type
, args
[0]);
355 /* This is needed because the gcc backend only implements
356 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
357 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
358 Similarly for CEILING. */
361 build_fixbound_expr (stmtblock_t
* pblock
, tree arg
, tree type
, int up
)
368 argtype
= TREE_TYPE (arg
);
369 arg
= gfc_evaluate_now (arg
, pblock
);
371 intval
= convert (type
, arg
);
372 intval
= gfc_evaluate_now (intval
, pblock
);
374 tmp
= convert (argtype
, intval
);
375 cond
= fold_build2_loc (input_location
, up
? GE_EXPR
: LE_EXPR
,
376 boolean_type_node
, tmp
, arg
);
378 tmp
= fold_build2_loc (input_location
, up
? PLUS_EXPR
: MINUS_EXPR
, type
,
379 intval
, build_int_cst (type
, 1));
380 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
, intval
, tmp
);
385 /* Round to nearest integer, away from zero. */
388 build_round_expr (tree arg
, tree restype
)
392 int argprec
, resprec
;
394 argtype
= TREE_TYPE (arg
);
395 argprec
= TYPE_PRECISION (argtype
);
396 resprec
= TYPE_PRECISION (restype
);
398 /* Depending on the type of the result, choose the int intrinsic
399 (iround, available only as a builtin, therefore cannot use it for
400 __float128), long int intrinsic (lround family) or long long
401 intrinsic (llround). We might also need to convert the result
403 if (resprec
<= INT_TYPE_SIZE
&& argprec
<= LONG_DOUBLE_TYPE_SIZE
)
404 fn
= builtin_decl_for_precision (BUILT_IN_IROUND
, argprec
);
405 else if (resprec
<= LONG_TYPE_SIZE
)
406 fn
= builtin_decl_for_precision (BUILT_IN_LROUND
, argprec
);
407 else if (resprec
<= LONG_LONG_TYPE_SIZE
)
408 fn
= builtin_decl_for_precision (BUILT_IN_LLROUND
, argprec
);
412 return fold_convert (restype
, build_call_expr_loc (input_location
,
417 /* Convert a real to an integer using a specific rounding mode.
418 Ideally we would just build the corresponding GENERIC node,
419 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
422 build_fix_expr (stmtblock_t
* pblock
, tree arg
, tree type
,
423 enum rounding_mode op
)
428 return build_fixbound_expr (pblock
, arg
, type
, 0);
432 return build_fixbound_expr (pblock
, arg
, type
, 1);
436 return build_round_expr (arg
, type
);
440 return fold_build1_loc (input_location
, FIX_TRUNC_EXPR
, type
, arg
);
449 /* Round a real value using the specified rounding mode.
450 We use a temporary integer of that same kind size as the result.
451 Values larger than those that can be represented by this kind are
452 unchanged, as they will not be accurate enough to represent the
454 huge = HUGE (KIND (a))
455 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
459 gfc_conv_intrinsic_aint (gfc_se
* se
, gfc_expr
* expr
, enum rounding_mode op
)
471 kind
= expr
->ts
.kind
;
472 nargs
= gfc_intrinsic_argument_list_length (expr
);
475 /* We have builtin functions for some cases. */
479 decl
= gfc_builtin_decl_for_float_kind (BUILT_IN_ROUND
, kind
);
483 decl
= gfc_builtin_decl_for_float_kind (BUILT_IN_TRUNC
, kind
);
490 /* Evaluate the argument. */
491 gcc_assert (expr
->value
.function
.actual
->expr
);
492 gfc_conv_intrinsic_function_args (se
, expr
, arg
, nargs
);
494 /* Use a builtin function if one exists. */
495 if (decl
!= NULL_TREE
)
497 se
->expr
= build_call_expr_loc (input_location
, decl
, 1, arg
[0]);
501 /* This code is probably redundant, but we'll keep it lying around just
503 type
= gfc_typenode_for_spec (&expr
->ts
);
504 arg
[0] = gfc_evaluate_now (arg
[0], &se
->pre
);
506 /* Test if the value is too large to handle sensibly. */
507 gfc_set_model_kind (kind
);
509 n
= gfc_validate_kind (BT_INTEGER
, kind
, false);
510 mpfr_set_z (huge
, gfc_integer_kinds
[n
].huge
, GFC_RND_MODE
);
511 tmp
= gfc_conv_mpfr_to_tree (huge
, kind
, 0);
512 cond
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
, arg
[0],
515 mpfr_neg (huge
, huge
, GFC_RND_MODE
);
516 tmp
= gfc_conv_mpfr_to_tree (huge
, kind
, 0);
517 tmp
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
, arg
[0],
519 cond
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
, boolean_type_node
,
521 itype
= gfc_get_int_type (kind
);
523 tmp
= build_fix_expr (&se
->pre
, arg
[0], itype
, op
);
524 tmp
= convert (type
, tmp
);
525 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
, tmp
,
531 /* Convert to an integer using the specified rounding mode. */
534 gfc_conv_intrinsic_int (gfc_se
* se
, gfc_expr
* expr
, enum rounding_mode op
)
540 nargs
= gfc_intrinsic_argument_list_length (expr
);
541 args
= XALLOCAVEC (tree
, nargs
);
543 /* Evaluate the argument, we process all arguments even though we only
544 use the first one for code generation purposes. */
545 type
= gfc_typenode_for_spec (&expr
->ts
);
546 gcc_assert (expr
->value
.function
.actual
->expr
);
547 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
549 if (TREE_CODE (TREE_TYPE (args
[0])) == INTEGER_TYPE
)
551 /* Conversion to a different integer kind. */
552 se
->expr
= convert (type
, args
[0]);
556 /* Conversion from complex to non-complex involves taking the real
557 component of the value. */
558 if (TREE_CODE (TREE_TYPE (args
[0])) == COMPLEX_TYPE
559 && expr
->ts
.type
!= BT_COMPLEX
)
563 artype
= TREE_TYPE (TREE_TYPE (args
[0]));
564 args
[0] = fold_build1_loc (input_location
, REALPART_EXPR
, artype
,
568 se
->expr
= build_fix_expr (&se
->pre
, args
[0], type
, op
);
573 /* Get the imaginary component of a value. */
576 gfc_conv_intrinsic_imagpart (gfc_se
* se
, gfc_expr
* expr
)
580 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
581 se
->expr
= fold_build1_loc (input_location
, IMAGPART_EXPR
,
582 TREE_TYPE (TREE_TYPE (arg
)), arg
);
586 /* Get the complex conjugate of a value. */
589 gfc_conv_intrinsic_conjg (gfc_se
* se
, gfc_expr
* expr
)
593 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
594 se
->expr
= fold_build1_loc (input_location
, CONJ_EXPR
, TREE_TYPE (arg
), arg
);
600 define_quad_builtin (const char *name
, tree type
, bool is_const
)
603 fndecl
= build_decl (input_location
, FUNCTION_DECL
, get_identifier (name
),
606 /* Mark the decl as external. */
607 DECL_EXTERNAL (fndecl
) = 1;
608 TREE_PUBLIC (fndecl
) = 1;
610 /* Mark it __attribute__((const)). */
611 TREE_READONLY (fndecl
) = is_const
;
613 rest_of_decl_compilation (fndecl
, 1, 0);
620 /* Initialize function decls for library functions. The external functions
621 are created as required. Builtin functions are added here. */
624 gfc_build_intrinsic_lib_fndecls (void)
626 gfc_intrinsic_map_t
*m
;
627 tree quad_decls
[END_BUILTINS
+ 1];
629 if (gfc_real16_is_float128
)
631 /* If we have soft-float types, we create the decls for their
632 C99-like library functions. For now, we only handle __float128
633 q-suffixed functions. */
635 tree type
, complex_type
, func_1
, func_2
, func_cabs
, func_frexp
;
636 tree func_iround
, func_lround
, func_llround
, func_scalbn
, func_cpow
;
638 memset (quad_decls
, 0, sizeof(tree
) * (END_BUILTINS
+ 1));
640 type
= float128_type_node
;
641 complex_type
= complex_float128_type_node
;
642 /* type (*) (type) */
643 func_1
= build_function_type_list (type
, type
, NULL_TREE
);
645 func_iround
= build_function_type_list (integer_type_node
,
647 /* long (*) (type) */
648 func_lround
= build_function_type_list (long_integer_type_node
,
650 /* long long (*) (type) */
651 func_llround
= build_function_type_list (long_long_integer_type_node
,
653 /* type (*) (type, type) */
654 func_2
= build_function_type_list (type
, type
, type
, NULL_TREE
);
655 /* type (*) (type, &int) */
657 = build_function_type_list (type
,
659 build_pointer_type (integer_type_node
),
661 /* type (*) (type, int) */
662 func_scalbn
= build_function_type_list (type
,
663 type
, integer_type_node
, NULL_TREE
);
664 /* type (*) (complex type) */
665 func_cabs
= build_function_type_list (type
, complex_type
, NULL_TREE
);
666 /* complex type (*) (complex type, complex type) */
668 = build_function_type_list (complex_type
,
669 complex_type
, complex_type
, NULL_TREE
);
671 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE)
672 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE)
673 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX)
675 /* Only these built-ins are actually needed here. These are used directly
676 from the code, when calling builtin_decl_for_precision() or
677 builtin_decl_for_float_type(). The others are all constructed by
678 gfc_get_intrinsic_lib_fndecl(). */
679 #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
680 quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, CONST);
682 #include "mathbuiltins.def"
686 #undef DEFINE_MATH_BUILTIN
687 #undef DEFINE_MATH_BUILTIN_C
691 /* Add GCC builtin functions. */
692 for (m
= gfc_intrinsic_map
;
693 m
->id
!= GFC_ISYM_NONE
|| m
->double_built_in
!= END_BUILTINS
; m
++)
695 if (m
->float_built_in
!= END_BUILTINS
)
696 m
->real4_decl
= builtin_decl_explicit (m
->float_built_in
);
697 if (m
->complex_float_built_in
!= END_BUILTINS
)
698 m
->complex4_decl
= builtin_decl_explicit (m
->complex_float_built_in
);
699 if (m
->double_built_in
!= END_BUILTINS
)
700 m
->real8_decl
= builtin_decl_explicit (m
->double_built_in
);
701 if (m
->complex_double_built_in
!= END_BUILTINS
)
702 m
->complex8_decl
= builtin_decl_explicit (m
->complex_double_built_in
);
704 /* If real(kind=10) exists, it is always long double. */
705 if (m
->long_double_built_in
!= END_BUILTINS
)
706 m
->real10_decl
= builtin_decl_explicit (m
->long_double_built_in
);
707 if (m
->complex_long_double_built_in
!= END_BUILTINS
)
709 = builtin_decl_explicit (m
->complex_long_double_built_in
);
711 if (!gfc_real16_is_float128
)
713 if (m
->long_double_built_in
!= END_BUILTINS
)
714 m
->real16_decl
= builtin_decl_explicit (m
->long_double_built_in
);
715 if (m
->complex_long_double_built_in
!= END_BUILTINS
)
717 = builtin_decl_explicit (m
->complex_long_double_built_in
);
719 else if (quad_decls
[m
->double_built_in
] != NULL_TREE
)
721 /* Quad-precision function calls are constructed when first
722 needed by builtin_decl_for_precision(), except for those
723 that will be used directly (define by OTHER_BUILTIN). */
724 m
->real16_decl
= quad_decls
[m
->double_built_in
];
726 else if (quad_decls
[m
->complex_double_built_in
] != NULL_TREE
)
728 /* Same thing for the complex ones. */
729 m
->complex16_decl
= quad_decls
[m
->double_built_in
];
735 /* Create a fndecl for a simple intrinsic library function. */
738 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t
* m
, gfc_expr
* expr
)
741 vec
<tree
, va_gc
> *argtypes
;
743 gfc_actual_arglist
*actual
;
746 char name
[GFC_MAX_SYMBOL_LEN
+ 3];
749 if (ts
->type
== BT_REAL
)
754 pdecl
= &m
->real4_decl
;
757 pdecl
= &m
->real8_decl
;
760 pdecl
= &m
->real10_decl
;
763 pdecl
= &m
->real16_decl
;
769 else if (ts
->type
== BT_COMPLEX
)
771 gcc_assert (m
->complex_available
);
776 pdecl
= &m
->complex4_decl
;
779 pdecl
= &m
->complex8_decl
;
782 pdecl
= &m
->complex10_decl
;
785 pdecl
= &m
->complex16_decl
;
799 int n
= gfc_validate_kind (BT_REAL
, ts
->kind
, false);
800 if (gfc_real_kinds
[n
].c_float
)
801 snprintf (name
, sizeof (name
), "%s%s%s",
802 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
, "f");
803 else if (gfc_real_kinds
[n
].c_double
)
804 snprintf (name
, sizeof (name
), "%s%s",
805 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
);
806 else if (gfc_real_kinds
[n
].c_long_double
)
807 snprintf (name
, sizeof (name
), "%s%s%s",
808 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
, "l");
809 else if (gfc_real_kinds
[n
].c_float128
)
810 snprintf (name
, sizeof (name
), "%s%s%s",
811 ts
->type
== BT_COMPLEX
? "c" : "", m
->name
, "q");
817 snprintf (name
, sizeof (name
), PREFIX ("%s_%c%d"), m
->name
,
818 ts
->type
== BT_COMPLEX
? 'c' : 'r',
823 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
825 type
= gfc_typenode_for_spec (&actual
->expr
->ts
);
826 vec_safe_push (argtypes
, type
);
828 type
= build_function_type_vec (gfc_typenode_for_spec (ts
), argtypes
);
829 fndecl
= build_decl (input_location
,
830 FUNCTION_DECL
, get_identifier (name
), type
);
832 /* Mark the decl as external. */
833 DECL_EXTERNAL (fndecl
) = 1;
834 TREE_PUBLIC (fndecl
) = 1;
836 /* Mark it __attribute__((const)), if possible. */
837 TREE_READONLY (fndecl
) = m
->is_constant
;
839 rest_of_decl_compilation (fndecl
, 1, 0);
846 /* Convert an intrinsic function into an external or builtin call. */
849 gfc_conv_intrinsic_lib_function (gfc_se
* se
, gfc_expr
* expr
)
851 gfc_intrinsic_map_t
*m
;
855 unsigned int num_args
;
858 id
= expr
->value
.function
.isym
->id
;
859 /* Find the entry for this function. */
860 for (m
= gfc_intrinsic_map
;
861 m
->id
!= GFC_ISYM_NONE
|| m
->double_built_in
!= END_BUILTINS
; m
++)
867 if (m
->id
== GFC_ISYM_NONE
)
869 gfc_internal_error ("Intrinsic function %qs (%d) not recognized",
870 expr
->value
.function
.name
, id
);
873 /* Get the decl and generate the call. */
874 num_args
= gfc_intrinsic_argument_list_length (expr
);
875 args
= XALLOCAVEC (tree
, num_args
);
877 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
878 fndecl
= gfc_get_intrinsic_lib_fndecl (m
, expr
);
879 rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
881 fndecl
= build_addr (fndecl
, current_function_decl
);
882 se
->expr
= build_call_array_loc (input_location
, rettype
, fndecl
, num_args
, args
);
886 /* If bounds-checking is enabled, create code to verify at runtime that the
887 string lengths for both expressions are the same (needed for e.g. MERGE).
888 If bounds-checking is not enabled, does nothing. */
891 gfc_trans_same_strlen_check (const char* intr_name
, locus
* where
,
892 tree a
, tree b
, stmtblock_t
* target
)
897 /* If bounds-checking is disabled, do nothing. */
898 if (!(gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
))
901 /* Compare the two string lengths. */
902 cond
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
, a
, b
);
904 /* Output the runtime-check. */
905 name
= gfc_build_cstring_const (intr_name
);
906 name
= gfc_build_addr_expr (pchar_type_node
, name
);
907 gfc_trans_runtime_check (true, false, cond
, target
, where
,
908 "Unequal character lengths (%ld/%ld) in %s",
909 fold_convert (long_integer_type_node
, a
),
910 fold_convert (long_integer_type_node
, b
), name
);
914 /* The EXPONENT(X) intrinsic function is translated into
916 return isfinite(X) ? (frexp (X, &ret) , ret) : huge
917 so that if X is a NaN or infinity, the result is HUGE(0).
921 gfc_conv_intrinsic_exponent (gfc_se
*se
, gfc_expr
*expr
)
923 tree arg
, type
, res
, tmp
, frexp
, cond
, huge
;
926 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
,
927 expr
->value
.function
.actual
->expr
->ts
.kind
);
929 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
930 arg
= gfc_evaluate_now (arg
, &se
->pre
);
932 i
= gfc_validate_kind (BT_INTEGER
, gfc_c_int_kind
, false);
933 huge
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].huge
, gfc_c_int_kind
);
934 cond
= build_call_expr_loc (input_location
,
935 builtin_decl_explicit (BUILT_IN_ISFINITE
),
938 res
= gfc_create_var (integer_type_node
, NULL
);
939 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
940 gfc_build_addr_expr (NULL_TREE
, res
));
941 tmp
= fold_build2_loc (input_location
, COMPOUND_EXPR
, integer_type_node
,
943 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
946 type
= gfc_typenode_for_spec (&expr
->ts
);
947 se
->expr
= fold_convert (type
, se
->expr
);
951 /* Fill in the following structure
952 struct caf_vector_t {
953 size_t nvec; // size of the vector
960 ptrdiff_t lower_bound;
961 ptrdiff_t upper_bound;
968 conv_caf_vector_subscript_elem (stmtblock_t
*block
, int i
, tree desc
,
969 tree lower
, tree upper
, tree stride
,
970 tree vector
, int kind
, tree nvec
)
972 tree field
, type
, tmp
;
974 desc
= gfc_build_array_ref (desc
, gfc_rank_cst
[i
], NULL_TREE
);
975 type
= TREE_TYPE (desc
);
977 field
= gfc_advance_chain (TYPE_FIELDS (type
), 0);
978 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
979 desc
, field
, NULL_TREE
);
980 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), nvec
));
983 field
= gfc_advance_chain (TYPE_FIELDS (type
), 1);
984 desc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
985 desc
, field
, NULL_TREE
);
986 type
= TREE_TYPE (desc
);
988 /* Access the inner struct. */
989 field
= gfc_advance_chain (TYPE_FIELDS (type
), vector
!= NULL_TREE
? 0 : 1);
990 desc
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
991 desc
, field
, NULL_TREE
);
992 type
= TREE_TYPE (desc
);
994 if (vector
!= NULL_TREE
)
996 /* Set dim.lower/upper/stride. */
997 field
= gfc_advance_chain (TYPE_FIELDS (type
), 0);
998 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
999 desc
, field
, NULL_TREE
);
1000 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), vector
));
1001 field
= gfc_advance_chain (TYPE_FIELDS (type
), 1);
1002 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1003 desc
, field
, NULL_TREE
);
1004 gfc_add_modify (block
, tmp
, build_int_cst (integer_type_node
, kind
));
1008 /* Set vector and kind. */
1009 field
= gfc_advance_chain (TYPE_FIELDS (type
), 0);
1010 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1011 desc
, field
, NULL_TREE
);
1012 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), lower
));
1014 field
= gfc_advance_chain (TYPE_FIELDS (type
), 1);
1015 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1016 desc
, field
, NULL_TREE
);
1017 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), upper
));
1019 field
= gfc_advance_chain (TYPE_FIELDS (type
), 2);
1020 tmp
= fold_build3_loc (input_location
, COMPONENT_REF
, TREE_TYPE (field
),
1021 desc
, field
, NULL_TREE
);
1022 gfc_add_modify (block
, tmp
, fold_convert (TREE_TYPE (field
), stride
));
1028 conv_caf_vector_subscript (stmtblock_t
*block
, tree desc
, gfc_array_ref
*ar
)
1031 tree var
, lower
, upper
= NULL_TREE
, stride
= NULL_TREE
, vector
, nvec
;
1032 tree lbound
, ubound
, tmp
;
1035 var
= gfc_create_var (gfc_get_caf_vector_type (ar
->dimen
), "vector");
1037 for (i
= 0; i
< ar
->dimen
; i
++)
1038 switch (ar
->dimen_type
[i
])
1043 gfc_init_se (&argse
, NULL
);
1044 gfc_conv_expr (&argse
, ar
->end
[i
]);
1045 gfc_add_block_to_block (block
, &argse
.pre
);
1046 upper
= gfc_evaluate_now (argse
.expr
, block
);
1049 upper
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[i
]);
1052 gfc_init_se (&argse
, NULL
);
1053 gfc_conv_expr (&argse
, ar
->stride
[i
]);
1054 gfc_add_block_to_block (block
, &argse
.pre
);
1055 stride
= gfc_evaluate_now (argse
.expr
, block
);
1058 stride
= gfc_index_one_node
;
1064 gfc_init_se (&argse
, NULL
);
1065 gfc_conv_expr (&argse
, ar
->start
[i
]);
1066 gfc_add_block_to_block (block
, &argse
.pre
);
1067 lower
= gfc_evaluate_now (argse
.expr
, block
);
1070 lower
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[i
]);
1071 if (ar
->dimen_type
[i
] == DIMEN_ELEMENT
)
1074 stride
= gfc_index_one_node
;
1077 nvec
= size_zero_node
;
1078 conv_caf_vector_subscript_elem (block
, i
, var
, lower
, upper
, stride
,
1083 gfc_init_se (&argse
, NULL
);
1084 argse
.descriptor_only
= 1;
1085 gfc_conv_expr_descriptor (&argse
, ar
->start
[i
]);
1086 gfc_add_block_to_block (block
, &argse
.pre
);
1087 vector
= argse
.expr
;
1088 lbound
= gfc_conv_descriptor_lbound_get (vector
, gfc_rank_cst
[0]);
1089 ubound
= gfc_conv_descriptor_ubound_get (vector
, gfc_rank_cst
[0]);
1090 nvec
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
1091 tmp
= gfc_conv_descriptor_stride_get (vector
, gfc_rank_cst
[0]);
1092 nvec
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
1093 TREE_TYPE (nvec
), nvec
, tmp
);
1094 lower
= gfc_index_zero_node
;
1095 upper
= gfc_index_zero_node
;
1096 stride
= gfc_index_zero_node
;
1097 vector
= gfc_conv_descriptor_data_get (vector
);
1098 conv_caf_vector_subscript_elem (block
, i
, var
, lower
, upper
, stride
,
1099 vector
, ar
->start
[i
]->ts
.kind
, nvec
);
1104 return gfc_build_addr_expr (NULL_TREE
, var
);
1108 /* Get data from a remote coarray. */
1111 gfc_conv_intrinsic_caf_get (gfc_se
*se
, gfc_expr
*expr
, tree lhs
, tree lhs_kind
,
1112 tree may_require_tmp
)
1114 gfc_expr
*array_expr
;
1116 tree caf_decl
, token
, offset
, image_index
, tmp
;
1117 tree res_var
, dst_var
, type
, kind
, vec
;
1119 gcc_assert (flag_coarray
== GFC_FCOARRAY_LIB
);
1121 if (se
->ss
&& se
->ss
->info
->useflags
)
1123 /* Access the previously obtained result. */
1124 gfc_conv_tmp_array_ref (se
);
1128 /* If lhs is set, the CAF_GET intrinsic has already been stripped. */
1129 array_expr
= (lhs
== NULL_TREE
) ? expr
->value
.function
.actual
->expr
: expr
;
1130 type
= gfc_typenode_for_spec (&array_expr
->ts
);
1135 vec
= null_pointer_node
;
1137 gfc_init_se (&argse
, NULL
);
1138 if (array_expr
->rank
== 0)
1140 symbol_attribute attr
;
1142 gfc_clear_attr (&attr
);
1143 gfc_conv_expr (&argse
, array_expr
);
1145 if (lhs
== NULL_TREE
)
1147 gfc_clear_attr (&attr
);
1148 if (array_expr
->ts
.type
== BT_CHARACTER
)
1149 res_var
= gfc_conv_string_tmp (se
, build_pointer_type (type
),
1150 argse
.string_length
);
1152 res_var
= gfc_create_var (type
, "caf_res");
1153 dst_var
= gfc_conv_scalar_to_descriptor (&argse
, res_var
, attr
);
1154 dst_var
= gfc_build_addr_expr (NULL_TREE
, dst_var
);
1156 argse
.expr
= gfc_conv_scalar_to_descriptor (&argse
, argse
.expr
, attr
);
1157 argse
.expr
= gfc_build_addr_expr (NULL_TREE
, argse
.expr
);
1161 /* If has_vector, pass descriptor for whole array and the
1162 vector bounds separately. */
1163 gfc_array_ref
*ar
, ar2
;
1164 bool has_vector
= false;
1166 if (gfc_is_coindexed (expr
) && gfc_has_vector_subscript (expr
))
1169 ar
= gfc_find_array_ref (expr
);
1171 memset (ar
, '\0', sizeof (*ar
));
1175 gfc_conv_expr_descriptor (&argse
, array_expr
);
1176 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1177 has the wrong type if component references are done. */
1178 gfc_add_modify (&argse
.pre
, gfc_conv_descriptor_dtype (argse
.expr
),
1179 gfc_get_dtype_rank_type (has_vector
? ar2
.dimen
1184 vec
= conv_caf_vector_subscript (&argse
.pre
, argse
.expr
, &ar2
);
1188 if (lhs
== NULL_TREE
)
1190 /* Create temporary. */
1191 for (int n
= 0; n
< se
->ss
->loop
->dimen
; n
++)
1192 if (se
->loop
->to
[n
] == NULL_TREE
)
1195 gfc_conv_descriptor_lbound_get (argse
.expr
, gfc_rank_cst
[n
]);
1197 gfc_conv_descriptor_ubound_get (argse
.expr
, gfc_rank_cst
[n
]);
1199 gfc_trans_create_temp_array (&argse
.pre
, &argse
.post
, se
->ss
, type
,
1200 NULL_TREE
, false, true, false,
1201 &array_expr
->where
);
1202 res_var
= se
->ss
->info
->data
.array
.descriptor
;
1203 dst_var
= gfc_build_addr_expr (NULL_TREE
, res_var
);
1205 argse
.expr
= gfc_build_addr_expr (NULL_TREE
, argse
.expr
);
1208 kind
= build_int_cst (integer_type_node
, expr
->ts
.kind
);
1209 if (lhs_kind
== NULL_TREE
)
1212 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1213 gfc_add_block_to_block (&se
->post
, &argse
.post
);
1215 caf_decl
= gfc_get_tree_for_caf_expr (array_expr
);
1216 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
1217 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
1218 image_index
= gfc_caf_get_image_index (&se
->pre
, array_expr
, caf_decl
);
1219 gfc_get_caf_token_offset (&token
, &offset
, caf_decl
, argse
.expr
, array_expr
);
1221 /* No overlap possible as we have generated a temporary. */
1222 if (lhs
== NULL_TREE
)
1223 may_require_tmp
= boolean_false_node
;
1225 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_get
, 9,
1226 token
, offset
, image_index
, argse
.expr
, vec
,
1227 dst_var
, kind
, lhs_kind
, may_require_tmp
);
1228 gfc_add_expr_to_block (&se
->pre
, tmp
);
1231 gfc_advance_se_ss_chain (se
);
1234 if (array_expr
->ts
.type
== BT_CHARACTER
)
1235 se
->string_length
= argse
.string_length
;
1239 /* Send data to a remove coarray. */
1242 conv_caf_send (gfc_code
*code
) {
1243 gfc_expr
*lhs_expr
, *rhs_expr
;
1244 gfc_se lhs_se
, rhs_se
;
1246 tree caf_decl
, token
, offset
, image_index
, tmp
, lhs_kind
, rhs_kind
;
1247 tree may_require_tmp
;
1248 tree lhs_type
= NULL_TREE
;
1249 tree vec
= null_pointer_node
, rhs_vec
= null_pointer_node
;
1251 gcc_assert (flag_coarray
== GFC_FCOARRAY_LIB
);
1253 lhs_expr
= code
->ext
.actual
->expr
;
1254 rhs_expr
= code
->ext
.actual
->next
->expr
;
1255 may_require_tmp
= gfc_check_dependency (lhs_expr
, rhs_expr
, false) == 0
1256 ? boolean_false_node
: boolean_true_node
;
1257 gfc_init_block (&block
);
1260 gfc_init_se (&lhs_se
, NULL
);
1261 if (lhs_expr
->rank
== 0)
1263 symbol_attribute attr
;
1264 gfc_clear_attr (&attr
);
1265 gfc_conv_expr (&lhs_se
, lhs_expr
);
1266 lhs_type
= TREE_TYPE (lhs_se
.expr
);
1267 lhs_se
.expr
= gfc_conv_scalar_to_descriptor (&lhs_se
, lhs_se
.expr
, attr
);
1268 lhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, lhs_se
.expr
);
1272 /* If has_vector, pass descriptor for whole array and the
1273 vector bounds separately. */
1274 gfc_array_ref
*ar
, ar2
;
1275 bool has_vector
= false;
1277 if (gfc_is_coindexed (lhs_expr
) && gfc_has_vector_subscript (lhs_expr
))
1280 ar
= gfc_find_array_ref (lhs_expr
);
1282 memset (ar
, '\0', sizeof (*ar
));
1286 lhs_se
.want_pointer
= 1;
1287 gfc_conv_expr_descriptor (&lhs_se
, lhs_expr
);
1288 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1289 has the wrong type if component references are done. */
1290 lhs_type
= gfc_typenode_for_spec (&lhs_expr
->ts
);
1291 tmp
= build_fold_indirect_ref_loc (input_location
, lhs_se
.expr
);
1292 gfc_add_modify (&lhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
1293 gfc_get_dtype_rank_type (has_vector
? ar2
.dimen
1298 vec
= conv_caf_vector_subscript (&block
, lhs_se
.expr
, &ar2
);
1303 lhs_kind
= build_int_cst (integer_type_node
, lhs_expr
->ts
.kind
);
1304 gfc_add_block_to_block (&block
, &lhs_se
.pre
);
1306 /* Special case: RHS is a coarray but LHS is not; this code path avoids a
1307 temporary and a loop. */
1308 if (!gfc_is_coindexed (lhs_expr
))
1310 gcc_assert (gfc_is_coindexed (rhs_expr
));
1311 gfc_init_se (&rhs_se
, NULL
);
1312 gfc_conv_intrinsic_caf_get (&rhs_se
, rhs_expr
, lhs_se
.expr
, lhs_kind
,
1314 gfc_add_block_to_block (&block
, &rhs_se
.pre
);
1315 gfc_add_block_to_block (&block
, &rhs_se
.post
);
1316 gfc_add_block_to_block (&block
, &lhs_se
.post
);
1317 return gfc_finish_block (&block
);
1320 /* Obtain token, offset and image index for the LHS. */
1322 caf_decl
= gfc_get_tree_for_caf_expr (lhs_expr
);
1323 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
1324 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
1325 image_index
= gfc_caf_get_image_index (&block
, lhs_expr
, caf_decl
);
1326 gfc_get_caf_token_offset (&token
, &offset
, caf_decl
, lhs_se
.expr
, lhs_expr
);
1329 gfc_init_se (&rhs_se
, NULL
);
1330 if (rhs_expr
->expr_type
== EXPR_FUNCTION
&& rhs_expr
->value
.function
.isym
1331 && rhs_expr
->value
.function
.isym
->id
== GFC_ISYM_CONVERSION
)
1332 rhs_expr
= rhs_expr
->value
.function
.actual
->expr
;
1333 if (rhs_expr
->rank
== 0)
1335 symbol_attribute attr
;
1336 gfc_clear_attr (&attr
);
1337 gfc_conv_expr (&rhs_se
, rhs_expr
);
1338 if (!gfc_is_coindexed (rhs_expr
) && rhs_expr
->ts
.type
!= BT_CHARACTER
)
1339 rhs_se
.expr
= fold_convert (lhs_type
, rhs_se
.expr
);
1340 rhs_se
.expr
= gfc_conv_scalar_to_descriptor (&rhs_se
, rhs_se
.expr
, attr
);
1341 rhs_se
.expr
= gfc_build_addr_expr (NULL_TREE
, rhs_se
.expr
);
1345 /* If has_vector, pass descriptor for whole array and the
1346 vector bounds separately. */
1347 gfc_array_ref
*ar
, ar2
;
1348 bool has_vector
= false;
1351 if (gfc_is_coindexed (rhs_expr
) && gfc_has_vector_subscript (rhs_expr
))
1354 ar
= gfc_find_array_ref (rhs_expr
);
1356 memset (ar
, '\0', sizeof (*ar
));
1360 rhs_se
.want_pointer
= 1;
1361 gfc_conv_expr_descriptor (&rhs_se
, rhs_expr
);
1362 /* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
1363 has the wrong type if component references are done. */
1364 tmp
= build_fold_indirect_ref_loc (input_location
, rhs_se
.expr
);
1365 tmp2
= gfc_typenode_for_spec (&rhs_expr
->ts
);
1366 gfc_add_modify (&rhs_se
.pre
, gfc_conv_descriptor_dtype (tmp
),
1367 gfc_get_dtype_rank_type (has_vector
? ar2
.dimen
1372 rhs_vec
= conv_caf_vector_subscript (&block
, rhs_se
.expr
, &ar2
);
1377 gfc_add_block_to_block (&block
, &rhs_se
.pre
);
1379 rhs_kind
= build_int_cst (integer_type_node
, rhs_expr
->ts
.kind
);
1381 if (!gfc_is_coindexed (rhs_expr
))
1382 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_send
, 9, token
,
1383 offset
, image_index
, lhs_se
.expr
, vec
,
1384 rhs_se
.expr
, lhs_kind
, rhs_kind
, may_require_tmp
);
1387 tree rhs_token
, rhs_offset
, rhs_image_index
;
1389 caf_decl
= gfc_get_tree_for_caf_expr (rhs_expr
);
1390 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
1391 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
1392 rhs_image_index
= gfc_caf_get_image_index (&block
, rhs_expr
, caf_decl
);
1393 gfc_get_caf_token_offset (&rhs_token
, &rhs_offset
, caf_decl
, rhs_se
.expr
,
1395 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_sendget
, 13,
1396 token
, offset
, image_index
, lhs_se
.expr
, vec
,
1397 rhs_token
, rhs_offset
, rhs_image_index
,
1398 rhs_se
.expr
, rhs_vec
, lhs_kind
, rhs_kind
,
1401 gfc_add_expr_to_block (&block
, tmp
);
1402 gfc_add_block_to_block (&block
, &lhs_se
.post
);
1403 gfc_add_block_to_block (&block
, &rhs_se
.post
);
1404 return gfc_finish_block (&block
);
1409 trans_this_image (gfc_se
* se
, gfc_expr
*expr
)
1412 tree type
, desc
, dim_arg
, cond
, tmp
, m
, loop_var
, exit_label
, min_var
,
1413 lbound
, ubound
, extent
, ml
;
1416 gfc_expr
*distance
= expr
->value
.function
.actual
->next
->next
->expr
;
1418 if (expr
->value
.function
.actual
->expr
1419 && !gfc_is_coarray (expr
->value
.function
.actual
->expr
))
1420 distance
= expr
->value
.function
.actual
->expr
;
1422 /* The case -fcoarray=single is handled elsewhere. */
1423 gcc_assert (flag_coarray
!= GFC_FCOARRAY_SINGLE
);
1425 /* Argument-free version: THIS_IMAGE(). */
1426 if (distance
|| expr
->value
.function
.actual
->expr
== NULL
)
1430 gfc_init_se (&argse
, NULL
);
1431 gfc_conv_expr_val (&argse
, distance
);
1432 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1433 gfc_add_block_to_block (&se
->post
, &argse
.post
);
1434 tmp
= fold_convert (integer_type_node
, argse
.expr
);
1437 tmp
= integer_zero_node
;
1438 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_this_image
, 1,
1440 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
),
1445 /* Coarray-argument version: THIS_IMAGE(coarray [, dim]). */
1447 type
= gfc_get_int_type (gfc_default_integer_kind
);
1448 corank
= gfc_get_corank (expr
->value
.function
.actual
->expr
);
1449 rank
= expr
->value
.function
.actual
->expr
->rank
;
1451 /* Obtain the descriptor of the COARRAY. */
1452 gfc_init_se (&argse
, NULL
);
1453 argse
.want_coarray
= 1;
1454 gfc_conv_expr_descriptor (&argse
, expr
->value
.function
.actual
->expr
);
1455 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1456 gfc_add_block_to_block (&se
->post
, &argse
.post
);
1461 /* Create an implicit second parameter from the loop variable. */
1462 gcc_assert (!expr
->value
.function
.actual
->next
->expr
);
1463 gcc_assert (corank
> 0);
1464 gcc_assert (se
->loop
->dimen
== 1);
1465 gcc_assert (se
->ss
->info
->expr
== expr
);
1467 dim_arg
= se
->loop
->loopvar
[0];
1468 dim_arg
= fold_build2_loc (input_location
, PLUS_EXPR
,
1469 gfc_array_index_type
, dim_arg
,
1470 build_int_cst (TREE_TYPE (dim_arg
), 1));
1471 gfc_advance_se_ss_chain (se
);
1475 /* Use the passed DIM= argument. */
1476 gcc_assert (expr
->value
.function
.actual
->next
->expr
);
1477 gfc_init_se (&argse
, NULL
);
1478 gfc_conv_expr_type (&argse
, expr
->value
.function
.actual
->next
->expr
,
1479 gfc_array_index_type
);
1480 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1481 dim_arg
= argse
.expr
;
1483 if (INTEGER_CST_P (dim_arg
))
1485 if (wi::ltu_p (dim_arg
, 1)
1486 || wi::gtu_p (dim_arg
, GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))))
1487 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
1488 "dimension index", expr
->value
.function
.isym
->name
,
1491 else if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
1493 dim_arg
= gfc_evaluate_now (dim_arg
, &se
->pre
);
1494 cond
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
1496 build_int_cst (TREE_TYPE (dim_arg
), 1));
1497 tmp
= gfc_rank_cst
[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))];
1498 tmp
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
1500 cond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
1501 boolean_type_node
, cond
, tmp
);
1502 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
1507 /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer,
1508 one always has a dim_arg argument.
1510 m = this_image() - 1
1513 sub(1) = m + lcobound(corank)
1517 min_var = min (rank + corank - 2, rank + dim_arg - 1)
1520 extent = gfc_extent(i)
1528 sub(dim_arg) = (dim_arg < corank) ? ml - m*extent + lcobound(dim_arg)
1529 : m + lcobound(corank)
1532 /* this_image () - 1. */
1533 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_this_image
, 1,
1535 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, type
,
1536 fold_convert (type
, tmp
), build_int_cst (type
, 1));
1539 /* sub(1) = m + lcobound(corank). */
1540 lbound
= gfc_conv_descriptor_lbound_get (desc
,
1541 build_int_cst (TREE_TYPE (gfc_array_index_type
),
1543 lbound
= fold_convert (type
, lbound
);
1544 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, tmp
, lbound
);
1550 m
= gfc_create_var (type
, NULL
);
1551 ml
= gfc_create_var (type
, NULL
);
1552 loop_var
= gfc_create_var (integer_type_node
, NULL
);
1553 min_var
= gfc_create_var (integer_type_node
, NULL
);
1555 /* m = this_image () - 1. */
1556 gfc_add_modify (&se
->pre
, m
, tmp
);
1558 /* min_var = min (rank + corank-2, rank + dim_arg - 1). */
1559 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, integer_type_node
,
1560 fold_convert (integer_type_node
, dim_arg
),
1561 build_int_cst (integer_type_node
, rank
- 1));
1562 tmp
= fold_build2_loc (input_location
, MIN_EXPR
, integer_type_node
,
1563 build_int_cst (integer_type_node
, rank
+ corank
- 2),
1565 gfc_add_modify (&se
->pre
, min_var
, tmp
);
1568 tmp
= build_int_cst (integer_type_node
, rank
);
1569 gfc_add_modify (&se
->pre
, loop_var
, tmp
);
1571 exit_label
= gfc_build_label_decl (NULL_TREE
);
1572 TREE_USED (exit_label
) = 1;
1575 gfc_init_block (&loop
);
1578 gfc_add_modify (&loop
, ml
, m
);
1581 lbound
= gfc_conv_descriptor_lbound_get (desc
, loop_var
);
1582 ubound
= gfc_conv_descriptor_ubound_get (desc
, loop_var
);
1583 extent
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
1584 extent
= fold_convert (type
, extent
);
1587 gfc_add_modify (&loop
, m
,
1588 fold_build2_loc (input_location
, TRUNC_DIV_EXPR
, type
,
1591 /* Exit condition: if (i >= min_var) goto exit_label. */
1592 cond
= fold_build2_loc (input_location
, GE_EXPR
, boolean_type_node
, loop_var
,
1594 tmp
= build1_v (GOTO_EXPR
, exit_label
);
1595 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
, tmp
,
1596 build_empty_stmt (input_location
));
1597 gfc_add_expr_to_block (&loop
, tmp
);
1599 /* Increment loop variable: i++. */
1600 gfc_add_modify (&loop
, loop_var
,
1601 fold_build2_loc (input_location
, PLUS_EXPR
, integer_type_node
,
1603 build_int_cst (integer_type_node
, 1)));
1605 /* Making the loop... actually loop! */
1606 tmp
= gfc_finish_block (&loop
);
1607 tmp
= build1_v (LOOP_EXPR
, tmp
);
1608 gfc_add_expr_to_block (&se
->pre
, tmp
);
1610 /* The exit label. */
1611 tmp
= build1_v (LABEL_EXPR
, exit_label
);
1612 gfc_add_expr_to_block (&se
->pre
, tmp
);
1614 /* sub(co_dim) = (co_dim < corank) ? ml - m*extent + lcobound(dim_arg)
1615 : m + lcobound(corank) */
1617 cond
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
, dim_arg
,
1618 build_int_cst (TREE_TYPE (dim_arg
), corank
));
1620 lbound
= gfc_conv_descriptor_lbound_get (desc
,
1621 fold_build2_loc (input_location
, PLUS_EXPR
,
1622 gfc_array_index_type
, dim_arg
,
1623 build_int_cst (TREE_TYPE (dim_arg
), rank
-1)));
1624 lbound
= fold_convert (type
, lbound
);
1626 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, type
, ml
,
1627 fold_build2_loc (input_location
, MULT_EXPR
, type
,
1629 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, tmp
, lbound
);
1631 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
, tmp
,
1632 fold_build2_loc (input_location
, PLUS_EXPR
, type
,
1638 trans_image_index (gfc_se
* se
, gfc_expr
*expr
)
1640 tree num_images
, cond
, coindex
, type
, lbound
, ubound
, desc
, subdesc
,
1642 gfc_se argse
, subse
;
1643 int rank
, corank
, codim
;
1645 type
= gfc_get_int_type (gfc_default_integer_kind
);
1646 corank
= gfc_get_corank (expr
->value
.function
.actual
->expr
);
1647 rank
= expr
->value
.function
.actual
->expr
->rank
;
1649 /* Obtain the descriptor of the COARRAY. */
1650 gfc_init_se (&argse
, NULL
);
1651 argse
.want_coarray
= 1;
1652 gfc_conv_expr_descriptor (&argse
, expr
->value
.function
.actual
->expr
);
1653 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1654 gfc_add_block_to_block (&se
->post
, &argse
.post
);
1657 /* Obtain a handle to the SUB argument. */
1658 gfc_init_se (&subse
, NULL
);
1659 gfc_conv_expr_descriptor (&subse
, expr
->value
.function
.actual
->next
->expr
);
1660 gfc_add_block_to_block (&se
->pre
, &subse
.pre
);
1661 gfc_add_block_to_block (&se
->post
, &subse
.post
);
1662 subdesc
= build_fold_indirect_ref_loc (input_location
,
1663 gfc_conv_descriptor_data_get (subse
.expr
));
1665 /* Fortran 2008 does not require that the values remain in the cobounds,
1666 thus we need explicitly check this - and return 0 if they are exceeded. */
1668 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[rank
+corank
-1]);
1669 tmp
= gfc_build_array_ref (subdesc
, gfc_rank_cst
[corank
-1], NULL
);
1670 invalid_bound
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
1671 fold_convert (gfc_array_index_type
, tmp
),
1674 for (codim
= corank
+ rank
- 2; codim
>= rank
; codim
--)
1676 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[codim
]);
1677 ubound
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[codim
]);
1678 tmp
= gfc_build_array_ref (subdesc
, gfc_rank_cst
[codim
-rank
], NULL
);
1679 cond
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
1680 fold_convert (gfc_array_index_type
, tmp
),
1682 invalid_bound
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
1683 boolean_type_node
, invalid_bound
, cond
);
1684 cond
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
1685 fold_convert (gfc_array_index_type
, tmp
),
1687 invalid_bound
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
1688 boolean_type_node
, invalid_bound
, cond
);
1691 invalid_bound
= gfc_unlikely (invalid_bound
, PRED_FORTRAN_INVALID_BOUND
);
1693 /* See Fortran 2008, C.10 for the following algorithm. */
1695 /* coindex = sub(corank) - lcobound(n). */
1696 coindex
= fold_convert (gfc_array_index_type
,
1697 gfc_build_array_ref (subdesc
, gfc_rank_cst
[corank
-1],
1699 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[rank
+corank
-1]);
1700 coindex
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
1701 fold_convert (gfc_array_index_type
, coindex
),
1704 for (codim
= corank
+ rank
- 2; codim
>= rank
; codim
--)
1706 tree extent
, ubound
;
1708 /* coindex = coindex*extent(codim) + sub(codim) - lcobound(codim). */
1709 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[codim
]);
1710 ubound
= gfc_conv_descriptor_ubound_get (desc
, gfc_rank_cst
[codim
]);
1711 extent
= gfc_conv_array_extent_dim (lbound
, ubound
, NULL
);
1713 /* coindex *= extent. */
1714 coindex
= fold_build2_loc (input_location
, MULT_EXPR
,
1715 gfc_array_index_type
, coindex
, extent
);
1717 /* coindex += sub(codim). */
1718 tmp
= gfc_build_array_ref (subdesc
, gfc_rank_cst
[codim
-rank
], NULL
);
1719 coindex
= fold_build2_loc (input_location
, PLUS_EXPR
,
1720 gfc_array_index_type
, coindex
,
1721 fold_convert (gfc_array_index_type
, tmp
));
1723 /* coindex -= lbound(codim). */
1724 lbound
= gfc_conv_descriptor_lbound_get (desc
, gfc_rank_cst
[codim
]);
1725 coindex
= fold_build2_loc (input_location
, MINUS_EXPR
,
1726 gfc_array_index_type
, coindex
, lbound
);
1729 coindex
= fold_build2_loc (input_location
, PLUS_EXPR
, type
,
1730 fold_convert(type
, coindex
),
1731 build_int_cst (type
, 1));
1733 /* Return 0 if "coindex" exceeds num_images(). */
1735 if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
1736 num_images
= build_int_cst (type
, 1);
1739 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
, 2,
1741 build_int_cst (integer_type_node
, -1));
1742 num_images
= fold_convert (type
, tmp
);
1745 tmp
= gfc_create_var (type
, NULL
);
1746 gfc_add_modify (&se
->pre
, tmp
, coindex
);
1748 cond
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
, tmp
,
1750 cond
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
, boolean_type_node
,
1752 fold_convert (boolean_type_node
, invalid_bound
));
1753 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
1754 build_int_cst (type
, 0), tmp
);
1759 trans_num_images (gfc_se
* se
, gfc_expr
*expr
)
1761 tree tmp
, distance
, failed
;
1764 if (expr
->value
.function
.actual
->expr
)
1766 gfc_init_se (&argse
, NULL
);
1767 gfc_conv_expr_val (&argse
, expr
->value
.function
.actual
->expr
);
1768 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1769 gfc_add_block_to_block (&se
->post
, &argse
.post
);
1770 distance
= fold_convert (integer_type_node
, argse
.expr
);
1773 distance
= integer_zero_node
;
1775 if (expr
->value
.function
.actual
->next
->expr
)
1777 gfc_init_se (&argse
, NULL
);
1778 gfc_conv_expr_val (&argse
, expr
->value
.function
.actual
->next
->expr
);
1779 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1780 gfc_add_block_to_block (&se
->post
, &argse
.post
);
1781 failed
= fold_convert (integer_type_node
, argse
.expr
);
1784 failed
= build_int_cst (integer_type_node
, -1);
1786 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
, 2,
1788 se
->expr
= fold_convert (gfc_get_int_type (gfc_default_integer_kind
), tmp
);
1793 gfc_conv_intrinsic_rank (gfc_se
*se
, gfc_expr
*expr
)
1797 gfc_init_se (&argse
, NULL
);
1798 argse
.data_not_needed
= 1;
1799 argse
.descriptor_only
= 1;
1801 gfc_conv_expr_descriptor (&argse
, expr
->value
.function
.actual
->expr
);
1802 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1803 gfc_add_block_to_block (&se
->post
, &argse
.post
);
1805 se
->expr
= gfc_conv_descriptor_rank (argse
.expr
);
1809 /* Evaluate a single upper or lower bound. */
1810 /* TODO: bound intrinsic generates way too much unnecessary code. */
1813 gfc_conv_intrinsic_bound (gfc_se
* se
, gfc_expr
* expr
, int upper
)
1815 gfc_actual_arglist
*arg
;
1816 gfc_actual_arglist
*arg2
;
1821 tree cond
, cond1
, cond3
, cond4
, size
;
1825 gfc_array_spec
* as
;
1826 bool assumed_rank_lb_one
;
1828 arg
= expr
->value
.function
.actual
;
1833 /* Create an implicit second parameter from the loop variable. */
1834 gcc_assert (!arg2
->expr
);
1835 gcc_assert (se
->loop
->dimen
== 1);
1836 gcc_assert (se
->ss
->info
->expr
== expr
);
1837 gfc_advance_se_ss_chain (se
);
1838 bound
= se
->loop
->loopvar
[0];
1839 bound
= fold_build2_loc (input_location
, MINUS_EXPR
,
1840 gfc_array_index_type
, bound
,
1845 /* use the passed argument. */
1846 gcc_assert (arg2
->expr
);
1847 gfc_init_se (&argse
, NULL
);
1848 gfc_conv_expr_type (&argse
, arg2
->expr
, gfc_array_index_type
);
1849 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1851 /* Convert from one based to zero based. */
1852 bound
= fold_build2_loc (input_location
, MINUS_EXPR
,
1853 gfc_array_index_type
, bound
,
1854 gfc_index_one_node
);
1857 /* TODO: don't re-evaluate the descriptor on each iteration. */
1858 /* Get a descriptor for the first parameter. */
1859 gfc_init_se (&argse
, NULL
);
1860 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
1861 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
1862 gfc_add_block_to_block (&se
->post
, &argse
.post
);
1866 as
= gfc_get_full_arrayspec_from_expr (arg
->expr
);
1868 if (INTEGER_CST_P (bound
))
1870 if (((!as
|| as
->type
!= AS_ASSUMED_RANK
)
1871 && wi::geu_p (bound
, GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc
))))
1872 || wi::gtu_p (bound
, GFC_MAX_DIMENSIONS
))
1873 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
1874 "dimension index", upper
? "UBOUND" : "LBOUND",
1878 if (!INTEGER_CST_P (bound
) || (as
&& as
->type
== AS_ASSUMED_RANK
))
1880 if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
1882 bound
= gfc_evaluate_now (bound
, &se
->pre
);
1883 cond
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
1884 bound
, build_int_cst (TREE_TYPE (bound
), 0));
1885 if (as
&& as
->type
== AS_ASSUMED_RANK
)
1886 tmp
= gfc_conv_descriptor_rank (desc
);
1888 tmp
= gfc_rank_cst
[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc
))];
1889 tmp
= fold_build2_loc (input_location
, GE_EXPR
, boolean_type_node
,
1890 bound
, fold_convert(TREE_TYPE (bound
), tmp
));
1891 cond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
1892 boolean_type_node
, cond
, tmp
);
1893 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
1898 /* Take care of the lbound shift for assumed-rank arrays, which are
1899 nonallocatable and nonpointers. Those has a lbound of 1. */
1900 assumed_rank_lb_one
= as
&& as
->type
== AS_ASSUMED_RANK
1901 && ((arg
->expr
->ts
.type
!= BT_CLASS
1902 && !arg
->expr
->symtree
->n
.sym
->attr
.allocatable
1903 && !arg
->expr
->symtree
->n
.sym
->attr
.pointer
)
1904 || (arg
->expr
->ts
.type
== BT_CLASS
1905 && !CLASS_DATA (arg
->expr
)->attr
.allocatable
1906 && !CLASS_DATA (arg
->expr
)->attr
.class_pointer
));
1908 ubound
= gfc_conv_descriptor_ubound_get (desc
, bound
);
1909 lbound
= gfc_conv_descriptor_lbound_get (desc
, bound
);
1911 /* 13.14.53: Result value for LBOUND
1913 Case (i): For an array section or for an array expression other than a
1914 whole array or array structure component, LBOUND(ARRAY, DIM)
1915 has the value 1. For a whole array or array structure
1916 component, LBOUND(ARRAY, DIM) has the value:
1917 (a) equal to the lower bound for subscript DIM of ARRAY if
1918 dimension DIM of ARRAY does not have extent zero
1919 or if ARRAY is an assumed-size array of rank DIM,
1922 13.14.113: Result value for UBOUND
1924 Case (i): For an array section or for an array expression other than a
1925 whole array or array structure component, UBOUND(ARRAY, DIM)
1926 has the value equal to the number of elements in the given
1927 dimension; otherwise, it has a value equal to the upper bound
1928 for subscript DIM of ARRAY if dimension DIM of ARRAY does
1929 not have size zero and has value zero if dimension DIM has
1932 if (!upper
&& assumed_rank_lb_one
)
1933 se
->expr
= gfc_index_one_node
;
1936 tree stride
= gfc_conv_descriptor_stride_get (desc
, bound
);
1938 cond1
= fold_build2_loc (input_location
, GE_EXPR
, boolean_type_node
,
1940 cond3
= fold_build2_loc (input_location
, GE_EXPR
, boolean_type_node
,
1941 stride
, gfc_index_zero_node
);
1942 cond3
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
1943 boolean_type_node
, cond3
, cond1
);
1944 cond4
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
1945 stride
, gfc_index_zero_node
);
1950 cond
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
1951 boolean_type_node
, cond3
, cond4
);
1952 cond5
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
1953 gfc_index_one_node
, lbound
);
1954 cond5
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
1955 boolean_type_node
, cond4
, cond5
);
1957 cond
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
1958 boolean_type_node
, cond
, cond5
);
1960 if (assumed_rank_lb_one
)
1962 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
1963 gfc_array_index_type
, ubound
, lbound
);
1964 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
1965 gfc_array_index_type
, tmp
, gfc_index_one_node
);
1970 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
1971 gfc_array_index_type
, cond
,
1972 tmp
, gfc_index_zero_node
);
1976 if (as
->type
== AS_ASSUMED_SIZE
)
1977 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
1978 bound
, build_int_cst (TREE_TYPE (bound
),
1979 arg
->expr
->rank
- 1));
1981 cond
= boolean_false_node
;
1983 cond1
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
1984 boolean_type_node
, cond3
, cond4
);
1985 cond
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
1986 boolean_type_node
, cond
, cond1
);
1988 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
1989 gfc_array_index_type
, cond
,
1990 lbound
, gfc_index_one_node
);
1997 size
= fold_build2_loc (input_location
, MINUS_EXPR
,
1998 gfc_array_index_type
, ubound
, lbound
);
1999 se
->expr
= fold_build2_loc (input_location
, PLUS_EXPR
,
2000 gfc_array_index_type
, size
,
2001 gfc_index_one_node
);
2002 se
->expr
= fold_build2_loc (input_location
, MAX_EXPR
,
2003 gfc_array_index_type
, se
->expr
,
2004 gfc_index_zero_node
);
2007 se
->expr
= gfc_index_one_node
;
2010 type
= gfc_typenode_for_spec (&expr
->ts
);
2011 se
->expr
= convert (type
, se
->expr
);
2016 conv_intrinsic_cobound (gfc_se
* se
, gfc_expr
* expr
)
2018 gfc_actual_arglist
*arg
;
2019 gfc_actual_arglist
*arg2
;
2021 tree bound
, resbound
, resbound2
, desc
, cond
, tmp
;
2025 gcc_assert (expr
->value
.function
.isym
->id
== GFC_ISYM_LCOBOUND
2026 || expr
->value
.function
.isym
->id
== GFC_ISYM_UCOBOUND
2027 || expr
->value
.function
.isym
->id
== GFC_ISYM_THIS_IMAGE
);
2029 arg
= expr
->value
.function
.actual
;
2032 gcc_assert (arg
->expr
->expr_type
== EXPR_VARIABLE
);
2033 corank
= gfc_get_corank (arg
->expr
);
2035 gfc_init_se (&argse
, NULL
);
2036 argse
.want_coarray
= 1;
2038 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
2039 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2040 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2045 /* Create an implicit second parameter from the loop variable. */
2046 gcc_assert (!arg2
->expr
);
2047 gcc_assert (corank
> 0);
2048 gcc_assert (se
->loop
->dimen
== 1);
2049 gcc_assert (se
->ss
->info
->expr
== expr
);
2051 bound
= se
->loop
->loopvar
[0];
2052 bound
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
2053 bound
, gfc_rank_cst
[arg
->expr
->rank
]);
2054 gfc_advance_se_ss_chain (se
);
2058 /* use the passed argument. */
2059 gcc_assert (arg2
->expr
);
2060 gfc_init_se (&argse
, NULL
);
2061 gfc_conv_expr_type (&argse
, arg2
->expr
, gfc_array_index_type
);
2062 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2065 if (INTEGER_CST_P (bound
))
2067 if (wi::ltu_p (bound
, 1)
2068 || wi::gtu_p (bound
, GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))))
2069 gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid "
2070 "dimension index", expr
->value
.function
.isym
->name
,
2073 else if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
2075 bound
= gfc_evaluate_now (bound
, &se
->pre
);
2076 cond
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
2077 bound
, build_int_cst (TREE_TYPE (bound
), 1));
2078 tmp
= gfc_rank_cst
[GFC_TYPE_ARRAY_CORANK (TREE_TYPE (desc
))];
2079 tmp
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
2081 cond
= fold_build2_loc (input_location
, TRUTH_ORIF_EXPR
,
2082 boolean_type_node
, cond
, tmp
);
2083 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
2088 /* Subtract 1 to get to zero based and add dimensions. */
2089 switch (arg
->expr
->rank
)
2092 bound
= fold_build2_loc (input_location
, MINUS_EXPR
,
2093 gfc_array_index_type
, bound
,
2094 gfc_index_one_node
);
2098 bound
= fold_build2_loc (input_location
, PLUS_EXPR
,
2099 gfc_array_index_type
, bound
,
2100 gfc_rank_cst
[arg
->expr
->rank
- 1]);
2104 resbound
= gfc_conv_descriptor_lbound_get (desc
, bound
);
2106 /* Handle UCOBOUND with special handling of the last codimension. */
2107 if (expr
->value
.function
.isym
->id
== GFC_ISYM_UCOBOUND
)
2109 /* Last codimension: For -fcoarray=single just return
2110 the lcobound - otherwise add
2111 ceiling (real (num_images ()) / real (size)) - 1
2112 = (num_images () + size - 1) / size - 1
2113 = (num_images - 1) / size(),
2114 where size is the product of the extent of all but the last
2117 if (flag_coarray
!= GFC_FCOARRAY_SINGLE
&& corank
> 1)
2121 cosize
= gfc_conv_descriptor_cosize (desc
, arg
->expr
->rank
, corank
);
2122 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
,
2123 2, integer_zero_node
,
2124 build_int_cst (integer_type_node
, -1));
2125 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
2126 gfc_array_index_type
,
2127 fold_convert (gfc_array_index_type
, tmp
),
2128 build_int_cst (gfc_array_index_type
, 1));
2129 tmp
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
,
2130 gfc_array_index_type
, tmp
,
2131 fold_convert (gfc_array_index_type
, cosize
));
2132 resbound
= fold_build2_loc (input_location
, PLUS_EXPR
,
2133 gfc_array_index_type
, resbound
, tmp
);
2135 else if (flag_coarray
!= GFC_FCOARRAY_SINGLE
)
2137 /* ubound = lbound + num_images() - 1. */
2138 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_num_images
,
2139 2, integer_zero_node
,
2140 build_int_cst (integer_type_node
, -1));
2141 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
2142 gfc_array_index_type
,
2143 fold_convert (gfc_array_index_type
, tmp
),
2144 build_int_cst (gfc_array_index_type
, 1));
2145 resbound
= fold_build2_loc (input_location
, PLUS_EXPR
,
2146 gfc_array_index_type
, resbound
, tmp
);
2151 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
2153 build_int_cst (TREE_TYPE (bound
),
2154 arg
->expr
->rank
+ corank
- 1));
2156 resbound2
= gfc_conv_descriptor_ubound_get (desc
, bound
);
2157 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
2158 gfc_array_index_type
, cond
,
2159 resbound
, resbound2
);
2162 se
->expr
= resbound
;
2165 se
->expr
= resbound
;
2167 type
= gfc_typenode_for_spec (&expr
->ts
);
2168 se
->expr
= convert (type
, se
->expr
);
2173 conv_intrinsic_stride (gfc_se
* se
, gfc_expr
* expr
)
2175 gfc_actual_arglist
*array_arg
;
2176 gfc_actual_arglist
*dim_arg
;
2180 array_arg
= expr
->value
.function
.actual
;
2181 dim_arg
= array_arg
->next
;
2183 gcc_assert (array_arg
->expr
->expr_type
== EXPR_VARIABLE
);
2185 gfc_init_se (&argse
, NULL
);
2186 gfc_conv_expr_descriptor (&argse
, array_arg
->expr
);
2187 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2188 gfc_add_block_to_block (&se
->post
, &argse
.post
);
2191 gcc_assert (dim_arg
->expr
);
2192 gfc_init_se (&argse
, NULL
);
2193 gfc_conv_expr_type (&argse
, dim_arg
->expr
, gfc_array_index_type
);
2194 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
2195 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
2196 argse
.expr
, gfc_index_one_node
);
2197 se
->expr
= gfc_conv_descriptor_stride_get (desc
, tmp
);
2202 gfc_conv_intrinsic_abs (gfc_se
* se
, gfc_expr
* expr
)
2206 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
2208 switch (expr
->value
.function
.actual
->expr
->ts
.type
)
2212 se
->expr
= fold_build1_loc (input_location
, ABS_EXPR
, TREE_TYPE (arg
),
2217 cabs
= gfc_builtin_decl_for_float_kind (BUILT_IN_CABS
, expr
->ts
.kind
);
2218 se
->expr
= build_call_expr_loc (input_location
, cabs
, 1, arg
);
2227 /* Create a complex value from one or two real components. */
2230 gfc_conv_intrinsic_cmplx (gfc_se
* se
, gfc_expr
* expr
, int both
)
2236 unsigned int num_args
;
2238 num_args
= gfc_intrinsic_argument_list_length (expr
);
2239 args
= XALLOCAVEC (tree
, num_args
);
2241 type
= gfc_typenode_for_spec (&expr
->ts
);
2242 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
2243 real
= convert (TREE_TYPE (type
), args
[0]);
2245 imag
= convert (TREE_TYPE (type
), args
[1]);
2246 else if (TREE_CODE (TREE_TYPE (args
[0])) == COMPLEX_TYPE
)
2248 imag
= fold_build1_loc (input_location
, IMAGPART_EXPR
,
2249 TREE_TYPE (TREE_TYPE (args
[0])), args
[0]);
2250 imag
= convert (TREE_TYPE (type
), imag
);
2253 imag
= build_real_from_int_cst (TREE_TYPE (type
), integer_zero_node
);
2255 se
->expr
= fold_build2_loc (input_location
, COMPLEX_EXPR
, type
, real
, imag
);
2259 /* Remainder function MOD(A, P) = A - INT(A / P) * P
2260 MODULO(A, P) = A - FLOOR (A / P) * P
2262 The obvious algorithms above are numerically instable for large
2263 arguments, hence these intrinsics are instead implemented via calls
2264 to the fmod family of functions. It is the responsibility of the
2265 user to ensure that the second argument is non-zero. */
2268 gfc_conv_intrinsic_mod (gfc_se
* se
, gfc_expr
* expr
, int modulo
)
2278 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
2280 switch (expr
->ts
.type
)
2283 /* Integer case is easy, we've got a builtin op. */
2284 type
= TREE_TYPE (args
[0]);
2287 se
->expr
= fold_build2_loc (input_location
, FLOOR_MOD_EXPR
, type
,
2290 se
->expr
= fold_build2_loc (input_location
, TRUNC_MOD_EXPR
, type
,
2296 /* Check if we have a builtin fmod. */
2297 fmod
= gfc_builtin_decl_for_float_kind (BUILT_IN_FMOD
, expr
->ts
.kind
);
2299 /* The builtin should always be available. */
2300 gcc_assert (fmod
!= NULL_TREE
);
2302 tmp
= build_addr (fmod
, current_function_decl
);
2303 se
->expr
= build_call_array_loc (input_location
,
2304 TREE_TYPE (TREE_TYPE (fmod
)),
2309 type
= TREE_TYPE (args
[0]);
2311 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
2312 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
2315 modulo = arg - floor (arg/arg2) * arg2
2317 In order to calculate the result accurately, we use the fmod
2318 function as follows.
2320 res = fmod (arg, arg2);
2323 if ((arg < 0) xor (arg2 < 0))
2327 res = copysign (0., arg2);
2329 => As two nested ternary exprs:
2331 res = res ? (((arg < 0) xor (arg2 < 0)) ? res + arg2 : res)
2332 : copysign (0., arg2);
2336 zero
= gfc_build_const (type
, integer_zero_node
);
2337 tmp
= gfc_evaluate_now (se
->expr
, &se
->pre
);
2338 if (!flag_signed_zeros
)
2340 test
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
2342 test2
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
2344 test2
= fold_build2_loc (input_location
, TRUTH_XOR_EXPR
,
2345 boolean_type_node
, test
, test2
);
2346 test
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
2348 test
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
2349 boolean_type_node
, test
, test2
);
2350 test
= gfc_evaluate_now (test
, &se
->pre
);
2351 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, test
,
2352 fold_build2_loc (input_location
,
2354 type
, tmp
, args
[1]),
2359 tree expr1
, copysign
, cscall
;
2360 copysign
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
,
2362 test
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
2364 test2
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
,
2366 test2
= fold_build2_loc (input_location
, TRUTH_XOR_EXPR
,
2367 boolean_type_node
, test
, test2
);
2368 expr1
= fold_build3_loc (input_location
, COND_EXPR
, type
, test2
,
2369 fold_build2_loc (input_location
,
2371 type
, tmp
, args
[1]),
2373 test
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
2375 cscall
= build_call_expr_loc (input_location
, copysign
, 2, zero
,
2377 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, test
,
2387 /* DSHIFTL(I,J,S) = (I << S) | (J >> (BITSIZE(J) - S))
2388 DSHIFTR(I,J,S) = (I << (BITSIZE(I) - S)) | (J >> S)
2389 where the right shifts are logical (i.e. 0's are shifted in).
2390 Because SHIFT_EXPR's want shifts strictly smaller than the integral
2391 type width, we have to special-case both S == 0 and S == BITSIZE(J):
2393 DSHIFTL(I,J,BITSIZE) = J
2395 DSHIFTR(I,J,BITSIZE) = I. */
2398 gfc_conv_intrinsic_dshift (gfc_se
* se
, gfc_expr
* expr
, bool dshiftl
)
2400 tree type
, utype
, stype
, arg1
, arg2
, shift
, res
, left
, right
;
2401 tree args
[3], cond
, tmp
;
2404 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
2406 gcc_assert (TREE_TYPE (args
[0]) == TREE_TYPE (args
[1]));
2407 type
= TREE_TYPE (args
[0]);
2408 bitsize
= TYPE_PRECISION (type
);
2409 utype
= unsigned_type_for (type
);
2410 stype
= TREE_TYPE (args
[2]);
2412 arg1
= gfc_evaluate_now (args
[0], &se
->pre
);
2413 arg2
= gfc_evaluate_now (args
[1], &se
->pre
);
2414 shift
= gfc_evaluate_now (args
[2], &se
->pre
);
2416 /* The generic case. */
2417 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, stype
,
2418 build_int_cst (stype
, bitsize
), shift
);
2419 left
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
2420 arg1
, dshiftl
? shift
: tmp
);
2422 right
= fold_build2_loc (input_location
, RSHIFT_EXPR
, utype
,
2423 fold_convert (utype
, arg2
), dshiftl
? tmp
: shift
);
2424 right
= fold_convert (type
, right
);
2426 res
= fold_build2_loc (input_location
, BIT_IOR_EXPR
, type
, left
, right
);
2428 /* Special cases. */
2429 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
, shift
,
2430 build_int_cst (stype
, 0));
2431 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
2432 dshiftl
? arg1
: arg2
, res
);
2434 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
, shift
,
2435 build_int_cst (stype
, bitsize
));
2436 res
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
2437 dshiftl
? arg2
: arg1
, res
);
2443 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
2446 gfc_conv_intrinsic_dim (gfc_se
* se
, gfc_expr
* expr
)
2454 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
2455 type
= TREE_TYPE (args
[0]);
2457 val
= fold_build2_loc (input_location
, MINUS_EXPR
, type
, args
[0], args
[1]);
2458 val
= gfc_evaluate_now (val
, &se
->pre
);
2460 zero
= gfc_build_const (type
, integer_zero_node
);
2461 tmp
= fold_build2_loc (input_location
, LE_EXPR
, boolean_type_node
, val
, zero
);
2462 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, zero
, val
);
2466 /* SIGN(A, B) is absolute value of A times sign of B.
2467 The real value versions use library functions to ensure the correct
2468 handling of negative zero. Integer case implemented as:
2469 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
2473 gfc_conv_intrinsic_sign (gfc_se
* se
, gfc_expr
* expr
)
2479 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
2480 if (expr
->ts
.type
== BT_REAL
)
2484 tmp
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
, expr
->ts
.kind
);
2485 abs
= gfc_builtin_decl_for_float_kind (BUILT_IN_FABS
, expr
->ts
.kind
);
2487 /* We explicitly have to ignore the minus sign. We do so by using
2488 result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
2490 && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args
[1]))))
2493 zero
= build_real_from_int_cst (TREE_TYPE (args
[1]), integer_zero_node
);
2494 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
2496 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
2497 TREE_TYPE (args
[0]), cond
,
2498 build_call_expr_loc (input_location
, abs
, 1,
2500 build_call_expr_loc (input_location
, tmp
, 2,
2504 se
->expr
= build_call_expr_loc (input_location
, tmp
, 2,
2509 /* Having excluded floating point types, we know we are now dealing
2510 with signed integer types. */
2511 type
= TREE_TYPE (args
[0]);
2513 /* Args[0] is used multiple times below. */
2514 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
2516 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
2517 the signs of A and B are the same, and of all ones if they differ. */
2518 tmp
= fold_build2_loc (input_location
, BIT_XOR_EXPR
, type
, args
[0], args
[1]);
2519 tmp
= fold_build2_loc (input_location
, RSHIFT_EXPR
, type
, tmp
,
2520 build_int_cst (type
, TYPE_PRECISION (type
) - 1));
2521 tmp
= gfc_evaluate_now (tmp
, &se
->pre
);
2523 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
2524 is all ones (i.e. -1). */
2525 se
->expr
= fold_build2_loc (input_location
, BIT_XOR_EXPR
, type
,
2526 fold_build2_loc (input_location
, PLUS_EXPR
,
2527 type
, args
[0], tmp
), tmp
);
2531 /* Test for the presence of an optional argument. */
2534 gfc_conv_intrinsic_present (gfc_se
* se
, gfc_expr
* expr
)
2538 arg
= expr
->value
.function
.actual
->expr
;
2539 gcc_assert (arg
->expr_type
== EXPR_VARIABLE
);
2540 se
->expr
= gfc_conv_expr_present (arg
->symtree
->n
.sym
);
2541 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
2545 /* Calculate the double precision product of two single precision values. */
2548 gfc_conv_intrinsic_dprod (gfc_se
* se
, gfc_expr
* expr
)
2553 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
2555 /* Convert the args to double precision before multiplying. */
2556 type
= gfc_typenode_for_spec (&expr
->ts
);
2557 args
[0] = convert (type
, args
[0]);
2558 args
[1] = convert (type
, args
[1]);
2559 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, type
, args
[0],
2564 /* Return a length one character string containing an ascii character. */
2567 gfc_conv_intrinsic_char (gfc_se
* se
, gfc_expr
* expr
)
2572 unsigned int num_args
;
2574 num_args
= gfc_intrinsic_argument_list_length (expr
);
2575 gfc_conv_intrinsic_function_args (se
, expr
, arg
, num_args
);
2577 type
= gfc_get_char_type (expr
->ts
.kind
);
2578 var
= gfc_create_var (type
, "char");
2580 arg
[0] = fold_build1_loc (input_location
, NOP_EXPR
, type
, arg
[0]);
2581 gfc_add_modify (&se
->pre
, var
, arg
[0]);
2582 se
->expr
= gfc_build_addr_expr (build_pointer_type (type
), var
);
2583 se
->string_length
= build_int_cst (gfc_charlen_type_node
, 1);
2588 gfc_conv_intrinsic_ctime (gfc_se
* se
, gfc_expr
* expr
)
2596 unsigned int num_args
;
2598 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
2599 args
= XALLOCAVEC (tree
, num_args
);
2601 var
= gfc_create_var (pchar_type_node
, "pstr");
2602 len
= gfc_create_var (gfc_charlen_type_node
, "len");
2604 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
2605 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
2606 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
2608 fndecl
= build_addr (gfor_fndecl_ctime
, current_function_decl
);
2609 tmp
= build_call_array_loc (input_location
,
2610 TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime
)),
2611 fndecl
, num_args
, args
);
2612 gfc_add_expr_to_block (&se
->pre
, tmp
);
2614 /* Free the temporary afterwards, if necessary. */
2615 cond
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
2616 len
, build_int_cst (TREE_TYPE (len
), 0));
2617 tmp
= gfc_call_free (var
);
2618 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
2619 gfc_add_expr_to_block (&se
->post
, tmp
);
2622 se
->string_length
= len
;
2627 gfc_conv_intrinsic_fdate (gfc_se
* se
, gfc_expr
* expr
)
2635 unsigned int num_args
;
2637 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
2638 args
= XALLOCAVEC (tree
, num_args
);
2640 var
= gfc_create_var (pchar_type_node
, "pstr");
2641 len
= gfc_create_var (gfc_charlen_type_node
, "len");
2643 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
2644 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
2645 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
2647 fndecl
= build_addr (gfor_fndecl_fdate
, current_function_decl
);
2648 tmp
= build_call_array_loc (input_location
,
2649 TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate
)),
2650 fndecl
, num_args
, args
);
2651 gfc_add_expr_to_block (&se
->pre
, tmp
);
2653 /* Free the temporary afterwards, if necessary. */
2654 cond
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
2655 len
, build_int_cst (TREE_TYPE (len
), 0));
2656 tmp
= gfc_call_free (var
);
2657 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
2658 gfc_add_expr_to_block (&se
->post
, tmp
);
2661 se
->string_length
= len
;
2665 /* Call the SYSTEM_CLOCK library functions, handling the type and kind
2669 conv_intrinsic_system_clock (gfc_code
*code
)
2672 gfc_se count_se
, count_rate_se
, count_max_se
;
2673 tree arg1
= NULL_TREE
, arg2
= NULL_TREE
, arg3
= NULL_TREE
;
2677 gfc_expr
*count
= code
->ext
.actual
->expr
;
2678 gfc_expr
*count_rate
= code
->ext
.actual
->next
->expr
;
2679 gfc_expr
*count_max
= code
->ext
.actual
->next
->next
->expr
;
2681 /* Evaluate our arguments. */
2684 gfc_init_se (&count_se
, NULL
);
2685 gfc_conv_expr (&count_se
, count
);
2690 gfc_init_se (&count_rate_se
, NULL
);
2691 gfc_conv_expr (&count_rate_se
, count_rate
);
2696 gfc_init_se (&count_max_se
, NULL
);
2697 gfc_conv_expr (&count_max_se
, count_max
);
2700 /* Find the smallest kind found of the arguments. */
2702 least
= (count
&& count
->ts
.kind
< least
) ? count
->ts
.kind
: least
;
2703 least
= (count_rate
&& count_rate
->ts
.kind
< least
) ? count_rate
->ts
.kind
2705 least
= (count_max
&& count_max
->ts
.kind
< least
) ? count_max
->ts
.kind
2708 /* Prepare temporary variables. */
2713 arg1
= gfc_create_var (gfc_get_int_type (8), "count");
2714 else if (least
== 4)
2715 arg1
= gfc_create_var (gfc_get_int_type (4), "count");
2716 else if (count
->ts
.kind
== 1)
2717 arg1
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[0].pedantic_min_int
,
2720 arg1
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[1].pedantic_min_int
,
2727 arg2
= gfc_create_var (gfc_get_int_type (8), "count_rate");
2728 else if (least
== 4)
2729 arg2
= gfc_create_var (gfc_get_int_type (4), "count_rate");
2731 arg2
= integer_zero_node
;
2737 arg3
= gfc_create_var (gfc_get_int_type (8), "count_max");
2738 else if (least
== 4)
2739 arg3
= gfc_create_var (gfc_get_int_type (4), "count_max");
2741 arg3
= integer_zero_node
;
2744 /* Make the function call. */
2745 gfc_init_block (&block
);
2751 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
2752 : null_pointer_node
;
2753 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
2754 : null_pointer_node
;
2755 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
2756 : null_pointer_node
;
2761 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
2762 : null_pointer_node
;
2763 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
2764 : null_pointer_node
;
2765 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
2766 : null_pointer_node
;
2773 tmp
= build_call_expr_loc (input_location
,
2774 gfor_fndecl_system_clock4
, 3,
2775 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
2776 : null_pointer_node
,
2777 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
2778 : null_pointer_node
,
2779 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
2780 : null_pointer_node
);
2781 gfc_add_expr_to_block (&block
, tmp
);
2783 /* Handle kind>=8, 10, or 16 arguments */
2786 tmp
= build_call_expr_loc (input_location
,
2787 gfor_fndecl_system_clock8
, 3,
2788 arg1
? gfc_build_addr_expr (NULL_TREE
, arg1
)
2789 : null_pointer_node
,
2790 arg2
? gfc_build_addr_expr (NULL_TREE
, arg2
)
2791 : null_pointer_node
,
2792 arg3
? gfc_build_addr_expr (NULL_TREE
, arg3
)
2793 : null_pointer_node
);
2794 gfc_add_expr_to_block (&block
, tmp
);
2798 /* And store values back if needed. */
2799 if (arg1
&& arg1
!= count_se
.expr
)
2800 gfc_add_modify (&block
, count_se
.expr
,
2801 fold_convert (TREE_TYPE (count_se
.expr
), arg1
));
2802 if (arg2
&& arg2
!= count_rate_se
.expr
)
2803 gfc_add_modify (&block
, count_rate_se
.expr
,
2804 fold_convert (TREE_TYPE (count_rate_se
.expr
), arg2
));
2805 if (arg3
&& arg3
!= count_max_se
.expr
)
2806 gfc_add_modify (&block
, count_max_se
.expr
,
2807 fold_convert (TREE_TYPE (count_max_se
.expr
), arg3
));
2809 return gfc_finish_block (&block
);
2813 /* Return a character string containing the tty name. */
2816 gfc_conv_intrinsic_ttynam (gfc_se
* se
, gfc_expr
* expr
)
2824 unsigned int num_args
;
2826 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
2827 args
= XALLOCAVEC (tree
, num_args
);
2829 var
= gfc_create_var (pchar_type_node
, "pstr");
2830 len
= gfc_create_var (gfc_charlen_type_node
, "len");
2832 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
2833 args
[0] = gfc_build_addr_expr (NULL_TREE
, var
);
2834 args
[1] = gfc_build_addr_expr (NULL_TREE
, len
);
2836 fndecl
= build_addr (gfor_fndecl_ttynam
, current_function_decl
);
2837 tmp
= build_call_array_loc (input_location
,
2838 TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam
)),
2839 fndecl
, num_args
, args
);
2840 gfc_add_expr_to_block (&se
->pre
, tmp
);
2842 /* Free the temporary afterwards, if necessary. */
2843 cond
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
2844 len
, build_int_cst (TREE_TYPE (len
), 0));
2845 tmp
= gfc_call_free (var
);
2846 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
2847 gfc_add_expr_to_block (&se
->post
, tmp
);
2850 se
->string_length
= len
;
2854 /* Get the minimum/maximum value of all the parameters.
2855 minmax (a1, a2, a3, ...)
2858 if (a2 .op. mvar || isnan (mvar))
2860 if (a3 .op. mvar || isnan (mvar))
2867 /* TODO: Mismatching types can occur when specific names are used.
2868 These should be handled during resolution. */
2870 gfc_conv_intrinsic_minmax (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
2878 gfc_actual_arglist
*argexpr
;
2879 unsigned int i
, nargs
;
2881 nargs
= gfc_intrinsic_argument_list_length (expr
);
2882 args
= XALLOCAVEC (tree
, nargs
);
2884 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
2885 type
= gfc_typenode_for_spec (&expr
->ts
);
2887 argexpr
= expr
->value
.function
.actual
;
2888 if (TREE_TYPE (args
[0]) != type
)
2889 args
[0] = convert (type
, args
[0]);
2890 /* Only evaluate the argument once. */
2891 if (TREE_CODE (args
[0]) != VAR_DECL
&& !TREE_CONSTANT (args
[0]))
2892 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
2894 mvar
= gfc_create_var (type
, "M");
2895 gfc_add_modify (&se
->pre
, mvar
, args
[0]);
2896 for (i
= 1, argexpr
= argexpr
->next
; i
< nargs
; i
++)
2902 /* Handle absent optional arguments by ignoring the comparison. */
2903 if (argexpr
->expr
->expr_type
== EXPR_VARIABLE
2904 && argexpr
->expr
->symtree
->n
.sym
->attr
.optional
2905 && TREE_CODE (val
) == INDIRECT_REF
)
2906 cond
= fold_build2_loc (input_location
,
2907 NE_EXPR
, boolean_type_node
,
2908 TREE_OPERAND (val
, 0),
2909 build_int_cst (TREE_TYPE (TREE_OPERAND (val
, 0)), 0));
2914 /* Only evaluate the argument once. */
2915 if (TREE_CODE (val
) != VAR_DECL
&& !TREE_CONSTANT (val
))
2916 val
= gfc_evaluate_now (val
, &se
->pre
);
2919 thencase
= build2_v (MODIFY_EXPR
, mvar
, convert (type
, val
));
2921 tmp
= fold_build2_loc (input_location
, op
, boolean_type_node
,
2922 convert (type
, val
), mvar
);
2924 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
2925 __builtin_isnan might be made dependent on that module being loaded,
2926 to help performance of programs that don't rely on IEEE semantics. */
2927 if (FLOAT_TYPE_P (TREE_TYPE (mvar
)))
2929 isnan
= build_call_expr_loc (input_location
,
2930 builtin_decl_explicit (BUILT_IN_ISNAN
),
2932 tmp
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
2933 boolean_type_node
, tmp
,
2934 fold_convert (boolean_type_node
, isnan
));
2936 tmp
= build3_v (COND_EXPR
, tmp
, thencase
,
2937 build_empty_stmt (input_location
));
2939 if (cond
!= NULL_TREE
)
2940 tmp
= build3_v (COND_EXPR
, cond
, tmp
,
2941 build_empty_stmt (input_location
));
2943 gfc_add_expr_to_block (&se
->pre
, tmp
);
2944 argexpr
= argexpr
->next
;
2950 /* Generate library calls for MIN and MAX intrinsics for character
2953 gfc_conv_intrinsic_minmax_char (gfc_se
* se
, gfc_expr
* expr
, int op
)
2956 tree var
, len
, fndecl
, tmp
, cond
, function
;
2959 nargs
= gfc_intrinsic_argument_list_length (expr
);
2960 args
= XALLOCAVEC (tree
, nargs
+ 4);
2961 gfc_conv_intrinsic_function_args (se
, expr
, &args
[4], nargs
);
2963 /* Create the result variables. */
2964 len
= gfc_create_var (gfc_charlen_type_node
, "len");
2965 args
[0] = gfc_build_addr_expr (NULL_TREE
, len
);
2966 var
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
), "pstr");
2967 args
[1] = gfc_build_addr_expr (ppvoid_type_node
, var
);
2968 args
[2] = build_int_cst (integer_type_node
, op
);
2969 args
[3] = build_int_cst (integer_type_node
, nargs
/ 2);
2971 if (expr
->ts
.kind
== 1)
2972 function
= gfor_fndecl_string_minmax
;
2973 else if (expr
->ts
.kind
== 4)
2974 function
= gfor_fndecl_string_minmax_char4
;
2978 /* Make the function call. */
2979 fndecl
= build_addr (function
, current_function_decl
);
2980 tmp
= build_call_array_loc (input_location
,
2981 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
2983 gfc_add_expr_to_block (&se
->pre
, tmp
);
2985 /* Free the temporary afterwards, if necessary. */
2986 cond
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
2987 len
, build_int_cst (TREE_TYPE (len
), 0));
2988 tmp
= gfc_call_free (var
);
2989 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
2990 gfc_add_expr_to_block (&se
->post
, tmp
);
2993 se
->string_length
= len
;
2997 /* Create a symbol node for this intrinsic. The symbol from the frontend
2998 has the generic name. */
3001 gfc_get_symbol_for_expr (gfc_expr
* expr
, bool ignore_optional
)
3005 /* TODO: Add symbols for intrinsic function to the global namespace. */
3006 gcc_assert (strlen (expr
->value
.function
.name
) <= GFC_MAX_SYMBOL_LEN
- 5);
3007 sym
= gfc_new_symbol (expr
->value
.function
.name
, NULL
);
3010 sym
->attr
.external
= 1;
3011 sym
->attr
.function
= 1;
3012 sym
->attr
.always_explicit
= 1;
3013 sym
->attr
.proc
= PROC_INTRINSIC
;
3014 sym
->attr
.flavor
= FL_PROCEDURE
;
3018 sym
->attr
.dimension
= 1;
3019 sym
->as
= gfc_get_array_spec ();
3020 sym
->as
->type
= AS_ASSUMED_SHAPE
;
3021 sym
->as
->rank
= expr
->rank
;
3024 gfc_copy_formal_args_intr (sym
, expr
->value
.function
.isym
,
3025 ignore_optional
? expr
->value
.function
.actual
3031 /* Generate a call to an external intrinsic function. */
3033 gfc_conv_intrinsic_funcall (gfc_se
* se
, gfc_expr
* expr
)
3036 vec
<tree
, va_gc
> *append_args
;
3038 gcc_assert (!se
->ss
|| se
->ss
->info
->expr
== expr
);
3041 gcc_assert (expr
->rank
> 0);
3043 gcc_assert (expr
->rank
== 0);
3045 sym
= gfc_get_symbol_for_expr (expr
, se
->ignore_optional
);
3047 /* Calls to libgfortran_matmul need to be appended special arguments,
3048 to be able to call the BLAS ?gemm functions if required and possible. */
3050 if (expr
->value
.function
.isym
->id
== GFC_ISYM_MATMUL
3051 && sym
->ts
.type
!= BT_LOGICAL
)
3053 tree cint
= gfc_get_int_type (gfc_c_int_kind
);
3055 if (flag_external_blas
3056 && (sym
->ts
.type
== BT_REAL
|| sym
->ts
.type
== BT_COMPLEX
)
3057 && (sym
->ts
.kind
== 4 || sym
->ts
.kind
== 8))
3061 if (sym
->ts
.type
== BT_REAL
)
3063 if (sym
->ts
.kind
== 4)
3064 gemm_fndecl
= gfor_fndecl_sgemm
;
3066 gemm_fndecl
= gfor_fndecl_dgemm
;
3070 if (sym
->ts
.kind
== 4)
3071 gemm_fndecl
= gfor_fndecl_cgemm
;
3073 gemm_fndecl
= gfor_fndecl_zgemm
;
3076 vec_alloc (append_args
, 3);
3077 append_args
->quick_push (build_int_cst (cint
, 1));
3078 append_args
->quick_push (build_int_cst (cint
,
3079 flag_blas_matmul_limit
));
3080 append_args
->quick_push (gfc_build_addr_expr (NULL_TREE
,
3085 vec_alloc (append_args
, 3);
3086 append_args
->quick_push (build_int_cst (cint
, 0));
3087 append_args
->quick_push (build_int_cst (cint
, 0));
3088 append_args
->quick_push (null_pointer_node
);
3092 gfc_conv_procedure_call (se
, sym
, expr
->value
.function
.actual
, expr
,
3094 gfc_free_symbol (sym
);
3097 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
3117 gfc_conv_intrinsic_anyall (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
3126 gfc_actual_arglist
*actual
;
3133 gfc_conv_intrinsic_funcall (se
, expr
);
3137 actual
= expr
->value
.function
.actual
;
3138 type
= gfc_typenode_for_spec (&expr
->ts
);
3139 /* Initialize the result. */
3140 resvar
= gfc_create_var (type
, "test");
3142 tmp
= convert (type
, boolean_true_node
);
3144 tmp
= convert (type
, boolean_false_node
);
3145 gfc_add_modify (&se
->pre
, resvar
, tmp
);
3147 /* Walk the arguments. */
3148 arrayss
= gfc_walk_expr (actual
->expr
);
3149 gcc_assert (arrayss
!= gfc_ss_terminator
);
3151 /* Initialize the scalarizer. */
3152 gfc_init_loopinfo (&loop
);
3153 exit_label
= gfc_build_label_decl (NULL_TREE
);
3154 TREE_USED (exit_label
) = 1;
3155 gfc_add_ss_to_loop (&loop
, arrayss
);
3157 /* Initialize the loop. */
3158 gfc_conv_ss_startstride (&loop
);
3159 gfc_conv_loop_setup (&loop
, &expr
->where
);
3161 gfc_mark_ss_chain_used (arrayss
, 1);
3162 /* Generate the loop body. */
3163 gfc_start_scalarized_body (&loop
, &body
);
3165 /* If the condition matches then set the return value. */
3166 gfc_start_block (&block
);
3168 tmp
= convert (type
, boolean_false_node
);
3170 tmp
= convert (type
, boolean_true_node
);
3171 gfc_add_modify (&block
, resvar
, tmp
);
3173 /* And break out of the loop. */
3174 tmp
= build1_v (GOTO_EXPR
, exit_label
);
3175 gfc_add_expr_to_block (&block
, tmp
);
3177 found
= gfc_finish_block (&block
);
3179 /* Check this element. */
3180 gfc_init_se (&arrayse
, NULL
);
3181 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
3182 arrayse
.ss
= arrayss
;
3183 gfc_conv_expr_val (&arrayse
, actual
->expr
);
3185 gfc_add_block_to_block (&body
, &arrayse
.pre
);
3186 tmp
= fold_build2_loc (input_location
, op
, boolean_type_node
, arrayse
.expr
,
3187 build_int_cst (TREE_TYPE (arrayse
.expr
), 0));
3188 tmp
= build3_v (COND_EXPR
, tmp
, found
, build_empty_stmt (input_location
));
3189 gfc_add_expr_to_block (&body
, tmp
);
3190 gfc_add_block_to_block (&body
, &arrayse
.post
);
3192 gfc_trans_scalarizing_loops (&loop
, &body
);
3194 /* Add the exit label. */
3195 tmp
= build1_v (LABEL_EXPR
, exit_label
);
3196 gfc_add_expr_to_block (&loop
.pre
, tmp
);
3198 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
3199 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
3200 gfc_cleanup_loop (&loop
);
3205 /* COUNT(A) = Number of true elements in A. */
3207 gfc_conv_intrinsic_count (gfc_se
* se
, gfc_expr
* expr
)
3214 gfc_actual_arglist
*actual
;
3220 gfc_conv_intrinsic_funcall (se
, expr
);
3224 actual
= expr
->value
.function
.actual
;
3226 type
= gfc_typenode_for_spec (&expr
->ts
);
3227 /* Initialize the result. */
3228 resvar
= gfc_create_var (type
, "count");
3229 gfc_add_modify (&se
->pre
, resvar
, build_int_cst (type
, 0));
3231 /* Walk the arguments. */
3232 arrayss
= gfc_walk_expr (actual
->expr
);
3233 gcc_assert (arrayss
!= gfc_ss_terminator
);
3235 /* Initialize the scalarizer. */
3236 gfc_init_loopinfo (&loop
);
3237 gfc_add_ss_to_loop (&loop
, arrayss
);
3239 /* Initialize the loop. */
3240 gfc_conv_ss_startstride (&loop
);
3241 gfc_conv_loop_setup (&loop
, &expr
->where
);
3243 gfc_mark_ss_chain_used (arrayss
, 1);
3244 /* Generate the loop body. */
3245 gfc_start_scalarized_body (&loop
, &body
);
3247 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (resvar
),
3248 resvar
, build_int_cst (TREE_TYPE (resvar
), 1));
3249 tmp
= build2_v (MODIFY_EXPR
, resvar
, tmp
);
3251 gfc_init_se (&arrayse
, NULL
);
3252 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
3253 arrayse
.ss
= arrayss
;
3254 gfc_conv_expr_val (&arrayse
, actual
->expr
);
3255 tmp
= build3_v (COND_EXPR
, arrayse
.expr
, tmp
,
3256 build_empty_stmt (input_location
));
3258 gfc_add_block_to_block (&body
, &arrayse
.pre
);
3259 gfc_add_expr_to_block (&body
, tmp
);
3260 gfc_add_block_to_block (&body
, &arrayse
.post
);
3262 gfc_trans_scalarizing_loops (&loop
, &body
);
3264 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
3265 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
3266 gfc_cleanup_loop (&loop
);
3272 /* Update given gfc_se to have ss component pointing to the nested gfc_ss
3273 struct and return the corresponding loopinfo. */
3275 static gfc_loopinfo
*
3276 enter_nested_loop (gfc_se
*se
)
3278 se
->ss
= se
->ss
->nested_ss
;
3279 gcc_assert (se
->ss
== se
->ss
->loop
->ss
);
3281 return se
->ss
->loop
;
3285 /* Inline implementation of the sum and product intrinsics. */
3287 gfc_conv_intrinsic_arith (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
,
3291 tree scale
= NULL_TREE
;
3296 gfc_loopinfo loop
, *ploop
;
3297 gfc_actual_arglist
*arg_array
, *arg_mask
;
3298 gfc_ss
*arrayss
= NULL
;
3299 gfc_ss
*maskss
= NULL
;
3303 gfc_expr
*arrayexpr
;
3308 gcc_assert (gfc_inline_intrinsic_function_p (expr
));
3314 type
= gfc_typenode_for_spec (&expr
->ts
);
3315 /* Initialize the result. */
3316 resvar
= gfc_create_var (type
, "val");
3321 scale
= gfc_create_var (type
, "scale");
3322 gfc_add_modify (&se
->pre
, scale
,
3323 gfc_build_const (type
, integer_one_node
));
3324 tmp
= gfc_build_const (type
, integer_zero_node
);
3326 else if (op
== PLUS_EXPR
|| op
== BIT_IOR_EXPR
|| op
== BIT_XOR_EXPR
)
3327 tmp
= gfc_build_const (type
, integer_zero_node
);
3328 else if (op
== NE_EXPR
)
3330 tmp
= convert (type
, boolean_false_node
);
3331 else if (op
== BIT_AND_EXPR
)
3332 tmp
= gfc_build_const (type
, fold_build1_loc (input_location
, NEGATE_EXPR
,
3333 type
, integer_one_node
));
3335 tmp
= gfc_build_const (type
, integer_one_node
);
3337 gfc_add_modify (&se
->pre
, resvar
, tmp
);
3339 arg_array
= expr
->value
.function
.actual
;
3341 arrayexpr
= arg_array
->expr
;
3343 if (op
== NE_EXPR
|| norm2
)
3344 /* PARITY and NORM2. */
3348 arg_mask
= arg_array
->next
->next
;
3349 gcc_assert (arg_mask
!= NULL
);
3350 maskexpr
= arg_mask
->expr
;
3353 if (expr
->rank
== 0)
3355 /* Walk the arguments. */
3356 arrayss
= gfc_walk_expr (arrayexpr
);
3357 gcc_assert (arrayss
!= gfc_ss_terminator
);
3359 if (maskexpr
&& maskexpr
->rank
> 0)
3361 maskss
= gfc_walk_expr (maskexpr
);
3362 gcc_assert (maskss
!= gfc_ss_terminator
);
3367 /* Initialize the scalarizer. */
3368 gfc_init_loopinfo (&loop
);
3369 gfc_add_ss_to_loop (&loop
, arrayss
);
3370 if (maskexpr
&& maskexpr
->rank
> 0)
3371 gfc_add_ss_to_loop (&loop
, maskss
);
3373 /* Initialize the loop. */
3374 gfc_conv_ss_startstride (&loop
);
3375 gfc_conv_loop_setup (&loop
, &expr
->where
);
3377 gfc_mark_ss_chain_used (arrayss
, 1);
3378 if (maskexpr
&& maskexpr
->rank
> 0)
3379 gfc_mark_ss_chain_used (maskss
, 1);
3384 /* All the work has been done in the parent loops. */
3385 ploop
= enter_nested_loop (se
);
3389 /* Generate the loop body. */
3390 gfc_start_scalarized_body (ploop
, &body
);
3392 /* If we have a mask, only add this element if the mask is set. */
3393 if (maskexpr
&& maskexpr
->rank
> 0)
3395 gfc_init_se (&maskse
, parent_se
);
3396 gfc_copy_loopinfo_to_se (&maskse
, ploop
);
3397 if (expr
->rank
== 0)
3399 gfc_conv_expr_val (&maskse
, maskexpr
);
3400 gfc_add_block_to_block (&body
, &maskse
.pre
);
3402 gfc_start_block (&block
);
3405 gfc_init_block (&block
);
3407 /* Do the actual summation/product. */
3408 gfc_init_se (&arrayse
, parent_se
);
3409 gfc_copy_loopinfo_to_se (&arrayse
, ploop
);
3410 if (expr
->rank
== 0)
3411 arrayse
.ss
= arrayss
;
3412 gfc_conv_expr_val (&arrayse
, arrayexpr
);
3413 gfc_add_block_to_block (&block
, &arrayse
.pre
);
3417 /* if (x (i) != 0.0)
3423 result = 1.0 + result * val * val;
3429 result += val * val;
3432 tree res1
, res2
, cond
, absX
, val
;
3433 stmtblock_t ifblock1
, ifblock2
, ifblock3
;
3435 gfc_init_block (&ifblock1
);
3437 absX
= gfc_create_var (type
, "absX");
3438 gfc_add_modify (&ifblock1
, absX
,
3439 fold_build1_loc (input_location
, ABS_EXPR
, type
,
3441 val
= gfc_create_var (type
, "val");
3442 gfc_add_expr_to_block (&ifblock1
, val
);
3444 gfc_init_block (&ifblock2
);
3445 gfc_add_modify (&ifblock2
, val
,
3446 fold_build2_loc (input_location
, RDIV_EXPR
, type
, scale
,
3448 res1
= fold_build2_loc (input_location
, MULT_EXPR
, type
, val
, val
);
3449 res1
= fold_build2_loc (input_location
, MULT_EXPR
, type
, resvar
, res1
);
3450 res1
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, res1
,
3451 gfc_build_const (type
, integer_one_node
));
3452 gfc_add_modify (&ifblock2
, resvar
, res1
);
3453 gfc_add_modify (&ifblock2
, scale
, absX
);
3454 res1
= gfc_finish_block (&ifblock2
);
3456 gfc_init_block (&ifblock3
);
3457 gfc_add_modify (&ifblock3
, val
,
3458 fold_build2_loc (input_location
, RDIV_EXPR
, type
, absX
,
3460 res2
= fold_build2_loc (input_location
, MULT_EXPR
, type
, val
, val
);
3461 res2
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, resvar
, res2
);
3462 gfc_add_modify (&ifblock3
, resvar
, res2
);
3463 res2
= gfc_finish_block (&ifblock3
);
3465 cond
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
3467 tmp
= build3_v (COND_EXPR
, cond
, res1
, res2
);
3468 gfc_add_expr_to_block (&ifblock1
, tmp
);
3469 tmp
= gfc_finish_block (&ifblock1
);
3471 cond
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
3473 gfc_build_const (type
, integer_zero_node
));
3475 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
3476 gfc_add_expr_to_block (&block
, tmp
);
3480 tmp
= fold_build2_loc (input_location
, op
, type
, resvar
, arrayse
.expr
);
3481 gfc_add_modify (&block
, resvar
, tmp
);
3484 gfc_add_block_to_block (&block
, &arrayse
.post
);
3486 if (maskexpr
&& maskexpr
->rank
> 0)
3488 /* We enclose the above in if (mask) {...} . */
3490 tmp
= gfc_finish_block (&block
);
3491 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
3492 build_empty_stmt (input_location
));
3495 tmp
= gfc_finish_block (&block
);
3496 gfc_add_expr_to_block (&body
, tmp
);
3498 gfc_trans_scalarizing_loops (ploop
, &body
);
3500 /* For a scalar mask, enclose the loop in an if statement. */
3501 if (maskexpr
&& maskexpr
->rank
== 0)
3503 gfc_init_block (&block
);
3504 gfc_add_block_to_block (&block
, &ploop
->pre
);
3505 gfc_add_block_to_block (&block
, &ploop
->post
);
3506 tmp
= gfc_finish_block (&block
);
3510 tmp
= build3_v (COND_EXPR
, se
->ss
->info
->data
.scalar
.value
, tmp
,
3511 build_empty_stmt (input_location
));
3512 gfc_advance_se_ss_chain (se
);
3516 gcc_assert (expr
->rank
== 0);
3517 gfc_init_se (&maskse
, NULL
);
3518 gfc_conv_expr_val (&maskse
, maskexpr
);
3519 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
3520 build_empty_stmt (input_location
));
3523 gfc_add_expr_to_block (&block
, tmp
);
3524 gfc_add_block_to_block (&se
->pre
, &block
);
3525 gcc_assert (se
->post
.head
== NULL
);
3529 gfc_add_block_to_block (&se
->pre
, &ploop
->pre
);
3530 gfc_add_block_to_block (&se
->pre
, &ploop
->post
);
3533 if (expr
->rank
== 0)
3534 gfc_cleanup_loop (ploop
);
3538 /* result = scale * sqrt(result). */
3540 sqrt
= gfc_builtin_decl_for_float_kind (BUILT_IN_SQRT
, expr
->ts
.kind
);
3541 resvar
= build_call_expr_loc (input_location
,
3543 resvar
= fold_build2_loc (input_location
, MULT_EXPR
, type
, scale
, resvar
);
3550 /* Inline implementation of the dot_product intrinsic. This function
3551 is based on gfc_conv_intrinsic_arith (the previous function). */
3553 gfc_conv_intrinsic_dot_product (gfc_se
* se
, gfc_expr
* expr
)
3561 gfc_actual_arglist
*actual
;
3562 gfc_ss
*arrayss1
, *arrayss2
;
3563 gfc_se arrayse1
, arrayse2
;
3564 gfc_expr
*arrayexpr1
, *arrayexpr2
;
3566 type
= gfc_typenode_for_spec (&expr
->ts
);
3568 /* Initialize the result. */
3569 resvar
= gfc_create_var (type
, "val");
3570 if (expr
->ts
.type
== BT_LOGICAL
)
3571 tmp
= build_int_cst (type
, 0);
3573 tmp
= gfc_build_const (type
, integer_zero_node
);
3575 gfc_add_modify (&se
->pre
, resvar
, tmp
);
3577 /* Walk argument #1. */
3578 actual
= expr
->value
.function
.actual
;
3579 arrayexpr1
= actual
->expr
;
3580 arrayss1
= gfc_walk_expr (arrayexpr1
);
3581 gcc_assert (arrayss1
!= gfc_ss_terminator
);
3583 /* Walk argument #2. */
3584 actual
= actual
->next
;
3585 arrayexpr2
= actual
->expr
;
3586 arrayss2
= gfc_walk_expr (arrayexpr2
);
3587 gcc_assert (arrayss2
!= gfc_ss_terminator
);
3589 /* Initialize the scalarizer. */
3590 gfc_init_loopinfo (&loop
);
3591 gfc_add_ss_to_loop (&loop
, arrayss1
);
3592 gfc_add_ss_to_loop (&loop
, arrayss2
);
3594 /* Initialize the loop. */
3595 gfc_conv_ss_startstride (&loop
);
3596 gfc_conv_loop_setup (&loop
, &expr
->where
);
3598 gfc_mark_ss_chain_used (arrayss1
, 1);
3599 gfc_mark_ss_chain_used (arrayss2
, 1);
3601 /* Generate the loop body. */
3602 gfc_start_scalarized_body (&loop
, &body
);
3603 gfc_init_block (&block
);
3605 /* Make the tree expression for [conjg(]array1[)]. */
3606 gfc_init_se (&arrayse1
, NULL
);
3607 gfc_copy_loopinfo_to_se (&arrayse1
, &loop
);
3608 arrayse1
.ss
= arrayss1
;
3609 gfc_conv_expr_val (&arrayse1
, arrayexpr1
);
3610 if (expr
->ts
.type
== BT_COMPLEX
)
3611 arrayse1
.expr
= fold_build1_loc (input_location
, CONJ_EXPR
, type
,
3613 gfc_add_block_to_block (&block
, &arrayse1
.pre
);
3615 /* Make the tree expression for array2. */
3616 gfc_init_se (&arrayse2
, NULL
);
3617 gfc_copy_loopinfo_to_se (&arrayse2
, &loop
);
3618 arrayse2
.ss
= arrayss2
;
3619 gfc_conv_expr_val (&arrayse2
, arrayexpr2
);
3620 gfc_add_block_to_block (&block
, &arrayse2
.pre
);
3622 /* Do the actual product and sum. */
3623 if (expr
->ts
.type
== BT_LOGICAL
)
3625 tmp
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
, type
,
3626 arrayse1
.expr
, arrayse2
.expr
);
3627 tmp
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
, type
, resvar
, tmp
);
3631 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, type
, arrayse1
.expr
,
3633 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, type
, resvar
, tmp
);
3635 gfc_add_modify (&block
, resvar
, tmp
);
3637 /* Finish up the loop block and the loop. */
3638 tmp
= gfc_finish_block (&block
);
3639 gfc_add_expr_to_block (&body
, tmp
);
3641 gfc_trans_scalarizing_loops (&loop
, &body
);
3642 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
3643 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
3644 gfc_cleanup_loop (&loop
);
3650 /* Emit code for minloc or maxloc intrinsic. There are many different cases
3651 we need to handle. For performance reasons we sometimes create two
3652 loops instead of one, where the second one is much simpler.
3653 Examples for minloc intrinsic:
3654 1) Result is an array, a call is generated
3655 2) Array mask is used and NaNs need to be supported:
3661 if (pos == 0) pos = S + (1 - from);
3662 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3669 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3673 3) NaNs need to be supported, but it is known at compile time or cheaply
3674 at runtime whether array is nonempty or not:
3679 if (a[S] <= limit) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3682 if (from <= to) pos = 1;
3686 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3690 4) NaNs aren't supported, array mask is used:
3691 limit = infinities_supported ? Infinity : huge (limit);
3695 if (mask[S]) { limit = a[S]; pos = S + (1 - from); goto lab1; }
3701 if (mask[S]) if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3705 5) Same without array mask:
3706 limit = infinities_supported ? Infinity : huge (limit);
3707 pos = (from <= to) ? 1 : 0;
3710 if (a[S] < limit) { limit = a[S]; pos = S + (1 - from); }
3713 For 3) and 5), if mask is scalar, this all goes into a conditional,
3714 setting pos = 0; in the else branch. */
3717 gfc_conv_intrinsic_minmaxloc (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
3721 stmtblock_t ifblock
;
3722 stmtblock_t elseblock
;
3733 gfc_actual_arglist
*actual
;
3738 gfc_expr
*arrayexpr
;
3745 gfc_conv_intrinsic_funcall (se
, expr
);
3749 /* Initialize the result. */
3750 pos
= gfc_create_var (gfc_array_index_type
, "pos");
3751 offset
= gfc_create_var (gfc_array_index_type
, "offset");
3752 type
= gfc_typenode_for_spec (&expr
->ts
);
3754 /* Walk the arguments. */
3755 actual
= expr
->value
.function
.actual
;
3756 arrayexpr
= actual
->expr
;
3757 arrayss
= gfc_walk_expr (arrayexpr
);
3758 gcc_assert (arrayss
!= gfc_ss_terminator
);
3760 actual
= actual
->next
->next
;
3761 gcc_assert (actual
);
3762 maskexpr
= actual
->expr
;
3764 if (maskexpr
&& maskexpr
->rank
!= 0)
3766 maskss
= gfc_walk_expr (maskexpr
);
3767 gcc_assert (maskss
!= gfc_ss_terminator
);
3772 if (gfc_array_size (arrayexpr
, &asize
))
3774 nonempty
= gfc_conv_mpz_to_tree (asize
, gfc_index_integer_kind
);
3776 nonempty
= fold_build2_loc (input_location
, GT_EXPR
,
3777 boolean_type_node
, nonempty
,
3778 gfc_index_zero_node
);
3783 limit
= gfc_create_var (gfc_typenode_for_spec (&arrayexpr
->ts
), "limit");
3784 switch (arrayexpr
->ts
.type
)
3787 tmp
= gfc_build_inf_or_huge (TREE_TYPE (limit
), arrayexpr
->ts
.kind
);
3791 n
= gfc_validate_kind (arrayexpr
->ts
.type
, arrayexpr
->ts
.kind
, false);
3792 tmp
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
,
3793 arrayexpr
->ts
.kind
);
3800 /* We start with the most negative possible value for MAXLOC, and the most
3801 positive possible value for MINLOC. The most negative possible value is
3802 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
3803 possible value is HUGE in both cases. */
3805 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (tmp
), tmp
);
3806 if (op
== GT_EXPR
&& arrayexpr
->ts
.type
== BT_INTEGER
)
3807 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (tmp
), tmp
,
3808 build_int_cst (TREE_TYPE (tmp
), 1));
3810 gfc_add_modify (&se
->pre
, limit
, tmp
);
3812 /* Initialize the scalarizer. */
3813 gfc_init_loopinfo (&loop
);
3814 gfc_add_ss_to_loop (&loop
, arrayss
);
3816 gfc_add_ss_to_loop (&loop
, maskss
);
3818 /* Initialize the loop. */
3819 gfc_conv_ss_startstride (&loop
);
3821 /* The code generated can have more than one loop in sequence (see the
3822 comment at the function header). This doesn't work well with the
3823 scalarizer, which changes arrays' offset when the scalarization loops
3824 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}loc
3825 are currently inlined in the scalar case only (for which loop is of rank
3826 one). As there is no dependency to care about in that case, there is no
3827 temporary, so that we can use the scalarizer temporary code to handle
3828 multiple loops. Thus, we set temp_dim here, we call gfc_mark_ss_chain_used
3829 with flag=3 later, and we use gfc_trans_scalarized_loop_boundary even later
3831 TODO: this prevents inlining of rank > 0 minmaxloc calls, so this
3832 should eventually go away. We could either create two loops properly,
3833 or find another way to save/restore the array offsets between the two
3834 loops (without conflicting with temporary management), or use a single
3835 loop minmaxloc implementation. See PR 31067. */
3836 loop
.temp_dim
= loop
.dimen
;
3837 gfc_conv_loop_setup (&loop
, &expr
->where
);
3839 gcc_assert (loop
.dimen
== 1);
3840 if (nonempty
== NULL
&& maskss
== NULL
&& loop
.from
[0] && loop
.to
[0])
3841 nonempty
= fold_build2_loc (input_location
, LE_EXPR
, boolean_type_node
,
3842 loop
.from
[0], loop
.to
[0]);
3846 /* Initialize the position to zero, following Fortran 2003. We are free
3847 to do this because Fortran 95 allows the result of an entirely false
3848 mask to be processor dependent. If we know at compile time the array
3849 is non-empty and no MASK is used, we can initialize to 1 to simplify
3851 if (nonempty
!= NULL
&& !HONOR_NANS (DECL_MODE (limit
)))
3852 gfc_add_modify (&loop
.pre
, pos
,
3853 fold_build3_loc (input_location
, COND_EXPR
,
3854 gfc_array_index_type
,
3855 nonempty
, gfc_index_one_node
,
3856 gfc_index_zero_node
));
3859 gfc_add_modify (&loop
.pre
, pos
, gfc_index_zero_node
);
3860 lab1
= gfc_build_label_decl (NULL_TREE
);
3861 TREE_USED (lab1
) = 1;
3862 lab2
= gfc_build_label_decl (NULL_TREE
);
3863 TREE_USED (lab2
) = 1;
3866 /* An offset must be added to the loop
3867 counter to obtain the required position. */
3868 gcc_assert (loop
.from
[0]);
3870 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
3871 gfc_index_one_node
, loop
.from
[0]);
3872 gfc_add_modify (&loop
.pre
, offset
, tmp
);
3874 gfc_mark_ss_chain_used (arrayss
, lab1
? 3 : 1);
3876 gfc_mark_ss_chain_used (maskss
, lab1
? 3 : 1);
3877 /* Generate the loop body. */
3878 gfc_start_scalarized_body (&loop
, &body
);
3880 /* If we have a mask, only check this element if the mask is set. */
3883 gfc_init_se (&maskse
, NULL
);
3884 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
3886 gfc_conv_expr_val (&maskse
, maskexpr
);
3887 gfc_add_block_to_block (&body
, &maskse
.pre
);
3889 gfc_start_block (&block
);
3892 gfc_init_block (&block
);
3894 /* Compare with the current limit. */
3895 gfc_init_se (&arrayse
, NULL
);
3896 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
3897 arrayse
.ss
= arrayss
;
3898 gfc_conv_expr_val (&arrayse
, arrayexpr
);
3899 gfc_add_block_to_block (&block
, &arrayse
.pre
);
3901 /* We do the following if this is a more extreme value. */
3902 gfc_start_block (&ifblock
);
3904 /* Assign the value to the limit... */
3905 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
3907 if (nonempty
== NULL
&& HONOR_NANS (DECL_MODE (limit
)))
3909 stmtblock_t ifblock2
;
3912 gfc_start_block (&ifblock2
);
3913 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
),
3914 loop
.loopvar
[0], offset
);
3915 gfc_add_modify (&ifblock2
, pos
, tmp
);
3916 ifbody2
= gfc_finish_block (&ifblock2
);
3917 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
, pos
,
3918 gfc_index_zero_node
);
3919 tmp
= build3_v (COND_EXPR
, cond
, ifbody2
,
3920 build_empty_stmt (input_location
));
3921 gfc_add_expr_to_block (&block
, tmp
);
3924 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
),
3925 loop
.loopvar
[0], offset
);
3926 gfc_add_modify (&ifblock
, pos
, tmp
);
3929 gfc_add_expr_to_block (&ifblock
, build1_v (GOTO_EXPR
, lab1
));
3931 ifbody
= gfc_finish_block (&ifblock
);
3933 if (!lab1
|| HONOR_NANS (DECL_MODE (limit
)))
3936 cond
= fold_build2_loc (input_location
,
3937 op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
3938 boolean_type_node
, arrayse
.expr
, limit
);
3940 cond
= fold_build2_loc (input_location
, op
, boolean_type_node
,
3941 arrayse
.expr
, limit
);
3943 ifbody
= build3_v (COND_EXPR
, cond
, ifbody
,
3944 build_empty_stmt (input_location
));
3946 gfc_add_expr_to_block (&block
, ifbody
);
3950 /* We enclose the above in if (mask) {...}. */
3951 tmp
= gfc_finish_block (&block
);
3953 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
3954 build_empty_stmt (input_location
));
3957 tmp
= gfc_finish_block (&block
);
3958 gfc_add_expr_to_block (&body
, tmp
);
3962 gfc_trans_scalarized_loop_boundary (&loop
, &body
);
3964 if (HONOR_NANS (DECL_MODE (limit
)))
3966 if (nonempty
!= NULL
)
3968 ifbody
= build2_v (MODIFY_EXPR
, pos
, gfc_index_one_node
);
3969 tmp
= build3_v (COND_EXPR
, nonempty
, ifbody
,
3970 build_empty_stmt (input_location
));
3971 gfc_add_expr_to_block (&loop
.code
[0], tmp
);
3975 gfc_add_expr_to_block (&loop
.code
[0], build1_v (GOTO_EXPR
, lab2
));
3976 gfc_add_expr_to_block (&loop
.code
[0], build1_v (LABEL_EXPR
, lab1
));
3978 /* If we have a mask, only check this element if the mask is set. */
3981 gfc_init_se (&maskse
, NULL
);
3982 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
3984 gfc_conv_expr_val (&maskse
, maskexpr
);
3985 gfc_add_block_to_block (&body
, &maskse
.pre
);
3987 gfc_start_block (&block
);
3990 gfc_init_block (&block
);
3992 /* Compare with the current limit. */
3993 gfc_init_se (&arrayse
, NULL
);
3994 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
3995 arrayse
.ss
= arrayss
;
3996 gfc_conv_expr_val (&arrayse
, arrayexpr
);
3997 gfc_add_block_to_block (&block
, &arrayse
.pre
);
3999 /* We do the following if this is a more extreme value. */
4000 gfc_start_block (&ifblock
);
4002 /* Assign the value to the limit... */
4003 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
4005 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, TREE_TYPE (pos
),
4006 loop
.loopvar
[0], offset
);
4007 gfc_add_modify (&ifblock
, pos
, tmp
);
4009 ifbody
= gfc_finish_block (&ifblock
);
4011 cond
= fold_build2_loc (input_location
, op
, boolean_type_node
,
4012 arrayse
.expr
, limit
);
4014 tmp
= build3_v (COND_EXPR
, cond
, ifbody
,
4015 build_empty_stmt (input_location
));
4016 gfc_add_expr_to_block (&block
, tmp
);
4020 /* We enclose the above in if (mask) {...}. */
4021 tmp
= gfc_finish_block (&block
);
4023 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
4024 build_empty_stmt (input_location
));
4027 tmp
= gfc_finish_block (&block
);
4028 gfc_add_expr_to_block (&body
, tmp
);
4029 /* Avoid initializing loopvar[0] again, it should be left where
4030 it finished by the first loop. */
4031 loop
.from
[0] = loop
.loopvar
[0];
4034 gfc_trans_scalarizing_loops (&loop
, &body
);
4037 gfc_add_expr_to_block (&loop
.pre
, build1_v (LABEL_EXPR
, lab2
));
4039 /* For a scalar mask, enclose the loop in an if statement. */
4040 if (maskexpr
&& maskss
== NULL
)
4042 gfc_init_se (&maskse
, NULL
);
4043 gfc_conv_expr_val (&maskse
, maskexpr
);
4044 gfc_init_block (&block
);
4045 gfc_add_block_to_block (&block
, &loop
.pre
);
4046 gfc_add_block_to_block (&block
, &loop
.post
);
4047 tmp
= gfc_finish_block (&block
);
4049 /* For the else part of the scalar mask, just initialize
4050 the pos variable the same way as above. */
4052 gfc_init_block (&elseblock
);
4053 gfc_add_modify (&elseblock
, pos
, gfc_index_zero_node
);
4054 elsetmp
= gfc_finish_block (&elseblock
);
4056 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
, elsetmp
);
4057 gfc_add_expr_to_block (&block
, tmp
);
4058 gfc_add_block_to_block (&se
->pre
, &block
);
4062 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
4063 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
4065 gfc_cleanup_loop (&loop
);
4067 se
->expr
= convert (type
, pos
);
4070 /* Emit code for minval or maxval intrinsic. There are many different cases
4071 we need to handle. For performance reasons we sometimes create two
4072 loops instead of one, where the second one is much simpler.
4073 Examples for minval intrinsic:
4074 1) Result is an array, a call is generated
4075 2) Array mask is used and NaNs need to be supported, rank 1:
4080 if (mask[S]) { nonempty = true; if (a[S] <= limit) goto lab; }
4083 limit = nonempty ? NaN : huge (limit);
4085 while (S <= to) { if(mask[S]) limit = min (a[S], limit); S++; }
4086 3) NaNs need to be supported, but it is known at compile time or cheaply
4087 at runtime whether array is nonempty or not, rank 1:
4090 while (S <= to) { if (a[S] <= limit) goto lab; S++; }
4091 limit = (from <= to) ? NaN : huge (limit);
4093 while (S <= to) { limit = min (a[S], limit); S++; }
4094 4) Array mask is used and NaNs need to be supported, rank > 1:
4103 if (fast) limit = min (a[S1][S2], limit);
4106 if (a[S1][S2] <= limit) {
4117 limit = nonempty ? NaN : huge (limit);
4118 5) NaNs need to be supported, but it is known at compile time or cheaply
4119 at runtime whether array is nonempty or not, rank > 1:
4126 if (fast) limit = min (a[S1][S2], limit);
4128 if (a[S1][S2] <= limit) {
4138 limit = (nonempty_array) ? NaN : huge (limit);
4139 6) NaNs aren't supported, but infinities are. Array mask is used:
4144 if (mask[S]) { nonempty = true; limit = min (a[S], limit); }
4147 limit = nonempty ? limit : huge (limit);
4148 7) Same without array mask:
4151 while (S <= to) { limit = min (a[S], limit); S++; }
4152 limit = (from <= to) ? limit : huge (limit);
4153 8) Neither NaNs nor infinities are supported (-ffast-math or BT_INTEGER):
4154 limit = huge (limit);
4156 while (S <= to) { limit = min (a[S], limit); S++); }
4158 while (S <= to) { if (mask[S]) limit = min (a[S], limit); S++; }
4159 with array mask instead).
4160 For 3), 5), 7) and 8), if mask is scalar, this all goes into a conditional,
4161 setting limit = huge (limit); in the else branch. */
4164 gfc_conv_intrinsic_minmaxval (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
4174 tree huge_cst
= NULL
, nan_cst
= NULL
;
4176 stmtblock_t block
, block2
;
4178 gfc_actual_arglist
*actual
;
4183 gfc_expr
*arrayexpr
;
4189 gfc_conv_intrinsic_funcall (se
, expr
);
4193 type
= gfc_typenode_for_spec (&expr
->ts
);
4194 /* Initialize the result. */
4195 limit
= gfc_create_var (type
, "limit");
4196 n
= gfc_validate_kind (expr
->ts
.type
, expr
->ts
.kind
, false);
4197 switch (expr
->ts
.type
)
4200 huge_cst
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[n
].huge
,
4202 if (HONOR_INFINITIES (DECL_MODE (limit
)))
4204 REAL_VALUE_TYPE real
;
4206 tmp
= build_real (type
, real
);
4210 if (HONOR_NANS (DECL_MODE (limit
)))
4211 nan_cst
= gfc_build_nan (type
, "");
4215 tmp
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
, expr
->ts
.kind
);
4222 /* We start with the most negative possible value for MAXVAL, and the most
4223 positive possible value for MINVAL. The most negative possible value is
4224 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
4225 possible value is HUGE in both cases. */
4228 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (tmp
), tmp
);
4230 huge_cst
= fold_build1_loc (input_location
, NEGATE_EXPR
,
4231 TREE_TYPE (huge_cst
), huge_cst
);
4234 if (op
== GT_EXPR
&& expr
->ts
.type
== BT_INTEGER
)
4235 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (tmp
),
4236 tmp
, build_int_cst (type
, 1));
4238 gfc_add_modify (&se
->pre
, limit
, tmp
);
4240 /* Walk the arguments. */
4241 actual
= expr
->value
.function
.actual
;
4242 arrayexpr
= actual
->expr
;
4243 arrayss
= gfc_walk_expr (arrayexpr
);
4244 gcc_assert (arrayss
!= gfc_ss_terminator
);
4246 actual
= actual
->next
->next
;
4247 gcc_assert (actual
);
4248 maskexpr
= actual
->expr
;
4250 if (maskexpr
&& maskexpr
->rank
!= 0)
4252 maskss
= gfc_walk_expr (maskexpr
);
4253 gcc_assert (maskss
!= gfc_ss_terminator
);
4258 if (gfc_array_size (arrayexpr
, &asize
))
4260 nonempty
= gfc_conv_mpz_to_tree (asize
, gfc_index_integer_kind
);
4262 nonempty
= fold_build2_loc (input_location
, GT_EXPR
,
4263 boolean_type_node
, nonempty
,
4264 gfc_index_zero_node
);
4269 /* Initialize the scalarizer. */
4270 gfc_init_loopinfo (&loop
);
4271 gfc_add_ss_to_loop (&loop
, arrayss
);
4273 gfc_add_ss_to_loop (&loop
, maskss
);
4275 /* Initialize the loop. */
4276 gfc_conv_ss_startstride (&loop
);
4278 /* The code generated can have more than one loop in sequence (see the
4279 comment at the function header). This doesn't work well with the
4280 scalarizer, which changes arrays' offset when the scalarization loops
4281 are generated (see gfc_trans_preloop_setup). Fortunately, {min,max}val
4282 are currently inlined in the scalar case only. As there is no dependency
4283 to care about in that case, there is no temporary, so that we can use the
4284 scalarizer temporary code to handle multiple loops. Thus, we set temp_dim
4285 here, we call gfc_mark_ss_chain_used with flag=3 later, and we use
4286 gfc_trans_scalarized_loop_boundary even later to restore offset.
4287 TODO: this prevents inlining of rank > 0 minmaxval calls, so this
4288 should eventually go away. We could either create two loops properly,
4289 or find another way to save/restore the array offsets between the two
4290 loops (without conflicting with temporary management), or use a single
4291 loop minmaxval implementation. See PR 31067. */
4292 loop
.temp_dim
= loop
.dimen
;
4293 gfc_conv_loop_setup (&loop
, &expr
->where
);
4295 if (nonempty
== NULL
&& maskss
== NULL
4296 && loop
.dimen
== 1 && loop
.from
[0] && loop
.to
[0])
4297 nonempty
= fold_build2_loc (input_location
, LE_EXPR
, boolean_type_node
,
4298 loop
.from
[0], loop
.to
[0]);
4299 nonempty_var
= NULL
;
4300 if (nonempty
== NULL
4301 && (HONOR_INFINITIES (DECL_MODE (limit
))
4302 || HONOR_NANS (DECL_MODE (limit
))))
4304 nonempty_var
= gfc_create_var (boolean_type_node
, "nonempty");
4305 gfc_add_modify (&se
->pre
, nonempty_var
, boolean_false_node
);
4306 nonempty
= nonempty_var
;
4310 if (HONOR_NANS (DECL_MODE (limit
)))
4312 if (loop
.dimen
== 1)
4314 lab
= gfc_build_label_decl (NULL_TREE
);
4315 TREE_USED (lab
) = 1;
4319 fast
= gfc_create_var (boolean_type_node
, "fast");
4320 gfc_add_modify (&se
->pre
, fast
, boolean_false_node
);
4324 gfc_mark_ss_chain_used (arrayss
, lab
? 3 : 1);
4326 gfc_mark_ss_chain_used (maskss
, lab
? 3 : 1);
4327 /* Generate the loop body. */
4328 gfc_start_scalarized_body (&loop
, &body
);
4330 /* If we have a mask, only add this element if the mask is set. */
4333 gfc_init_se (&maskse
, NULL
);
4334 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
4336 gfc_conv_expr_val (&maskse
, maskexpr
);
4337 gfc_add_block_to_block (&body
, &maskse
.pre
);
4339 gfc_start_block (&block
);
4342 gfc_init_block (&block
);
4344 /* Compare with the current limit. */
4345 gfc_init_se (&arrayse
, NULL
);
4346 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
4347 arrayse
.ss
= arrayss
;
4348 gfc_conv_expr_val (&arrayse
, arrayexpr
);
4349 gfc_add_block_to_block (&block
, &arrayse
.pre
);
4351 gfc_init_block (&block2
);
4354 gfc_add_modify (&block2
, nonempty_var
, boolean_true_node
);
4356 if (HONOR_NANS (DECL_MODE (limit
)))
4358 tmp
= fold_build2_loc (input_location
, op
== GT_EXPR
? GE_EXPR
: LE_EXPR
,
4359 boolean_type_node
, arrayse
.expr
, limit
);
4361 ifbody
= build1_v (GOTO_EXPR
, lab
);
4364 stmtblock_t ifblock
;
4366 gfc_init_block (&ifblock
);
4367 gfc_add_modify (&ifblock
, limit
, arrayse
.expr
);
4368 gfc_add_modify (&ifblock
, fast
, boolean_true_node
);
4369 ifbody
= gfc_finish_block (&ifblock
);
4371 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
4372 build_empty_stmt (input_location
));
4373 gfc_add_expr_to_block (&block2
, tmp
);
4377 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
4379 if (HONOR_SIGNED_ZEROS (DECL_MODE (limit
)))
4381 tmp
= fold_build2_loc (input_location
, op
, boolean_type_node
,
4382 arrayse
.expr
, limit
);
4383 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
4384 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
4385 build_empty_stmt (input_location
));
4386 gfc_add_expr_to_block (&block2
, tmp
);
4390 tmp
= fold_build2_loc (input_location
,
4391 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
4392 type
, arrayse
.expr
, limit
);
4393 gfc_add_modify (&block2
, limit
, tmp
);
4399 tree elsebody
= gfc_finish_block (&block2
);
4401 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
4403 if (HONOR_NANS (DECL_MODE (limit
))
4404 || HONOR_SIGNED_ZEROS (DECL_MODE (limit
)))
4406 tmp
= fold_build2_loc (input_location
, op
, boolean_type_node
,
4407 arrayse
.expr
, limit
);
4408 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
4409 ifbody
= build3_v (COND_EXPR
, tmp
, ifbody
,
4410 build_empty_stmt (input_location
));
4414 tmp
= fold_build2_loc (input_location
,
4415 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
4416 type
, arrayse
.expr
, limit
);
4417 ifbody
= build2_v (MODIFY_EXPR
, limit
, tmp
);
4419 tmp
= build3_v (COND_EXPR
, fast
, ifbody
, elsebody
);
4420 gfc_add_expr_to_block (&block
, tmp
);
4423 gfc_add_block_to_block (&block
, &block2
);
4425 gfc_add_block_to_block (&block
, &arrayse
.post
);
4427 tmp
= gfc_finish_block (&block
);
4429 /* We enclose the above in if (mask) {...}. */
4430 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
4431 build_empty_stmt (input_location
));
4432 gfc_add_expr_to_block (&body
, tmp
);
4436 gfc_trans_scalarized_loop_boundary (&loop
, &body
);
4438 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
,
4440 gfc_add_modify (&loop
.code
[0], limit
, tmp
);
4441 gfc_add_expr_to_block (&loop
.code
[0], build1_v (LABEL_EXPR
, lab
));
4443 /* If we have a mask, only add this element if the mask is set. */
4446 gfc_init_se (&maskse
, NULL
);
4447 gfc_copy_loopinfo_to_se (&maskse
, &loop
);
4449 gfc_conv_expr_val (&maskse
, maskexpr
);
4450 gfc_add_block_to_block (&body
, &maskse
.pre
);
4452 gfc_start_block (&block
);
4455 gfc_init_block (&block
);
4457 /* Compare with the current limit. */
4458 gfc_init_se (&arrayse
, NULL
);
4459 gfc_copy_loopinfo_to_se (&arrayse
, &loop
);
4460 arrayse
.ss
= arrayss
;
4461 gfc_conv_expr_val (&arrayse
, arrayexpr
);
4462 gfc_add_block_to_block (&block
, &arrayse
.pre
);
4464 /* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
4466 if (HONOR_NANS (DECL_MODE (limit
))
4467 || HONOR_SIGNED_ZEROS (DECL_MODE (limit
)))
4469 tmp
= fold_build2_loc (input_location
, op
, boolean_type_node
,
4470 arrayse
.expr
, limit
);
4471 ifbody
= build2_v (MODIFY_EXPR
, limit
, arrayse
.expr
);
4472 tmp
= build3_v (COND_EXPR
, tmp
, ifbody
,
4473 build_empty_stmt (input_location
));
4474 gfc_add_expr_to_block (&block
, tmp
);
4478 tmp
= fold_build2_loc (input_location
,
4479 op
== GT_EXPR
? MAX_EXPR
: MIN_EXPR
,
4480 type
, arrayse
.expr
, limit
);
4481 gfc_add_modify (&block
, limit
, tmp
);
4484 gfc_add_block_to_block (&block
, &arrayse
.post
);
4486 tmp
= gfc_finish_block (&block
);
4488 /* We enclose the above in if (mask) {...}. */
4489 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
,
4490 build_empty_stmt (input_location
));
4491 gfc_add_expr_to_block (&body
, tmp
);
4492 /* Avoid initializing loopvar[0] again, it should be left where
4493 it finished by the first loop. */
4494 loop
.from
[0] = loop
.loopvar
[0];
4496 gfc_trans_scalarizing_loops (&loop
, &body
);
4500 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
,
4502 ifbody
= build2_v (MODIFY_EXPR
, limit
, tmp
);
4503 tmp
= build3_v (COND_EXPR
, fast
, build_empty_stmt (input_location
),
4505 gfc_add_expr_to_block (&loop
.pre
, tmp
);
4507 else if (HONOR_INFINITIES (DECL_MODE (limit
)) && !lab
)
4509 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, nonempty
, limit
,
4511 gfc_add_modify (&loop
.pre
, limit
, tmp
);
4514 /* For a scalar mask, enclose the loop in an if statement. */
4515 if (maskexpr
&& maskss
== NULL
)
4519 gfc_init_se (&maskse
, NULL
);
4520 gfc_conv_expr_val (&maskse
, maskexpr
);
4521 gfc_init_block (&block
);
4522 gfc_add_block_to_block (&block
, &loop
.pre
);
4523 gfc_add_block_to_block (&block
, &loop
.post
);
4524 tmp
= gfc_finish_block (&block
);
4526 if (HONOR_INFINITIES (DECL_MODE (limit
)))
4527 else_stmt
= build2_v (MODIFY_EXPR
, limit
, huge_cst
);
4529 else_stmt
= build_empty_stmt (input_location
);
4530 tmp
= build3_v (COND_EXPR
, maskse
.expr
, tmp
, else_stmt
);
4531 gfc_add_expr_to_block (&block
, tmp
);
4532 gfc_add_block_to_block (&se
->pre
, &block
);
4536 gfc_add_block_to_block (&se
->pre
, &loop
.pre
);
4537 gfc_add_block_to_block (&se
->pre
, &loop
.post
);
4540 gfc_cleanup_loop (&loop
);
4545 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
4547 gfc_conv_intrinsic_btest (gfc_se
* se
, gfc_expr
* expr
)
4553 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
4554 type
= TREE_TYPE (args
[0]);
4556 tmp
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
4557 build_int_cst (type
, 1), args
[1]);
4558 tmp
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[0], tmp
);
4559 tmp
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
, tmp
,
4560 build_int_cst (type
, 0));
4561 type
= gfc_typenode_for_spec (&expr
->ts
);
4562 se
->expr
= convert (type
, tmp
);
4566 /* Generate code for BGE, BGT, BLE and BLT intrinsics. */
4568 gfc_conv_intrinsic_bitcomp (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
4572 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
4574 /* Convert both arguments to the unsigned type of the same size. */
4575 args
[0] = fold_convert (unsigned_type_for (TREE_TYPE (args
[0])), args
[0]);
4576 args
[1] = fold_convert (unsigned_type_for (TREE_TYPE (args
[1])), args
[1]);
4578 /* If they have unequal type size, convert to the larger one. */
4579 if (TYPE_PRECISION (TREE_TYPE (args
[0]))
4580 > TYPE_PRECISION (TREE_TYPE (args
[1])))
4581 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
4582 else if (TYPE_PRECISION (TREE_TYPE (args
[1]))
4583 > TYPE_PRECISION (TREE_TYPE (args
[0])))
4584 args
[0] = fold_convert (TREE_TYPE (args
[1]), args
[0]);
4586 /* Now, we compare them. */
4587 se
->expr
= fold_build2_loc (input_location
, op
, boolean_type_node
,
4592 /* Generate code to perform the specified operation. */
4594 gfc_conv_intrinsic_bitop (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
4598 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
4599 se
->expr
= fold_build2_loc (input_location
, op
, TREE_TYPE (args
[0]),
4605 gfc_conv_intrinsic_not (gfc_se
* se
, gfc_expr
* expr
)
4609 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
4610 se
->expr
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
4611 TREE_TYPE (arg
), arg
);
4614 /* Set or clear a single bit. */
4616 gfc_conv_intrinsic_singlebitop (gfc_se
* se
, gfc_expr
* expr
, int set
)
4623 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
4624 type
= TREE_TYPE (args
[0]);
4626 tmp
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
,
4627 build_int_cst (type
, 1), args
[1]);
4633 tmp
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, type
, tmp
);
4635 se
->expr
= fold_build2_loc (input_location
, op
, type
, args
[0], tmp
);
4638 /* Extract a sequence of bits.
4639 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
4641 gfc_conv_intrinsic_ibits (gfc_se
* se
, gfc_expr
* expr
)
4648 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
4649 type
= TREE_TYPE (args
[0]);
4651 mask
= build_int_cst (type
, -1);
4652 mask
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
, mask
, args
[2]);
4653 mask
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, type
, mask
);
4655 tmp
= fold_build2_loc (input_location
, RSHIFT_EXPR
, type
, args
[0], args
[1]);
4657 se
->expr
= fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, tmp
, mask
);
4661 gfc_conv_intrinsic_shift (gfc_se
* se
, gfc_expr
* expr
, bool right_shift
,
4664 tree args
[2], type
, num_bits
, cond
;
4666 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
4668 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
4669 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
4670 type
= TREE_TYPE (args
[0]);
4673 args
[0] = fold_convert (unsigned_type_for (type
), args
[0]);
4675 gcc_assert (right_shift
);
4677 se
->expr
= fold_build2_loc (input_location
,
4678 right_shift
? RSHIFT_EXPR
: LSHIFT_EXPR
,
4679 TREE_TYPE (args
[0]), args
[0], args
[1]);
4682 se
->expr
= fold_convert (type
, se
->expr
);
4684 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4685 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4687 num_bits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
4688 cond
= fold_build2_loc (input_location
, GE_EXPR
, boolean_type_node
,
4691 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
4692 build_int_cst (type
, 0), se
->expr
);
4695 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
4697 : ((shift >= 0) ? i << shift : i >> -shift)
4698 where all shifts are logical shifts. */
4700 gfc_conv_intrinsic_ishft (gfc_se
* se
, gfc_expr
* expr
)
4712 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
4714 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
4715 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
4717 type
= TREE_TYPE (args
[0]);
4718 utype
= unsigned_type_for (type
);
4720 width
= fold_build1_loc (input_location
, ABS_EXPR
, TREE_TYPE (args
[1]),
4723 /* Left shift if positive. */
4724 lshift
= fold_build2_loc (input_location
, LSHIFT_EXPR
, type
, args
[0], width
);
4726 /* Right shift if negative.
4727 We convert to an unsigned type because we want a logical shift.
4728 The standard doesn't define the case of shifting negative
4729 numbers, and we try to be compatible with other compilers, most
4730 notably g77, here. */
4731 rshift
= fold_convert (type
, fold_build2_loc (input_location
, RSHIFT_EXPR
,
4732 utype
, convert (utype
, args
[0]), width
));
4734 tmp
= fold_build2_loc (input_location
, GE_EXPR
, boolean_type_node
, args
[1],
4735 build_int_cst (TREE_TYPE (args
[1]), 0));
4736 tmp
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, lshift
, rshift
);
4738 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
4739 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
4741 num_bits
= build_int_cst (TREE_TYPE (args
[1]), TYPE_PRECISION (type
));
4742 cond
= fold_build2_loc (input_location
, GE_EXPR
, boolean_type_node
, width
,
4744 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
4745 build_int_cst (type
, 0), tmp
);
4749 /* Circular shift. AKA rotate or barrel shift. */
4752 gfc_conv_intrinsic_ishftc (gfc_se
* se
, gfc_expr
* expr
)
4760 unsigned int num_args
;
4762 num_args
= gfc_intrinsic_argument_list_length (expr
);
4763 args
= XALLOCAVEC (tree
, num_args
);
4765 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
4769 /* Use a library function for the 3 parameter version. */
4770 tree int4type
= gfc_get_int_type (4);
4772 type
= TREE_TYPE (args
[0]);
4773 /* We convert the first argument to at least 4 bytes, and
4774 convert back afterwards. This removes the need for library
4775 functions for all argument sizes, and function will be
4776 aligned to at least 32 bits, so there's no loss. */
4777 if (expr
->ts
.kind
< 4)
4778 args
[0] = convert (int4type
, args
[0]);
4780 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
4781 need loads of library functions. They cannot have values >
4782 BIT_SIZE (I) so the conversion is safe. */
4783 args
[1] = convert (int4type
, args
[1]);
4784 args
[2] = convert (int4type
, args
[2]);
4786 switch (expr
->ts
.kind
)
4791 tmp
= gfor_fndecl_math_ishftc4
;
4794 tmp
= gfor_fndecl_math_ishftc8
;
4797 tmp
= gfor_fndecl_math_ishftc16
;
4802 se
->expr
= build_call_expr_loc (input_location
,
4803 tmp
, 3, args
[0], args
[1], args
[2]);
4804 /* Convert the result back to the original type, if we extended
4805 the first argument's width above. */
4806 if (expr
->ts
.kind
< 4)
4807 se
->expr
= convert (type
, se
->expr
);
4811 type
= TREE_TYPE (args
[0]);
4813 /* Evaluate arguments only once. */
4814 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
4815 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
4817 /* Rotate left if positive. */
4818 lrot
= fold_build2_loc (input_location
, LROTATE_EXPR
, type
, args
[0], args
[1]);
4820 /* Rotate right if negative. */
4821 tmp
= fold_build1_loc (input_location
, NEGATE_EXPR
, TREE_TYPE (args
[1]),
4823 rrot
= fold_build2_loc (input_location
,RROTATE_EXPR
, type
, args
[0], tmp
);
4825 zero
= build_int_cst (TREE_TYPE (args
[1]), 0);
4826 tmp
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
, args
[1],
4828 rrot
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, lrot
, rrot
);
4830 /* Do nothing if shift == 0. */
4831 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
, args
[1],
4833 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, tmp
, args
[0],
4838 /* LEADZ (i) = (i == 0) ? BIT_SIZE (i)
4839 : __builtin_clz(i) - (BIT_SIZE('int') - BIT_SIZE(i))
4841 The conditional expression is necessary because the result of LEADZ(0)
4842 is defined, but the result of __builtin_clz(0) is undefined for most
4845 For INTEGER kinds smaller than the C 'int' type, we have to subtract the
4846 difference in bit size between the argument of LEADZ and the C int. */
4849 gfc_conv_intrinsic_leadz (gfc_se
* se
, gfc_expr
* expr
)
4861 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
4862 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
4864 /* Which variant of __builtin_clz* should we call? */
4865 if (argsize
<= INT_TYPE_SIZE
)
4867 arg_type
= unsigned_type_node
;
4868 func
= builtin_decl_explicit (BUILT_IN_CLZ
);
4870 else if (argsize
<= LONG_TYPE_SIZE
)
4872 arg_type
= long_unsigned_type_node
;
4873 func
= builtin_decl_explicit (BUILT_IN_CLZL
);
4875 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
4877 arg_type
= long_long_unsigned_type_node
;
4878 func
= builtin_decl_explicit (BUILT_IN_CLZLL
);
4882 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
4883 arg_type
= gfc_build_uint_type (argsize
);
4887 /* Convert the actual argument twice: first, to the unsigned type of the
4888 same size; then, to the proper argument type for the built-in
4889 function. But the return type is of the default INTEGER kind. */
4890 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
4891 arg
= fold_convert (arg_type
, arg
);
4892 arg
= gfc_evaluate_now (arg
, &se
->pre
);
4893 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
4895 /* Compute LEADZ for the case i .ne. 0. */
4898 s
= TYPE_PRECISION (arg_type
) - argsize
;
4899 tmp
= fold_convert (result_type
,
4900 build_call_expr_loc (input_location
, func
,
4902 leadz
= fold_build2_loc (input_location
, MINUS_EXPR
, result_type
,
4903 tmp
, build_int_cst (result_type
, s
));
4907 /* We end up here if the argument type is larger than 'long long'.
4908 We generate this code:
4910 if (x & (ULL_MAX << ULL_SIZE) != 0)
4911 return clzll ((unsigned long long) (x >> ULLSIZE));
4913 return ULL_SIZE + clzll ((unsigned long long) x);
4914 where ULL_MAX is the largest value that a ULL_MAX can hold
4915 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
4916 is the bit-size of the long long type (64 in this example). */
4917 tree ullsize
, ullmax
, tmp1
, tmp2
, btmp
;
4919 ullsize
= build_int_cst (result_type
, LONG_LONG_TYPE_SIZE
);
4920 ullmax
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
4921 long_long_unsigned_type_node
,
4922 build_int_cst (long_long_unsigned_type_node
,
4925 cond
= fold_build2_loc (input_location
, LSHIFT_EXPR
, arg_type
,
4926 fold_convert (arg_type
, ullmax
), ullsize
);
4927 cond
= fold_build2_loc (input_location
, BIT_AND_EXPR
, arg_type
,
4929 cond
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
4930 cond
, build_int_cst (arg_type
, 0));
4932 tmp1
= fold_build2_loc (input_location
, RSHIFT_EXPR
, arg_type
,
4934 tmp1
= fold_convert (long_long_unsigned_type_node
, tmp1
);
4935 btmp
= builtin_decl_explicit (BUILT_IN_CLZLL
);
4936 tmp1
= fold_convert (result_type
,
4937 build_call_expr_loc (input_location
, btmp
, 1, tmp1
));
4939 tmp2
= fold_convert (long_long_unsigned_type_node
, arg
);
4940 btmp
= builtin_decl_explicit (BUILT_IN_CLZLL
);
4941 tmp2
= fold_convert (result_type
,
4942 build_call_expr_loc (input_location
, btmp
, 1, tmp2
));
4943 tmp2
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
4946 leadz
= fold_build3_loc (input_location
, COND_EXPR
, result_type
,
4950 /* Build BIT_SIZE. */
4951 bit_size
= build_int_cst (result_type
, argsize
);
4953 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
4954 arg
, build_int_cst (arg_type
, 0));
4955 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, result_type
, cond
,
4960 /* TRAILZ(i) = (i == 0) ? BIT_SIZE (i) : __builtin_ctz(i)
4962 The conditional expression is necessary because the result of TRAILZ(0)
4963 is defined, but the result of __builtin_ctz(0) is undefined for most
4967 gfc_conv_intrinsic_trailz (gfc_se
* se
, gfc_expr
*expr
)
4978 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
4979 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
4981 /* Which variant of __builtin_ctz* should we call? */
4982 if (argsize
<= INT_TYPE_SIZE
)
4984 arg_type
= unsigned_type_node
;
4985 func
= builtin_decl_explicit (BUILT_IN_CTZ
);
4987 else if (argsize
<= LONG_TYPE_SIZE
)
4989 arg_type
= long_unsigned_type_node
;
4990 func
= builtin_decl_explicit (BUILT_IN_CTZL
);
4992 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
4994 arg_type
= long_long_unsigned_type_node
;
4995 func
= builtin_decl_explicit (BUILT_IN_CTZLL
);
4999 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
5000 arg_type
= gfc_build_uint_type (argsize
);
5004 /* Convert the actual argument twice: first, to the unsigned type of the
5005 same size; then, to the proper argument type for the built-in
5006 function. But the return type is of the default INTEGER kind. */
5007 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
5008 arg
= fold_convert (arg_type
, arg
);
5009 arg
= gfc_evaluate_now (arg
, &se
->pre
);
5010 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
5012 /* Compute TRAILZ for the case i .ne. 0. */
5014 trailz
= fold_convert (result_type
, build_call_expr_loc (input_location
,
5018 /* We end up here if the argument type is larger than 'long long'.
5019 We generate this code:
5021 if ((x & ULL_MAX) == 0)
5022 return ULL_SIZE + ctzll ((unsigned long long) (x >> ULLSIZE));
5024 return ctzll ((unsigned long long) x);
5026 where ULL_MAX is the largest value that a ULL_MAX can hold
5027 (0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
5028 is the bit-size of the long long type (64 in this example). */
5029 tree ullsize
, ullmax
, tmp1
, tmp2
, btmp
;
5031 ullsize
= build_int_cst (result_type
, LONG_LONG_TYPE_SIZE
);
5032 ullmax
= fold_build1_loc (input_location
, BIT_NOT_EXPR
,
5033 long_long_unsigned_type_node
,
5034 build_int_cst (long_long_unsigned_type_node
, 0));
5036 cond
= fold_build2_loc (input_location
, BIT_AND_EXPR
, arg_type
, arg
,
5037 fold_convert (arg_type
, ullmax
));
5038 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
, cond
,
5039 build_int_cst (arg_type
, 0));
5041 tmp1
= fold_build2_loc (input_location
, RSHIFT_EXPR
, arg_type
,
5043 tmp1
= fold_convert (long_long_unsigned_type_node
, tmp1
);
5044 btmp
= builtin_decl_explicit (BUILT_IN_CTZLL
);
5045 tmp1
= fold_convert (result_type
,
5046 build_call_expr_loc (input_location
, btmp
, 1, tmp1
));
5047 tmp1
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
5050 tmp2
= fold_convert (long_long_unsigned_type_node
, arg
);
5051 btmp
= builtin_decl_explicit (BUILT_IN_CTZLL
);
5052 tmp2
= fold_convert (result_type
,
5053 build_call_expr_loc (input_location
, btmp
, 1, tmp2
));
5055 trailz
= fold_build3_loc (input_location
, COND_EXPR
, result_type
,
5059 /* Build BIT_SIZE. */
5060 bit_size
= build_int_cst (result_type
, argsize
);
5062 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
5063 arg
, build_int_cst (arg_type
, 0));
5064 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, result_type
, cond
,
5068 /* Using __builtin_popcount for POPCNT and __builtin_parity for POPPAR;
5069 for types larger than "long long", we call the long long built-in for
5070 the lower and higher bits and combine the result. */
5073 gfc_conv_intrinsic_popcnt_poppar (gfc_se
* se
, gfc_expr
*expr
, int parity
)
5081 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
5082 argsize
= TYPE_PRECISION (TREE_TYPE (arg
));
5083 result_type
= gfc_get_int_type (gfc_default_integer_kind
);
5085 /* Which variant of the builtin should we call? */
5086 if (argsize
<= INT_TYPE_SIZE
)
5088 arg_type
= unsigned_type_node
;
5089 func
= builtin_decl_explicit (parity
5091 : BUILT_IN_POPCOUNT
);
5093 else if (argsize
<= LONG_TYPE_SIZE
)
5095 arg_type
= long_unsigned_type_node
;
5096 func
= builtin_decl_explicit (parity
5098 : BUILT_IN_POPCOUNTL
);
5100 else if (argsize
<= LONG_LONG_TYPE_SIZE
)
5102 arg_type
= long_long_unsigned_type_node
;
5103 func
= builtin_decl_explicit (parity
5105 : BUILT_IN_POPCOUNTLL
);
5109 /* Our argument type is larger than 'long long', which mean none
5110 of the POPCOUNT builtins covers it. We thus call the 'long long'
5111 variant multiple times, and add the results. */
5112 tree utype
, arg2
, call1
, call2
;
5114 /* For now, we only cover the case where argsize is twice as large
5116 gcc_assert (argsize
== 2 * LONG_LONG_TYPE_SIZE
);
5118 func
= builtin_decl_explicit (parity
5120 : BUILT_IN_POPCOUNTLL
);
5122 /* Convert it to an integer, and store into a variable. */
5123 utype
= gfc_build_uint_type (argsize
);
5124 arg
= fold_convert (utype
, arg
);
5125 arg
= gfc_evaluate_now (arg
, &se
->pre
);
5127 /* Call the builtin twice. */
5128 call1
= build_call_expr_loc (input_location
, func
, 1,
5129 fold_convert (long_long_unsigned_type_node
,
5132 arg2
= fold_build2_loc (input_location
, RSHIFT_EXPR
, utype
, arg
,
5133 build_int_cst (utype
, LONG_LONG_TYPE_SIZE
));
5134 call2
= build_call_expr_loc (input_location
, func
, 1,
5135 fold_convert (long_long_unsigned_type_node
,
5138 /* Combine the results. */
5140 se
->expr
= fold_build2_loc (input_location
, BIT_XOR_EXPR
, result_type
,
5143 se
->expr
= fold_build2_loc (input_location
, PLUS_EXPR
, result_type
,
5149 /* Convert the actual argument twice: first, to the unsigned type of the
5150 same size; then, to the proper argument type for the built-in
5152 arg
= fold_convert (gfc_build_uint_type (argsize
), arg
);
5153 arg
= fold_convert (arg_type
, arg
);
5155 se
->expr
= fold_convert (result_type
,
5156 build_call_expr_loc (input_location
, func
, 1, arg
));
5160 /* Process an intrinsic with unspecified argument-types that has an optional
5161 argument (which could be of type character), e.g. EOSHIFT. For those, we
5162 need to append the string length of the optional argument if it is not
5163 present and the type is really character.
5164 primary specifies the position (starting at 1) of the non-optional argument
5165 specifying the type and optional gives the position of the optional
5166 argument in the arglist. */
5169 conv_generic_with_optional_char_arg (gfc_se
* se
, gfc_expr
* expr
,
5170 unsigned primary
, unsigned optional
)
5172 gfc_actual_arglist
* prim_arg
;
5173 gfc_actual_arglist
* opt_arg
;
5175 gfc_actual_arglist
* arg
;
5177 vec
<tree
, va_gc
> *append_args
;
5179 /* Find the two arguments given as position. */
5183 for (arg
= expr
->value
.function
.actual
; arg
; arg
= arg
->next
)
5187 if (cur_pos
== primary
)
5189 if (cur_pos
== optional
)
5192 if (cur_pos
>= primary
&& cur_pos
>= optional
)
5195 gcc_assert (prim_arg
);
5196 gcc_assert (prim_arg
->expr
);
5197 gcc_assert (opt_arg
);
5199 /* If we do have type CHARACTER and the optional argument is really absent,
5200 append a dummy 0 as string length. */
5202 if (prim_arg
->expr
->ts
.type
== BT_CHARACTER
&& !opt_arg
->expr
)
5206 dummy
= build_int_cst (gfc_charlen_type_node
, 0);
5207 vec_alloc (append_args
, 1);
5208 append_args
->quick_push (dummy
);
5211 /* Build the call itself. */
5212 gcc_assert (!se
->ignore_optional
);
5213 sym
= gfc_get_symbol_for_expr (expr
, false);
5214 gfc_conv_procedure_call (se
, sym
, expr
->value
.function
.actual
, expr
,
5216 gfc_free_symbol (sym
);
5220 /* The length of a character string. */
5222 gfc_conv_intrinsic_len (gfc_se
* se
, gfc_expr
* expr
)
5231 gcc_assert (!se
->ss
);
5233 arg
= expr
->value
.function
.actual
->expr
;
5235 type
= gfc_typenode_for_spec (&expr
->ts
);
5236 switch (arg
->expr_type
)
5239 len
= build_int_cst (gfc_charlen_type_node
, arg
->value
.character
.length
);
5243 /* Obtain the string length from the function used by
5244 trans-array.c(gfc_trans_array_constructor). */
5246 get_array_ctor_strlen (&se
->pre
, arg
->value
.constructor
, &len
);
5250 if (arg
->ref
== NULL
5251 || (arg
->ref
->next
== NULL
&& arg
->ref
->type
== REF_ARRAY
))
5253 /* This doesn't catch all cases.
5254 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
5255 and the surrounding thread. */
5256 sym
= arg
->symtree
->n
.sym
;
5257 decl
= gfc_get_symbol_decl (sym
);
5258 if (decl
== current_function_decl
&& sym
->attr
.function
5259 && (sym
->result
== sym
))
5260 decl
= gfc_get_fake_result_decl (sym
, 0);
5262 len
= sym
->ts
.u
.cl
->backend_decl
;
5267 /* Otherwise fall through. */
5270 /* Anybody stupid enough to do this deserves inefficient code. */
5271 gfc_init_se (&argse
, se
);
5273 gfc_conv_expr (&argse
, arg
);
5275 gfc_conv_expr_descriptor (&argse
, arg
);
5276 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
5277 gfc_add_block_to_block (&se
->post
, &argse
.post
);
5278 len
= argse
.string_length
;
5281 se
->expr
= convert (type
, len
);
5284 /* The length of a character string not including trailing blanks. */
5286 gfc_conv_intrinsic_len_trim (gfc_se
* se
, gfc_expr
* expr
)
5288 int kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
5289 tree args
[2], type
, fndecl
;
5291 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5292 type
= gfc_typenode_for_spec (&expr
->ts
);
5295 fndecl
= gfor_fndecl_string_len_trim
;
5297 fndecl
= gfor_fndecl_string_len_trim_char4
;
5301 se
->expr
= build_call_expr_loc (input_location
,
5302 fndecl
, 2, args
[0], args
[1]);
5303 se
->expr
= convert (type
, se
->expr
);
5307 /* Returns the starting position of a substring within a string. */
5310 gfc_conv_intrinsic_index_scan_verify (gfc_se
* se
, gfc_expr
* expr
,
5313 tree logical4_type_node
= gfc_get_logical_type (4);
5317 unsigned int num_args
;
5319 args
= XALLOCAVEC (tree
, 5);
5321 /* Get number of arguments; characters count double due to the
5322 string length argument. Kind= is not passed to the library
5323 and thus ignored. */
5324 if (expr
->value
.function
.actual
->next
->next
->expr
== NULL
)
5329 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
5330 type
= gfc_typenode_for_spec (&expr
->ts
);
5333 args
[4] = build_int_cst (logical4_type_node
, 0);
5335 args
[4] = convert (logical4_type_node
, args
[4]);
5337 fndecl
= build_addr (function
, current_function_decl
);
5338 se
->expr
= build_call_array_loc (input_location
,
5339 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
5341 se
->expr
= convert (type
, se
->expr
);
5345 /* The ascii value for a single character. */
5347 gfc_conv_intrinsic_ichar (gfc_se
* se
, gfc_expr
* expr
)
5349 tree args
[3], type
, pchartype
;
5352 nargs
= gfc_intrinsic_argument_list_length (expr
);
5353 gfc_conv_intrinsic_function_args (se
, expr
, args
, nargs
);
5354 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args
[1])));
5355 pchartype
= gfc_get_pchar_type (expr
->value
.function
.actual
->expr
->ts
.kind
);
5356 args
[1] = fold_build1_loc (input_location
, NOP_EXPR
, pchartype
, args
[1]);
5357 type
= gfc_typenode_for_spec (&expr
->ts
);
5359 se
->expr
= build_fold_indirect_ref_loc (input_location
,
5361 se
->expr
= convert (type
, se
->expr
);
5365 /* Intrinsic ISNAN calls __builtin_isnan. */
5368 gfc_conv_intrinsic_isnan (gfc_se
* se
, gfc_expr
* expr
)
5372 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
5373 se
->expr
= build_call_expr_loc (input_location
,
5374 builtin_decl_explicit (BUILT_IN_ISNAN
),
5376 STRIP_TYPE_NOPS (se
->expr
);
5377 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
5381 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
5382 their argument against a constant integer value. */
5385 gfc_conv_has_intvalue (gfc_se
* se
, gfc_expr
* expr
, const int value
)
5389 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
5390 se
->expr
= fold_build2_loc (input_location
, EQ_EXPR
,
5391 gfc_typenode_for_spec (&expr
->ts
),
5392 arg
, build_int_cst (TREE_TYPE (arg
), value
));
5397 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
5400 gfc_conv_intrinsic_merge (gfc_se
* se
, gfc_expr
* expr
)
5408 unsigned int num_args
;
5410 num_args
= gfc_intrinsic_argument_list_length (expr
);
5411 args
= XALLOCAVEC (tree
, num_args
);
5413 gfc_conv_intrinsic_function_args (se
, expr
, args
, num_args
);
5414 if (expr
->ts
.type
!= BT_CHARACTER
)
5422 /* We do the same as in the non-character case, but the argument
5423 list is different because of the string length arguments. We
5424 also have to set the string length for the result. */
5431 gfc_trans_same_strlen_check ("MERGE intrinsic", &expr
->where
, len
, len2
,
5433 se
->string_length
= len
;
5435 type
= TREE_TYPE (tsource
);
5436 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, mask
, tsource
,
5437 fold_convert (type
, fsource
));
5441 /* MERGE_BITS (I, J, MASK) = (I & MASK) | (I & (~MASK)). */
5444 gfc_conv_intrinsic_merge_bits (gfc_se
* se
, gfc_expr
* expr
)
5446 tree args
[3], mask
, type
;
5448 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
5449 mask
= gfc_evaluate_now (args
[2], &se
->pre
);
5451 type
= TREE_TYPE (args
[0]);
5452 gcc_assert (TREE_TYPE (args
[1]) == type
);
5453 gcc_assert (TREE_TYPE (mask
) == type
);
5455 args
[0] = fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[0], mask
);
5456 args
[1] = fold_build2_loc (input_location
, BIT_AND_EXPR
, type
, args
[1],
5457 fold_build1_loc (input_location
, BIT_NOT_EXPR
,
5459 se
->expr
= fold_build2_loc (input_location
, BIT_IOR_EXPR
, type
,
5464 /* MASKL(n) = n == 0 ? 0 : (~0) << (BIT_SIZE - n)
5465 MASKR(n) = n == BIT_SIZE ? ~0 : ~((~0) << n) */
5468 gfc_conv_intrinsic_mask (gfc_se
* se
, gfc_expr
* expr
, int left
)
5470 tree arg
, allones
, type
, utype
, res
, cond
, bitsize
;
5473 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
5474 arg
= gfc_evaluate_now (arg
, &se
->pre
);
5476 type
= gfc_get_int_type (expr
->ts
.kind
);
5477 utype
= unsigned_type_for (type
);
5479 i
= gfc_validate_kind (BT_INTEGER
, expr
->ts
.kind
, false);
5480 bitsize
= build_int_cst (TREE_TYPE (arg
), gfc_integer_kinds
[i
].bit_size
);
5482 allones
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, utype
,
5483 build_int_cst (utype
, 0));
5487 /* Left-justified mask. */
5488 res
= fold_build2_loc (input_location
, MINUS_EXPR
, TREE_TYPE (arg
),
5490 res
= fold_build2_loc (input_location
, LSHIFT_EXPR
, utype
, allones
,
5491 fold_convert (utype
, res
));
5493 /* Special case arg == 0, because SHIFT_EXPR wants a shift strictly
5494 smaller than type width. */
5495 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
, arg
,
5496 build_int_cst (TREE_TYPE (arg
), 0));
5497 res
= fold_build3_loc (input_location
, COND_EXPR
, utype
, cond
,
5498 build_int_cst (utype
, 0), res
);
5502 /* Right-justified mask. */
5503 res
= fold_build2_loc (input_location
, LSHIFT_EXPR
, utype
, allones
,
5504 fold_convert (utype
, arg
));
5505 res
= fold_build1_loc (input_location
, BIT_NOT_EXPR
, utype
, res
);
5507 /* Special case agr == bit_size, because SHIFT_EXPR wants a shift
5508 strictly smaller than type width. */
5509 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
5511 res
= fold_build3_loc (input_location
, COND_EXPR
, utype
,
5512 cond
, allones
, res
);
5515 se
->expr
= fold_convert (type
, res
);
5519 /* FRACTION (s) is translated into:
5520 isfinite (s) ? frexp (s, &dummy_int) : NaN */
5522 gfc_conv_intrinsic_fraction (gfc_se
* se
, gfc_expr
* expr
)
5524 tree arg
, type
, tmp
, res
, frexp
, cond
;
5526 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
5528 type
= gfc_typenode_for_spec (&expr
->ts
);
5529 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
5530 arg
= gfc_evaluate_now (arg
, &se
->pre
);
5532 cond
= build_call_expr_loc (input_location
,
5533 builtin_decl_explicit (BUILT_IN_ISFINITE
),
5536 tmp
= gfc_create_var (integer_type_node
, NULL
);
5537 res
= build_call_expr_loc (input_location
, frexp
, 2,
5538 fold_convert (type
, arg
),
5539 gfc_build_addr_expr (NULL_TREE
, tmp
));
5540 res
= fold_convert (type
, res
);
5542 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
,
5543 cond
, res
, gfc_build_nan (type
, ""));
5547 /* NEAREST (s, dir) is translated into
5548 tmp = copysign (HUGE_VAL, dir);
5549 return nextafter (s, tmp);
5552 gfc_conv_intrinsic_nearest (gfc_se
* se
, gfc_expr
* expr
)
5554 tree args
[2], type
, tmp
, nextafter
, copysign
, huge_val
;
5556 nextafter
= gfc_builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER
, expr
->ts
.kind
);
5557 copysign
= gfc_builtin_decl_for_float_kind (BUILT_IN_COPYSIGN
, expr
->ts
.kind
);
5559 type
= gfc_typenode_for_spec (&expr
->ts
);
5560 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5562 huge_val
= gfc_build_inf_or_huge (type
, expr
->ts
.kind
);
5563 tmp
= build_call_expr_loc (input_location
, copysign
, 2, huge_val
,
5564 fold_convert (type
, args
[1]));
5565 se
->expr
= build_call_expr_loc (input_location
, nextafter
, 2,
5566 fold_convert (type
, args
[0]), tmp
);
5567 se
->expr
= fold_convert (type
, se
->expr
);
5571 /* SPACING (s) is translated into
5581 e = MAX_EXPR (e, emin);
5582 res = scalbn (1., e);
5586 where prec is the precision of s, gfc_real_kinds[k].digits,
5587 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
5588 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
5591 gfc_conv_intrinsic_spacing (gfc_se
* se
, gfc_expr
* expr
)
5593 tree arg
, type
, prec
, emin
, tiny
, res
, e
;
5594 tree cond
, nan
, tmp
, frexp
, scalbn
;
5598 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
5599 prec
= build_int_cst (integer_type_node
, gfc_real_kinds
[k
].digits
);
5600 emin
= build_int_cst (integer_type_node
, gfc_real_kinds
[k
].min_exponent
- 1);
5601 tiny
= gfc_conv_mpfr_to_tree (gfc_real_kinds
[k
].tiny
, expr
->ts
.kind
, 0);
5603 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
5604 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
5606 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
5607 arg
= gfc_evaluate_now (arg
, &se
->pre
);
5609 type
= gfc_typenode_for_spec (&expr
->ts
);
5610 e
= gfc_create_var (integer_type_node
, NULL
);
5611 res
= gfc_create_var (type
, NULL
);
5614 /* Build the block for s /= 0. */
5615 gfc_start_block (&block
);
5616 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
5617 gfc_build_addr_expr (NULL_TREE
, e
));
5618 gfc_add_expr_to_block (&block
, tmp
);
5620 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, integer_type_node
, e
,
5622 gfc_add_modify (&block
, e
, fold_build2_loc (input_location
, MAX_EXPR
,
5623 integer_type_node
, tmp
, emin
));
5625 tmp
= build_call_expr_loc (input_location
, scalbn
, 2,
5626 build_real_from_int_cst (type
, integer_one_node
), e
);
5627 gfc_add_modify (&block
, res
, tmp
);
5629 /* Finish by building the IF statement for value zero. */
5630 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
, arg
,
5631 build_real_from_int_cst (type
, integer_zero_node
));
5632 tmp
= build3_v (COND_EXPR
, cond
, build2_v (MODIFY_EXPR
, res
, tiny
),
5633 gfc_finish_block (&block
));
5635 /* And deal with infinities and NaNs. */
5636 cond
= build_call_expr_loc (input_location
,
5637 builtin_decl_explicit (BUILT_IN_ISFINITE
),
5639 nan
= gfc_build_nan (type
, "");
5640 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build2_v (MODIFY_EXPR
, res
, nan
));
5642 gfc_add_expr_to_block (&se
->pre
, tmp
);
5647 /* RRSPACING (s) is translated into
5656 x = scalbn (x, precision - e);
5663 where precision is gfc_real_kinds[k].digits. */
5666 gfc_conv_intrinsic_rrspacing (gfc_se
* se
, gfc_expr
* expr
)
5668 tree arg
, type
, e
, x
, cond
, nan
, stmt
, tmp
, frexp
, scalbn
, fabs
;
5672 k
= gfc_validate_kind (BT_REAL
, expr
->ts
.kind
, false);
5673 prec
= gfc_real_kinds
[k
].digits
;
5675 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
5676 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
5677 fabs
= gfc_builtin_decl_for_float_kind (BUILT_IN_FABS
, expr
->ts
.kind
);
5679 type
= gfc_typenode_for_spec (&expr
->ts
);
5680 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
5681 arg
= gfc_evaluate_now (arg
, &se
->pre
);
5683 e
= gfc_create_var (integer_type_node
, NULL
);
5684 x
= gfc_create_var (type
, NULL
);
5685 gfc_add_modify (&se
->pre
, x
,
5686 build_call_expr_loc (input_location
, fabs
, 1, arg
));
5689 gfc_start_block (&block
);
5690 tmp
= build_call_expr_loc (input_location
, frexp
, 2, arg
,
5691 gfc_build_addr_expr (NULL_TREE
, e
));
5692 gfc_add_expr_to_block (&block
, tmp
);
5694 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, integer_type_node
,
5695 build_int_cst (integer_type_node
, prec
), e
);
5696 tmp
= build_call_expr_loc (input_location
, scalbn
, 2, x
, tmp
);
5697 gfc_add_modify (&block
, x
, tmp
);
5698 stmt
= gfc_finish_block (&block
);
5701 cond
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
, x
,
5702 build_real_from_int_cst (type
, integer_zero_node
));
5703 tmp
= build3_v (COND_EXPR
, cond
, stmt
, build_empty_stmt (input_location
));
5705 /* And deal with infinities and NaNs. */
5706 cond
= build_call_expr_loc (input_location
,
5707 builtin_decl_explicit (BUILT_IN_ISFINITE
),
5709 nan
= gfc_build_nan (type
, "");
5710 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build2_v (MODIFY_EXPR
, x
, nan
));
5712 gfc_add_expr_to_block (&se
->pre
, tmp
);
5713 se
->expr
= fold_convert (type
, x
);
5717 /* SCALE (s, i) is translated into scalbn (s, i). */
5719 gfc_conv_intrinsic_scale (gfc_se
* se
, gfc_expr
* expr
)
5721 tree args
[2], type
, scalbn
;
5723 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
5725 type
= gfc_typenode_for_spec (&expr
->ts
);
5726 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5727 se
->expr
= build_call_expr_loc (input_location
, scalbn
, 2,
5728 fold_convert (type
, args
[0]),
5729 fold_convert (integer_type_node
, args
[1]));
5730 se
->expr
= fold_convert (type
, se
->expr
);
5734 /* SET_EXPONENT (s, i) is translated into
5735 isfinite(s) ? scalbn (frexp (s, &dummy_int), i) : NaN */
5737 gfc_conv_intrinsic_set_exponent (gfc_se
* se
, gfc_expr
* expr
)
5739 tree args
[2], type
, tmp
, frexp
, scalbn
, cond
, nan
, res
;
5741 frexp
= gfc_builtin_decl_for_float_kind (BUILT_IN_FREXP
, expr
->ts
.kind
);
5742 scalbn
= gfc_builtin_decl_for_float_kind (BUILT_IN_SCALBN
, expr
->ts
.kind
);
5744 type
= gfc_typenode_for_spec (&expr
->ts
);
5745 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
5746 args
[0] = gfc_evaluate_now (args
[0], &se
->pre
);
5748 tmp
= gfc_create_var (integer_type_node
, NULL
);
5749 tmp
= build_call_expr_loc (input_location
, frexp
, 2,
5750 fold_convert (type
, args
[0]),
5751 gfc_build_addr_expr (NULL_TREE
, tmp
));
5752 res
= build_call_expr_loc (input_location
, scalbn
, 2, tmp
,
5753 fold_convert (integer_type_node
, args
[1]));
5754 res
= fold_convert (type
, res
);
5756 /* Call to isfinite */
5757 cond
= build_call_expr_loc (input_location
,
5758 builtin_decl_explicit (BUILT_IN_ISFINITE
),
5760 nan
= gfc_build_nan (type
, "");
5762 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
, type
, cond
,
5768 gfc_conv_intrinsic_size (gfc_se
* se
, gfc_expr
* expr
)
5770 gfc_actual_arglist
*actual
;
5777 gfc_init_se (&argse
, NULL
);
5778 actual
= expr
->value
.function
.actual
;
5780 if (actual
->expr
->ts
.type
== BT_CLASS
)
5781 gfc_add_class_array_ref (actual
->expr
);
5783 argse
.want_pointer
= 1;
5784 argse
.data_not_needed
= 1;
5785 gfc_conv_expr_descriptor (&argse
, actual
->expr
);
5786 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
5787 gfc_add_block_to_block (&se
->post
, &argse
.post
);
5788 arg1
= gfc_evaluate_now (argse
.expr
, &se
->pre
);
5790 /* Build the call to size0. */
5791 fncall0
= build_call_expr_loc (input_location
,
5792 gfor_fndecl_size0
, 1, arg1
);
5794 actual
= actual
->next
;
5798 gfc_init_se (&argse
, NULL
);
5799 gfc_conv_expr_type (&argse
, actual
->expr
,
5800 gfc_array_index_type
);
5801 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
5803 /* Unusually, for an intrinsic, size does not exclude
5804 an optional arg2, so we must test for it. */
5805 if (actual
->expr
->expr_type
== EXPR_VARIABLE
5806 && actual
->expr
->symtree
->n
.sym
->attr
.dummy
5807 && actual
->expr
->symtree
->n
.sym
->attr
.optional
)
5810 /* Build the call to size1. */
5811 fncall1
= build_call_expr_loc (input_location
,
5812 gfor_fndecl_size1
, 2,
5815 gfc_init_se (&argse
, NULL
);
5816 argse
.want_pointer
= 1;
5817 argse
.data_not_needed
= 1;
5818 gfc_conv_expr (&argse
, actual
->expr
);
5819 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
5820 tmp
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
5821 argse
.expr
, null_pointer_node
);
5822 tmp
= gfc_evaluate_now (tmp
, &se
->pre
);
5823 se
->expr
= fold_build3_loc (input_location
, COND_EXPR
,
5824 pvoid_type_node
, tmp
, fncall1
, fncall0
);
5828 se
->expr
= NULL_TREE
;
5829 argse
.expr
= fold_build2_loc (input_location
, MINUS_EXPR
,
5830 gfc_array_index_type
,
5831 argse
.expr
, gfc_index_one_node
);
5834 else if (expr
->value
.function
.actual
->expr
->rank
== 1)
5836 argse
.expr
= gfc_index_zero_node
;
5837 se
->expr
= NULL_TREE
;
5842 if (se
->expr
== NULL_TREE
)
5844 tree ubound
, lbound
;
5846 arg1
= build_fold_indirect_ref_loc (input_location
,
5848 ubound
= gfc_conv_descriptor_ubound_get (arg1
, argse
.expr
);
5849 lbound
= gfc_conv_descriptor_lbound_get (arg1
, argse
.expr
);
5850 se
->expr
= fold_build2_loc (input_location
, MINUS_EXPR
,
5851 gfc_array_index_type
, ubound
, lbound
);
5852 se
->expr
= fold_build2_loc (input_location
, PLUS_EXPR
,
5853 gfc_array_index_type
,
5854 se
->expr
, gfc_index_one_node
);
5855 se
->expr
= fold_build2_loc (input_location
, MAX_EXPR
,
5856 gfc_array_index_type
, se
->expr
,
5857 gfc_index_zero_node
);
5860 type
= gfc_typenode_for_spec (&expr
->ts
);
5861 se
->expr
= convert (type
, se
->expr
);
5865 /* Helper function to compute the size of a character variable,
5866 excluding the terminating null characters. The result has
5867 gfc_array_index_type type. */
5870 size_of_string_in_bytes (int kind
, tree string_length
)
5873 int i
= gfc_validate_kind (BT_CHARACTER
, kind
, false);
5875 bytesize
= build_int_cst (gfc_array_index_type
,
5876 gfc_character_kinds
[i
].bit_size
/ 8);
5878 return fold_build2_loc (input_location
, MULT_EXPR
, gfc_array_index_type
,
5880 fold_convert (gfc_array_index_type
, string_length
));
5885 gfc_conv_intrinsic_sizeof (gfc_se
*se
, gfc_expr
*expr
)
5896 gfc_init_se (&argse
, NULL
);
5897 arg
= expr
->value
.function
.actual
->expr
;
5899 if (arg
->rank
|| arg
->ts
.type
== BT_ASSUMED
)
5900 gfc_conv_expr_descriptor (&argse
, arg
);
5902 gfc_conv_expr_reference (&argse
, arg
);
5904 if (arg
->ts
.type
== BT_ASSUMED
)
5906 /* This only works if an array descriptor has been passed; thus, extract
5907 the size from the descriptor. */
5908 gcc_assert (TYPE_PRECISION (gfc_array_index_type
)
5909 == TYPE_PRECISION (size_type_node
));
5910 tmp
= arg
->symtree
->n
.sym
->backend_decl
;
5911 tmp
= DECL_LANG_SPECIFIC (tmp
)
5912 && GFC_DECL_SAVED_DESCRIPTOR (tmp
) != NULL_TREE
5913 ? GFC_DECL_SAVED_DESCRIPTOR (tmp
) : tmp
;
5914 if (POINTER_TYPE_P (TREE_TYPE (tmp
)))
5915 tmp
= build_fold_indirect_ref_loc (input_location
, tmp
);
5916 tmp
= fold_convert (size_type_node
, gfc_conv_descriptor_dtype (tmp
));
5917 tmp
= fold_build2_loc (input_location
, RSHIFT_EXPR
, TREE_TYPE (tmp
), tmp
,
5918 build_int_cst (TREE_TYPE (tmp
),
5919 GFC_DTYPE_SIZE_SHIFT
));
5920 byte_size
= fold_convert (gfc_array_index_type
, tmp
);
5922 else if (arg
->ts
.type
== BT_CLASS
)
5924 /* For deferred length arrays, conv_expr_descriptor returns an
5925 indirect_ref to the component. */
5927 || (arg
->rank
> 0 && !VAR_P (argse
.expr
)
5928 && GFC_DECL_CLASS (TREE_OPERAND (argse
.expr
, 0))))
5929 byte_size
= gfc_class_vtab_size_get (TREE_OPERAND (argse
.expr
, 0));
5930 else if (arg
->rank
> 0)
5931 /* The scalarizer added an additional temp. To get the class' vptr
5932 one has to look at the original backend_decl. */
5933 byte_size
= gfc_class_vtab_size_get (
5934 GFC_DECL_SAVED_DESCRIPTOR (arg
->symtree
->n
.sym
->backend_decl
));
5936 byte_size
= gfc_class_vtab_size_get (argse
.expr
);
5940 if (arg
->ts
.type
== BT_CHARACTER
)
5941 byte_size
= size_of_string_in_bytes (arg
->ts
.kind
, argse
.string_length
);
5945 byte_size
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
5948 byte_size
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
5949 byte_size
= fold_convert (gfc_array_index_type
,
5950 size_in_bytes (byte_size
));
5955 se
->expr
= byte_size
;
5958 source_bytes
= gfc_create_var (gfc_array_index_type
, "bytes");
5959 gfc_add_modify (&argse
.pre
, source_bytes
, byte_size
);
5961 if (arg
->rank
== -1)
5963 tree cond
, loop_var
, exit_label
;
5966 tmp
= fold_convert (gfc_array_index_type
,
5967 gfc_conv_descriptor_rank (argse
.expr
));
5968 loop_var
= gfc_create_var (gfc_array_index_type
, "i");
5969 gfc_add_modify (&argse
.pre
, loop_var
, gfc_index_zero_node
);
5970 exit_label
= gfc_build_label_decl (NULL_TREE
);
5977 source_bytes = source_bytes * array.dim[i].extent;
5981 gfc_start_block (&body
);
5982 cond
= fold_build2_loc (input_location
, GE_EXPR
, boolean_type_node
,
5984 tmp
= build1_v (GOTO_EXPR
, exit_label
);
5985 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
,
5986 cond
, tmp
, build_empty_stmt (input_location
));
5987 gfc_add_expr_to_block (&body
, tmp
);
5989 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, loop_var
);
5990 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, loop_var
);
5991 tmp
= gfc_conv_array_extent_dim (lower
, upper
, NULL
);
5992 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
5993 gfc_array_index_type
, tmp
, source_bytes
);
5994 gfc_add_modify (&body
, source_bytes
, tmp
);
5996 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
5997 gfc_array_index_type
, loop_var
,
5998 gfc_index_one_node
);
5999 gfc_add_modify_loc (input_location
, &body
, loop_var
, tmp
);
6001 tmp
= gfc_finish_block (&body
);
6003 tmp
= fold_build1_loc (input_location
, LOOP_EXPR
, void_type_node
,
6005 gfc_add_expr_to_block (&argse
.pre
, tmp
);
6007 tmp
= build1_v (LABEL_EXPR
, exit_label
);
6008 gfc_add_expr_to_block (&argse
.pre
, tmp
);
6012 /* Obtain the size of the array in bytes. */
6013 for (n
= 0; n
< arg
->rank
; n
++)
6016 idx
= gfc_rank_cst
[n
];
6017 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, idx
);
6018 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, idx
);
6019 tmp
= gfc_conv_array_extent_dim (lower
, upper
, NULL
);
6020 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
6021 gfc_array_index_type
, tmp
, source_bytes
);
6022 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
6025 se
->expr
= source_bytes
;
6028 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6033 gfc_conv_intrinsic_storage_size (gfc_se
*se
, gfc_expr
*expr
)
6037 tree type
, result_type
, tmp
;
6039 arg
= expr
->value
.function
.actual
->expr
;
6041 gfc_init_se (&argse
, NULL
);
6042 result_type
= gfc_get_int_type (expr
->ts
.kind
);
6046 if (arg
->ts
.type
== BT_CLASS
)
6048 gfc_add_vptr_component (arg
);
6049 gfc_add_size_component (arg
);
6050 gfc_conv_expr (&argse
, arg
);
6051 tmp
= fold_convert (result_type
, argse
.expr
);
6055 gfc_conv_expr_reference (&argse
, arg
);
6056 type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
6061 argse
.want_pointer
= 0;
6062 gfc_conv_expr_descriptor (&argse
, arg
);
6063 if (arg
->ts
.type
== BT_CLASS
)
6066 tmp
= gfc_class_vtab_size_get (
6067 GFC_DECL_SAVED_DESCRIPTOR (arg
->symtree
->n
.sym
->backend_decl
));
6069 tmp
= gfc_class_vtab_size_get (TREE_OPERAND (argse
.expr
, 0));
6070 tmp
= fold_convert (result_type
, tmp
);
6073 type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
6076 /* Obtain the argument's word length. */
6077 if (arg
->ts
.type
== BT_CHARACTER
)
6078 tmp
= size_of_string_in_bytes (arg
->ts
.kind
, argse
.string_length
);
6080 tmp
= size_in_bytes (type
);
6081 tmp
= fold_convert (result_type
, tmp
);
6084 se
->expr
= fold_build2_loc (input_location
, MULT_EXPR
, result_type
, tmp
,
6085 build_int_cst (result_type
, BITS_PER_UNIT
));
6086 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6090 /* Intrinsic string comparison functions. */
6093 gfc_conv_intrinsic_strcmp (gfc_se
* se
, gfc_expr
* expr
, enum tree_code op
)
6097 gfc_conv_intrinsic_function_args (se
, expr
, args
, 4);
6100 = gfc_build_compare_string (args
[0], args
[1], args
[2], args
[3],
6101 expr
->value
.function
.actual
->expr
->ts
.kind
,
6103 se
->expr
= fold_build2_loc (input_location
, op
,
6104 gfc_typenode_for_spec (&expr
->ts
), se
->expr
,
6105 build_int_cst (TREE_TYPE (se
->expr
), 0));
6108 /* Generate a call to the adjustl/adjustr library function. */
6110 gfc_conv_intrinsic_adjust (gfc_se
* se
, gfc_expr
* expr
, tree fndecl
)
6118 gfc_conv_intrinsic_function_args (se
, expr
, &args
[1], 2);
6121 type
= TREE_TYPE (args
[2]);
6122 var
= gfc_conv_string_tmp (se
, type
, len
);
6125 tmp
= build_call_expr_loc (input_location
,
6126 fndecl
, 3, args
[0], args
[1], args
[2]);
6127 gfc_add_expr_to_block (&se
->pre
, tmp
);
6129 se
->string_length
= len
;
6133 /* Generate code for the TRANSFER intrinsic:
6135 DEST = TRANSFER (SOURCE, MOLD)
6137 typeof<DEST> = typeof<MOLD>
6142 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
6144 typeof<DEST> = typeof<MOLD>
6146 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
6147 sizeof (DEST(0) * SIZE). */
6149 gfc_conv_intrinsic_transfer (gfc_se
* se
, gfc_expr
* expr
)
6165 gfc_actual_arglist
*arg
;
6167 gfc_array_info
*info
;
6171 gfc_expr
*source_expr
, *mold_expr
;
6175 info
= &se
->ss
->info
->data
.array
;
6177 /* Convert SOURCE. The output from this stage is:-
6178 source_bytes = length of the source in bytes
6179 source = pointer to the source data. */
6180 arg
= expr
->value
.function
.actual
;
6181 source_expr
= arg
->expr
;
6183 /* Ensure double transfer through LOGICAL preserves all
6185 if (arg
->expr
->expr_type
== EXPR_FUNCTION
6186 && arg
->expr
->value
.function
.esym
== NULL
6187 && arg
->expr
->value
.function
.isym
!= NULL
6188 && arg
->expr
->value
.function
.isym
->id
== GFC_ISYM_TRANSFER
6189 && arg
->expr
->ts
.type
== BT_LOGICAL
6190 && expr
->ts
.type
!= arg
->expr
->ts
.type
)
6191 arg
->expr
->value
.function
.name
= "__transfer_in_transfer";
6193 gfc_init_se (&argse
, NULL
);
6195 source_bytes
= gfc_create_var (gfc_array_index_type
, NULL
);
6197 /* Obtain the pointer to source and the length of source in bytes. */
6198 if (arg
->expr
->rank
== 0)
6200 gfc_conv_expr_reference (&argse
, arg
->expr
);
6201 if (arg
->expr
->ts
.type
== BT_CLASS
)
6202 source
= gfc_class_data_get (argse
.expr
);
6204 source
= argse
.expr
;
6206 /* Obtain the source word length. */
6207 switch (arg
->expr
->ts
.type
)
6210 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
,
6211 argse
.string_length
);
6214 tmp
= gfc_class_vtab_size_get (argse
.expr
);
6217 source_type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
6219 tmp
= fold_convert (gfc_array_index_type
,
6220 size_in_bytes (source_type
));
6226 argse
.want_pointer
= 0;
6227 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
6228 source
= gfc_conv_descriptor_data_get (argse
.expr
);
6229 source_type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
6231 /* Repack the source if not simply contiguous. */
6232 if (!gfc_is_simply_contiguous (arg
->expr
, false))
6234 tmp
= gfc_build_addr_expr (NULL_TREE
, argse
.expr
);
6236 if (warn_array_temporaries
)
6237 gfc_warning (OPT_Warray_temporaries
,
6238 "Creating array temporary at %L", &expr
->where
);
6240 source
= build_call_expr_loc (input_location
,
6241 gfor_fndecl_in_pack
, 1, tmp
);
6242 source
= gfc_evaluate_now (source
, &argse
.pre
);
6244 /* Free the temporary. */
6245 gfc_start_block (&block
);
6246 tmp
= gfc_call_free (convert (pvoid_type_node
, source
));
6247 gfc_add_expr_to_block (&block
, tmp
);
6248 stmt
= gfc_finish_block (&block
);
6250 /* Clean up if it was repacked. */
6251 gfc_init_block (&block
);
6252 tmp
= gfc_conv_array_data (argse
.expr
);
6253 tmp
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
6255 tmp
= build3_v (COND_EXPR
, tmp
, stmt
,
6256 build_empty_stmt (input_location
));
6257 gfc_add_expr_to_block (&block
, tmp
);
6258 gfc_add_block_to_block (&block
, &se
->post
);
6259 gfc_init_block (&se
->post
);
6260 gfc_add_block_to_block (&se
->post
, &block
);
6263 /* Obtain the source word length. */
6264 if (arg
->expr
->ts
.type
== BT_CHARACTER
)
6265 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
,
6266 argse
.string_length
);
6268 tmp
= fold_convert (gfc_array_index_type
,
6269 size_in_bytes (source_type
));
6271 /* Obtain the size of the array in bytes. */
6272 extent
= gfc_create_var (gfc_array_index_type
, NULL
);
6273 for (n
= 0; n
< arg
->expr
->rank
; n
++)
6276 idx
= gfc_rank_cst
[n
];
6277 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
6278 lower
= gfc_conv_descriptor_lbound_get (argse
.expr
, idx
);
6279 upper
= gfc_conv_descriptor_ubound_get (argse
.expr
, idx
);
6280 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
6281 gfc_array_index_type
, upper
, lower
);
6282 gfc_add_modify (&argse
.pre
, extent
, tmp
);
6283 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
,
6284 gfc_array_index_type
, extent
,
6285 gfc_index_one_node
);
6286 tmp
= fold_build2_loc (input_location
, MULT_EXPR
,
6287 gfc_array_index_type
, tmp
, source_bytes
);
6291 gfc_add_modify (&argse
.pre
, source_bytes
, tmp
);
6292 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6293 gfc_add_block_to_block (&se
->post
, &argse
.post
);
6295 /* Now convert MOLD. The outputs are:
6296 mold_type = the TREE type of MOLD
6297 dest_word_len = destination word length in bytes. */
6299 mold_expr
= arg
->expr
;
6301 gfc_init_se (&argse
, NULL
);
6303 scalar_mold
= arg
->expr
->rank
== 0;
6305 if (arg
->expr
->rank
== 0)
6307 gfc_conv_expr_reference (&argse
, arg
->expr
);
6308 mold_type
= TREE_TYPE (build_fold_indirect_ref_loc (input_location
,
6313 gfc_init_se (&argse
, NULL
);
6314 argse
.want_pointer
= 0;
6315 gfc_conv_expr_descriptor (&argse
, arg
->expr
);
6316 mold_type
= gfc_get_element_type (TREE_TYPE (argse
.expr
));
6319 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6320 gfc_add_block_to_block (&se
->post
, &argse
.post
);
6322 if (strcmp (expr
->value
.function
.name
, "__transfer_in_transfer") == 0)
6324 /* If this TRANSFER is nested in another TRANSFER, use a type
6325 that preserves all bits. */
6326 if (arg
->expr
->ts
.type
== BT_LOGICAL
)
6327 mold_type
= gfc_get_int_type (arg
->expr
->ts
.kind
);
6330 /* Obtain the destination word length. */
6331 switch (arg
->expr
->ts
.type
)
6334 tmp
= size_of_string_in_bytes (arg
->expr
->ts
.kind
, argse
.string_length
);
6335 mold_type
= gfc_get_character_type_len (arg
->expr
->ts
.kind
, tmp
);
6338 tmp
= gfc_class_vtab_size_get (argse
.expr
);
6341 tmp
= fold_convert (gfc_array_index_type
, size_in_bytes (mold_type
));
6344 dest_word_len
= gfc_create_var (gfc_array_index_type
, NULL
);
6345 gfc_add_modify (&se
->pre
, dest_word_len
, tmp
);
6347 /* Finally convert SIZE, if it is present. */
6349 size_words
= gfc_create_var (gfc_array_index_type
, NULL
);
6353 gfc_init_se (&argse
, NULL
);
6354 gfc_conv_expr_reference (&argse
, arg
->expr
);
6355 tmp
= convert (gfc_array_index_type
,
6356 build_fold_indirect_ref_loc (input_location
,
6358 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6359 gfc_add_block_to_block (&se
->post
, &argse
.post
);
6364 /* Separate array and scalar results. */
6365 if (scalar_mold
&& tmp
== NULL_TREE
)
6366 goto scalar_transfer
;
6368 size_bytes
= gfc_create_var (gfc_array_index_type
, NULL
);
6369 if (tmp
!= NULL_TREE
)
6370 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, gfc_array_index_type
,
6371 tmp
, dest_word_len
);
6375 gfc_add_modify (&se
->pre
, size_bytes
, tmp
);
6376 gfc_add_modify (&se
->pre
, size_words
,
6377 fold_build2_loc (input_location
, CEIL_DIV_EXPR
,
6378 gfc_array_index_type
,
6379 size_bytes
, dest_word_len
));
6381 /* Evaluate the bounds of the result. If the loop range exists, we have
6382 to check if it is too large. If so, we modify loop->to be consistent
6383 with min(size, size(source)). Otherwise, size is made consistent with
6384 the loop range, so that the right number of bytes is transferred.*/
6385 n
= se
->loop
->order
[0];
6386 if (se
->loop
->to
[n
] != NULL_TREE
)
6388 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
6389 se
->loop
->to
[n
], se
->loop
->from
[n
]);
6390 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
6391 tmp
, gfc_index_one_node
);
6392 tmp
= fold_build2_loc (input_location
, MIN_EXPR
, gfc_array_index_type
,
6394 gfc_add_modify (&se
->pre
, size_words
, tmp
);
6395 gfc_add_modify (&se
->pre
, size_bytes
,
6396 fold_build2_loc (input_location
, MULT_EXPR
,
6397 gfc_array_index_type
,
6398 size_words
, dest_word_len
));
6399 upper
= fold_build2_loc (input_location
, PLUS_EXPR
, gfc_array_index_type
,
6400 size_words
, se
->loop
->from
[n
]);
6401 upper
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
6402 upper
, gfc_index_one_node
);
6406 upper
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
6407 size_words
, gfc_index_one_node
);
6408 se
->loop
->from
[n
] = gfc_index_zero_node
;
6411 se
->loop
->to
[n
] = upper
;
6413 /* Build a destination descriptor, using the pointer, source, as the
6415 gfc_trans_create_temp_array (&se
->pre
, &se
->post
, se
->ss
, mold_type
,
6416 NULL_TREE
, false, true, false, &expr
->where
);
6418 /* Cast the pointer to the result. */
6419 tmp
= gfc_conv_descriptor_data_get (info
->descriptor
);
6420 tmp
= fold_convert (pvoid_type_node
, tmp
);
6422 /* Use memcpy to do the transfer. */
6424 = build_call_expr_loc (input_location
,
6425 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3, tmp
,
6426 fold_convert (pvoid_type_node
, source
),
6427 fold_convert (size_type_node
,
6428 fold_build2_loc (input_location
,
6430 gfc_array_index_type
,
6433 gfc_add_expr_to_block (&se
->pre
, tmp
);
6435 se
->expr
= info
->descriptor
;
6436 if (expr
->ts
.type
== BT_CHARACTER
)
6437 se
->string_length
= fold_convert (gfc_charlen_type_node
, dest_word_len
);
6441 /* Deal with scalar results. */
6443 extent
= fold_build2_loc (input_location
, MIN_EXPR
, gfc_array_index_type
,
6444 dest_word_len
, source_bytes
);
6445 extent
= fold_build2_loc (input_location
, MAX_EXPR
, gfc_array_index_type
,
6446 extent
, gfc_index_zero_node
);
6448 if (expr
->ts
.type
== BT_CHARACTER
)
6450 tree direct
, indirect
, free
;
6452 ptr
= convert (gfc_get_pchar_type (expr
->ts
.kind
), source
);
6453 tmpdecl
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
),
6456 /* If source is longer than the destination, use a pointer to
6457 the source directly. */
6458 gfc_init_block (&block
);
6459 gfc_add_modify (&block
, tmpdecl
, ptr
);
6460 direct
= gfc_finish_block (&block
);
6462 /* Otherwise, allocate a string with the length of the destination
6463 and copy the source into it. */
6464 gfc_init_block (&block
);
6465 tmp
= gfc_get_pchar_type (expr
->ts
.kind
);
6466 tmp
= gfc_call_malloc (&block
, tmp
, dest_word_len
);
6467 gfc_add_modify (&block
, tmpdecl
,
6468 fold_convert (TREE_TYPE (ptr
), tmp
));
6469 tmp
= build_call_expr_loc (input_location
,
6470 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3,
6471 fold_convert (pvoid_type_node
, tmpdecl
),
6472 fold_convert (pvoid_type_node
, ptr
),
6473 fold_convert (size_type_node
, extent
));
6474 gfc_add_expr_to_block (&block
, tmp
);
6475 indirect
= gfc_finish_block (&block
);
6477 /* Wrap it up with the condition. */
6478 tmp
= fold_build2_loc (input_location
, LE_EXPR
, boolean_type_node
,
6479 dest_word_len
, source_bytes
);
6480 tmp
= build3_v (COND_EXPR
, tmp
, direct
, indirect
);
6481 gfc_add_expr_to_block (&se
->pre
, tmp
);
6483 /* Free the temporary string, if necessary. */
6484 free
= gfc_call_free (tmpdecl
);
6485 tmp
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
6486 dest_word_len
, source_bytes
);
6487 tmp
= build3_v (COND_EXPR
, tmp
, free
, build_empty_stmt (input_location
));
6488 gfc_add_expr_to_block (&se
->post
, tmp
);
6491 se
->string_length
= fold_convert (gfc_charlen_type_node
, dest_word_len
);
6495 tmpdecl
= gfc_create_var (mold_type
, "transfer");
6497 ptr
= convert (build_pointer_type (mold_type
), source
);
6499 /* For CLASS results, allocate the needed memory first. */
6500 if (mold_expr
->ts
.type
== BT_CLASS
)
6503 cdata
= gfc_class_data_get (tmpdecl
);
6504 tmp
= gfc_call_malloc (&se
->pre
, TREE_TYPE (cdata
), dest_word_len
);
6505 gfc_add_modify (&se
->pre
, cdata
, tmp
);
6508 /* Use memcpy to do the transfer. */
6509 if (mold_expr
->ts
.type
== BT_CLASS
)
6510 tmp
= gfc_class_data_get (tmpdecl
);
6512 tmp
= gfc_build_addr_expr (NULL_TREE
, tmpdecl
);
6514 tmp
= build_call_expr_loc (input_location
,
6515 builtin_decl_explicit (BUILT_IN_MEMCPY
), 3,
6516 fold_convert (pvoid_type_node
, tmp
),
6517 fold_convert (pvoid_type_node
, ptr
),
6518 fold_convert (size_type_node
, extent
));
6519 gfc_add_expr_to_block (&se
->pre
, tmp
);
6521 /* For CLASS results, set the _vptr. */
6522 if (mold_expr
->ts
.type
== BT_CLASS
)
6526 vptr
= gfc_class_vptr_get (tmpdecl
);
6527 vtab
= gfc_find_derived_vtab (source_expr
->ts
.u
.derived
);
6529 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
6530 gfc_add_modify (&se
->pre
, vptr
, fold_convert (TREE_TYPE (vptr
), tmp
));
6538 /* Generate code for the ALLOCATED intrinsic.
6539 Generate inline code that directly check the address of the argument. */
6542 gfc_conv_allocated (gfc_se
*se
, gfc_expr
*expr
)
6544 gfc_actual_arglist
*arg1
;
6548 gfc_init_se (&arg1se
, NULL
);
6549 arg1
= expr
->value
.function
.actual
;
6551 if (arg1
->expr
->ts
.type
== BT_CLASS
)
6553 /* Make sure that class array expressions have both a _data
6554 component reference and an array reference.... */
6555 if (CLASS_DATA (arg1
->expr
)->attr
.dimension
)
6556 gfc_add_class_array_ref (arg1
->expr
);
6557 /* .... whilst scalars only need the _data component. */
6559 gfc_add_data_component (arg1
->expr
);
6562 if (arg1
->expr
->rank
== 0)
6564 /* Allocatable scalar. */
6565 arg1se
.want_pointer
= 1;
6566 gfc_conv_expr (&arg1se
, arg1
->expr
);
6571 /* Allocatable array. */
6572 arg1se
.descriptor_only
= 1;
6573 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
6574 tmp
= gfc_conv_descriptor_data_get (arg1se
.expr
);
6577 tmp
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
, tmp
,
6578 fold_convert (TREE_TYPE (tmp
), null_pointer_node
));
6579 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), tmp
);
6583 /* Generate code for the ASSOCIATED intrinsic.
6584 If both POINTER and TARGET are arrays, generate a call to library function
6585 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
6586 In other cases, generate inline code that directly compare the address of
6587 POINTER with the address of TARGET. */
6590 gfc_conv_associated (gfc_se
*se
, gfc_expr
*expr
)
6592 gfc_actual_arglist
*arg1
;
6593 gfc_actual_arglist
*arg2
;
6598 tree nonzero_charlen
;
6599 tree nonzero_arraylen
;
6603 gfc_init_se (&arg1se
, NULL
);
6604 gfc_init_se (&arg2se
, NULL
);
6605 arg1
= expr
->value
.function
.actual
;
6608 /* Check whether the expression is a scalar or not; we cannot use
6609 arg1->expr->rank as it can be nonzero for proc pointers. */
6610 ss
= gfc_walk_expr (arg1
->expr
);
6611 scalar
= ss
== gfc_ss_terminator
;
6613 gfc_free_ss_chain (ss
);
6617 /* No optional target. */
6620 /* A pointer to a scalar. */
6621 arg1se
.want_pointer
= 1;
6622 gfc_conv_expr (&arg1se
, arg1
->expr
);
6623 if (arg1
->expr
->symtree
->n
.sym
->attr
.proc_pointer
6624 && arg1
->expr
->symtree
->n
.sym
->attr
.dummy
)
6625 arg1se
.expr
= build_fold_indirect_ref_loc (input_location
,
6627 if (arg1
->expr
->ts
.type
== BT_CLASS
)
6629 tmp2
= gfc_class_data_get (arg1se
.expr
);
6630 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2
)))
6631 tmp2
= gfc_conv_descriptor_data_get (tmp2
);
6638 /* A pointer to an array. */
6639 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
6640 tmp2
= gfc_conv_descriptor_data_get (arg1se
.expr
);
6642 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
6643 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
6644 tmp
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
, tmp2
,
6645 fold_convert (TREE_TYPE (tmp2
), null_pointer_node
));
6650 /* An optional target. */
6651 if (arg2
->expr
->ts
.type
== BT_CLASS
)
6652 gfc_add_data_component (arg2
->expr
);
6654 nonzero_charlen
= NULL_TREE
;
6655 if (arg1
->expr
->ts
.type
== BT_CHARACTER
)
6656 nonzero_charlen
= fold_build2_loc (input_location
, NE_EXPR
,
6658 arg1
->expr
->ts
.u
.cl
->backend_decl
,
6662 /* A pointer to a scalar. */
6663 arg1se
.want_pointer
= 1;
6664 gfc_conv_expr (&arg1se
, arg1
->expr
);
6665 if (arg1
->expr
->symtree
->n
.sym
->attr
.proc_pointer
6666 && arg1
->expr
->symtree
->n
.sym
->attr
.dummy
)
6667 arg1se
.expr
= build_fold_indirect_ref_loc (input_location
,
6669 if (arg1
->expr
->ts
.type
== BT_CLASS
)
6670 arg1se
.expr
= gfc_class_data_get (arg1se
.expr
);
6672 arg2se
.want_pointer
= 1;
6673 gfc_conv_expr (&arg2se
, arg2
->expr
);
6674 if (arg2
->expr
->symtree
->n
.sym
->attr
.proc_pointer
6675 && arg2
->expr
->symtree
->n
.sym
->attr
.dummy
)
6676 arg2se
.expr
= build_fold_indirect_ref_loc (input_location
,
6678 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
6679 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
6680 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
6681 arg1se
.expr
, arg2se
.expr
);
6682 tmp2
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
6683 arg1se
.expr
, null_pointer_node
);
6684 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
6685 boolean_type_node
, tmp
, tmp2
);
6689 /* An array pointer of zero length is not associated if target is
6691 arg1se
.descriptor_only
= 1;
6692 gfc_conv_expr_lhs (&arg1se
, arg1
->expr
);
6693 if (arg1
->expr
->rank
== -1)
6695 tmp
= gfc_conv_descriptor_rank (arg1se
.expr
);
6696 tmp
= fold_build2_loc (input_location
, MINUS_EXPR
,
6697 TREE_TYPE (tmp
), tmp
, gfc_index_one_node
);
6700 tmp
= gfc_rank_cst
[arg1
->expr
->rank
- 1];
6701 tmp
= gfc_conv_descriptor_stride_get (arg1se
.expr
, tmp
);
6702 nonzero_arraylen
= fold_build2_loc (input_location
, NE_EXPR
,
6703 boolean_type_node
, tmp
,
6704 build_int_cst (TREE_TYPE (tmp
), 0));
6706 /* A pointer to an array, call library function _gfor_associated. */
6707 arg1se
.want_pointer
= 1;
6708 gfc_conv_expr_descriptor (&arg1se
, arg1
->expr
);
6710 arg2se
.want_pointer
= 1;
6711 gfc_conv_expr_descriptor (&arg2se
, arg2
->expr
);
6712 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
6713 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
6714 se
->expr
= build_call_expr_loc (input_location
,
6715 gfor_fndecl_associated
, 2,
6716 arg1se
.expr
, arg2se
.expr
);
6717 se
->expr
= convert (boolean_type_node
, se
->expr
);
6718 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
6719 boolean_type_node
, se
->expr
,
6723 /* If target is present zero character length pointers cannot
6725 if (nonzero_charlen
!= NULL_TREE
)
6726 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
6728 se
->expr
, nonzero_charlen
);
6731 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
6735 /* Generate code for the SAME_TYPE_AS intrinsic.
6736 Generate inline code that directly checks the vindices. */
6739 gfc_conv_same_type_as (gfc_se
*se
, gfc_expr
*expr
)
6744 tree conda
= NULL_TREE
, condb
= NULL_TREE
;
6746 gfc_init_se (&se1
, NULL
);
6747 gfc_init_se (&se2
, NULL
);
6749 a
= expr
->value
.function
.actual
->expr
;
6750 b
= expr
->value
.function
.actual
->next
->expr
;
6752 if (UNLIMITED_POLY (a
))
6754 tmp
= gfc_class_vptr_get (a
->symtree
->n
.sym
->backend_decl
);
6755 conda
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
6756 tmp
, build_int_cst (TREE_TYPE (tmp
), 0));
6759 if (UNLIMITED_POLY (b
))
6761 tmp
= gfc_class_vptr_get (b
->symtree
->n
.sym
->backend_decl
);
6762 condb
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
6763 tmp
, build_int_cst (TREE_TYPE (tmp
), 0));
6766 if (a
->ts
.type
== BT_CLASS
)
6768 gfc_add_vptr_component (a
);
6769 gfc_add_hash_component (a
);
6771 else if (a
->ts
.type
== BT_DERIVED
)
6772 a
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
,
6773 a
->ts
.u
.derived
->hash_value
);
6775 if (b
->ts
.type
== BT_CLASS
)
6777 gfc_add_vptr_component (b
);
6778 gfc_add_hash_component (b
);
6780 else if (b
->ts
.type
== BT_DERIVED
)
6781 b
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
,
6782 b
->ts
.u
.derived
->hash_value
);
6784 gfc_conv_expr (&se1
, a
);
6785 gfc_conv_expr (&se2
, b
);
6787 tmp
= fold_build2_loc (input_location
, EQ_EXPR
,
6788 boolean_type_node
, se1
.expr
,
6789 fold_convert (TREE_TYPE (se1
.expr
), se2
.expr
));
6792 tmp
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
6793 boolean_type_node
, conda
, tmp
);
6796 tmp
= fold_build2_loc (input_location
, TRUTH_ANDIF_EXPR
,
6797 boolean_type_node
, condb
, tmp
);
6799 se
->expr
= convert (gfc_typenode_for_spec (&expr
->ts
), tmp
);
6803 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
6806 gfc_conv_intrinsic_sc_kind (gfc_se
*se
, gfc_expr
*expr
)
6810 gfc_conv_intrinsic_function_args (se
, expr
, args
, 2);
6811 se
->expr
= build_call_expr_loc (input_location
,
6812 gfor_fndecl_sc_kind
, 2, args
[0], args
[1]);
6813 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
6817 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
6820 gfc_conv_intrinsic_si_kind (gfc_se
*se
, gfc_expr
*expr
)
6824 gfc_conv_intrinsic_function_args (se
, expr
, &arg
, 1);
6826 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
6827 type
= gfc_get_int_type (4);
6828 arg
= gfc_build_addr_expr (NULL_TREE
, fold_convert (type
, arg
));
6830 /* Convert it to the required type. */
6831 type
= gfc_typenode_for_spec (&expr
->ts
);
6832 se
->expr
= build_call_expr_loc (input_location
,
6833 gfor_fndecl_si_kind
, 1, arg
);
6834 se
->expr
= fold_convert (type
, se
->expr
);
6838 /* Generate code for SELECTED_REAL_KIND (P, R, RADIX) intrinsic function. */
6841 gfc_conv_intrinsic_sr_kind (gfc_se
*se
, gfc_expr
*expr
)
6843 gfc_actual_arglist
*actual
;
6846 vec
<tree
, va_gc
> *args
= NULL
;
6848 for (actual
= expr
->value
.function
.actual
; actual
; actual
= actual
->next
)
6850 gfc_init_se (&argse
, se
);
6852 /* Pass a NULL pointer for an absent arg. */
6853 if (actual
->expr
== NULL
)
6854 argse
.expr
= null_pointer_node
;
6860 if (actual
->expr
->ts
.kind
!= gfc_c_int_kind
)
6862 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
6863 ts
.type
= BT_INTEGER
;
6864 ts
.kind
= gfc_c_int_kind
;
6865 gfc_convert_type (actual
->expr
, &ts
, 2);
6867 gfc_conv_expr_reference (&argse
, actual
->expr
);
6870 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
6871 gfc_add_block_to_block (&se
->post
, &argse
.post
);
6872 vec_safe_push (args
, argse
.expr
);
6875 /* Convert it to the required type. */
6876 type
= gfc_typenode_for_spec (&expr
->ts
);
6877 se
->expr
= build_call_expr_loc_vec (input_location
,
6878 gfor_fndecl_sr_kind
, args
);
6879 se
->expr
= fold_convert (type
, se
->expr
);
6883 /* Generate code for TRIM (A) intrinsic function. */
6886 gfc_conv_intrinsic_trim (gfc_se
* se
, gfc_expr
* expr
)
6896 unsigned int num_args
;
6898 num_args
= gfc_intrinsic_argument_list_length (expr
) + 2;
6899 args
= XALLOCAVEC (tree
, num_args
);
6901 var
= gfc_create_var (gfc_get_pchar_type (expr
->ts
.kind
), "pstr");
6902 addr
= gfc_build_addr_expr (ppvoid_type_node
, var
);
6903 len
= gfc_create_var (gfc_charlen_type_node
, "len");
6905 gfc_conv_intrinsic_function_args (se
, expr
, &args
[2], num_args
- 2);
6906 args
[0] = gfc_build_addr_expr (NULL_TREE
, len
);
6909 if (expr
->ts
.kind
== 1)
6910 function
= gfor_fndecl_string_trim
;
6911 else if (expr
->ts
.kind
== 4)
6912 function
= gfor_fndecl_string_trim_char4
;
6916 fndecl
= build_addr (function
, current_function_decl
);
6917 tmp
= build_call_array_loc (input_location
,
6918 TREE_TYPE (TREE_TYPE (function
)), fndecl
,
6920 gfc_add_expr_to_block (&se
->pre
, tmp
);
6922 /* Free the temporary afterwards, if necessary. */
6923 cond
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
6924 len
, build_int_cst (TREE_TYPE (len
), 0));
6925 tmp
= gfc_call_free (var
);
6926 tmp
= build3_v (COND_EXPR
, cond
, tmp
, build_empty_stmt (input_location
));
6927 gfc_add_expr_to_block (&se
->post
, tmp
);
6930 se
->string_length
= len
;
6934 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
6937 gfc_conv_intrinsic_repeat (gfc_se
* se
, gfc_expr
* expr
)
6939 tree args
[3], ncopies
, dest
, dlen
, src
, slen
, ncopies_type
;
6940 tree type
, cond
, tmp
, count
, exit_label
, n
, max
, largest
;
6942 stmtblock_t block
, body
;
6945 /* We store in charsize the size of a character. */
6946 i
= gfc_validate_kind (BT_CHARACTER
, expr
->ts
.kind
, false);
6947 size
= build_int_cst (size_type_node
, gfc_character_kinds
[i
].bit_size
/ 8);
6949 /* Get the arguments. */
6950 gfc_conv_intrinsic_function_args (se
, expr
, args
, 3);
6951 slen
= fold_convert (size_type_node
, gfc_evaluate_now (args
[0], &se
->pre
));
6953 ncopies
= gfc_evaluate_now (args
[2], &se
->pre
);
6954 ncopies_type
= TREE_TYPE (ncopies
);
6956 /* Check that NCOPIES is not negative. */
6957 cond
= fold_build2_loc (input_location
, LT_EXPR
, boolean_type_node
, ncopies
,
6958 build_int_cst (ncopies_type
, 0));
6959 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
6960 "Argument NCOPIES of REPEAT intrinsic is negative "
6961 "(its value is %ld)",
6962 fold_convert (long_integer_type_node
, ncopies
));
6964 /* If the source length is zero, any non negative value of NCOPIES
6965 is valid, and nothing happens. */
6966 n
= gfc_create_var (ncopies_type
, "ncopies");
6967 cond
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
, slen
,
6968 build_int_cst (size_type_node
, 0));
6969 tmp
= fold_build3_loc (input_location
, COND_EXPR
, ncopies_type
, cond
,
6970 build_int_cst (ncopies_type
, 0), ncopies
);
6971 gfc_add_modify (&se
->pre
, n
, tmp
);
6974 /* Check that ncopies is not too large: ncopies should be less than
6975 (or equal to) MAX / slen, where MAX is the maximal integer of
6976 the gfc_charlen_type_node type. If slen == 0, we need a special
6977 case to avoid the division by zero. */
6978 i
= gfc_validate_kind (BT_INTEGER
, gfc_charlen_int_kind
, false);
6979 max
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[i
].huge
, gfc_charlen_int_kind
);
6980 max
= fold_build2_loc (input_location
, TRUNC_DIV_EXPR
, size_type_node
,
6981 fold_convert (size_type_node
, max
), slen
);
6982 largest
= TYPE_PRECISION (size_type_node
) > TYPE_PRECISION (ncopies_type
)
6983 ? size_type_node
: ncopies_type
;
6984 cond
= fold_build2_loc (input_location
, GT_EXPR
, boolean_type_node
,
6985 fold_convert (largest
, ncopies
),
6986 fold_convert (largest
, max
));
6987 tmp
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
, slen
,
6988 build_int_cst (size_type_node
, 0));
6989 cond
= fold_build3_loc (input_location
, COND_EXPR
, boolean_type_node
, tmp
,
6990 boolean_false_node
, cond
);
6991 gfc_trans_runtime_check (true, false, cond
, &se
->pre
, &expr
->where
,
6992 "Argument NCOPIES of REPEAT intrinsic is too large");
6994 /* Compute the destination length. */
6995 dlen
= fold_build2_loc (input_location
, MULT_EXPR
, gfc_charlen_type_node
,
6996 fold_convert (gfc_charlen_type_node
, slen
),
6997 fold_convert (gfc_charlen_type_node
, ncopies
));
6998 type
= gfc_get_character_type (expr
->ts
.kind
, expr
->ts
.u
.cl
);
6999 dest
= gfc_conv_string_tmp (se
, build_pointer_type (type
), dlen
);
7001 /* Generate the code to do the repeat operation:
7002 for (i = 0; i < ncopies; i++)
7003 memmove (dest + (i * slen * size), src, slen*size); */
7004 gfc_start_block (&block
);
7005 count
= gfc_create_var (ncopies_type
, "count");
7006 gfc_add_modify (&block
, count
, build_int_cst (ncopies_type
, 0));
7007 exit_label
= gfc_build_label_decl (NULL_TREE
);
7009 /* Start the loop body. */
7010 gfc_start_block (&body
);
7012 /* Exit the loop if count >= ncopies. */
7013 cond
= fold_build2_loc (input_location
, GE_EXPR
, boolean_type_node
, count
,
7015 tmp
= build1_v (GOTO_EXPR
, exit_label
);
7016 TREE_USED (exit_label
) = 1;
7017 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
, tmp
,
7018 build_empty_stmt (input_location
));
7019 gfc_add_expr_to_block (&body
, tmp
);
7021 /* Call memmove (dest + (i*slen*size), src, slen*size). */
7022 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, gfc_charlen_type_node
,
7023 fold_convert (gfc_charlen_type_node
, slen
),
7024 fold_convert (gfc_charlen_type_node
, count
));
7025 tmp
= fold_build2_loc (input_location
, MULT_EXPR
, gfc_charlen_type_node
,
7026 tmp
, fold_convert (gfc_charlen_type_node
, size
));
7027 tmp
= fold_build_pointer_plus_loc (input_location
,
7028 fold_convert (pvoid_type_node
, dest
), tmp
);
7029 tmp
= build_call_expr_loc (input_location
,
7030 builtin_decl_explicit (BUILT_IN_MEMMOVE
),
7032 fold_build2_loc (input_location
, MULT_EXPR
,
7033 size_type_node
, slen
,
7034 fold_convert (size_type_node
,
7036 gfc_add_expr_to_block (&body
, tmp
);
7038 /* Increment count. */
7039 tmp
= fold_build2_loc (input_location
, PLUS_EXPR
, ncopies_type
,
7040 count
, build_int_cst (TREE_TYPE (count
), 1));
7041 gfc_add_modify (&body
, count
, tmp
);
7043 /* Build the loop. */
7044 tmp
= build1_v (LOOP_EXPR
, gfc_finish_block (&body
));
7045 gfc_add_expr_to_block (&block
, tmp
);
7047 /* Add the exit label. */
7048 tmp
= build1_v (LABEL_EXPR
, exit_label
);
7049 gfc_add_expr_to_block (&block
, tmp
);
7051 /* Finish the block. */
7052 tmp
= gfc_finish_block (&block
);
7053 gfc_add_expr_to_block (&se
->pre
, tmp
);
7055 /* Set the result value. */
7057 se
->string_length
= dlen
;
7061 /* Generate code for the IARGC intrinsic. */
7064 gfc_conv_intrinsic_iargc (gfc_se
* se
, gfc_expr
* expr
)
7070 /* Call the library function. This always returns an INTEGER(4). */
7071 fndecl
= gfor_fndecl_iargc
;
7072 tmp
= build_call_expr_loc (input_location
,
7075 /* Convert it to the required type. */
7076 type
= gfc_typenode_for_spec (&expr
->ts
);
7077 tmp
= fold_convert (type
, tmp
);
7083 /* The loc intrinsic returns the address of its argument as
7084 gfc_index_integer_kind integer. */
7087 gfc_conv_intrinsic_loc (gfc_se
* se
, gfc_expr
* expr
)
7092 gcc_assert (!se
->ss
);
7094 arg_expr
= expr
->value
.function
.actual
->expr
;
7095 if (arg_expr
->rank
== 0)
7097 if (arg_expr
->ts
.type
== BT_CLASS
)
7098 gfc_add_component_ref (arg_expr
, "_data");
7099 gfc_conv_expr_reference (se
, arg_expr
);
7102 gfc_conv_array_parameter (se
, arg_expr
, true, NULL
, NULL
, NULL
);
7103 se
->expr
= convert (gfc_get_int_type (gfc_index_integer_kind
), se
->expr
);
7105 /* Create a temporary variable for loc return value. Without this,
7106 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
7107 temp_var
= gfc_create_var (gfc_get_int_type (gfc_index_integer_kind
), NULL
);
7108 gfc_add_modify (&se
->pre
, temp_var
, se
->expr
);
7109 se
->expr
= temp_var
;
7113 /* The following routine generates code for the intrinsic
7114 functions from the ISO_C_BINDING module:
7120 conv_isocbinding_function (gfc_se
*se
, gfc_expr
*expr
)
7122 gfc_actual_arglist
*arg
= expr
->value
.function
.actual
;
7124 if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_LOC
)
7126 if (arg
->expr
->rank
== 0)
7127 gfc_conv_expr_reference (se
, arg
->expr
);
7128 else if (gfc_is_simply_contiguous (arg
->expr
, false))
7129 gfc_conv_array_parameter (se
, arg
->expr
, true, NULL
, NULL
, NULL
);
7132 gfc_conv_expr_descriptor (se
, arg
->expr
);
7133 se
->expr
= gfc_conv_descriptor_data_get (se
->expr
);
7136 /* TODO -- the following two lines shouldn't be necessary, but if
7137 they're removed, a bug is exposed later in the code path.
7138 This workaround was thus introduced, but will have to be
7139 removed; please see PR 35150 for details about the issue. */
7140 se
->expr
= convert (pvoid_type_node
, se
->expr
);
7141 se
->expr
= gfc_evaluate_now (se
->expr
, &se
->pre
);
7143 else if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_FUNLOC
)
7144 gfc_conv_expr_reference (se
, arg
->expr
);
7145 else if (expr
->value
.function
.isym
->id
== GFC_ISYM_C_ASSOCIATED
)
7150 /* Build the addr_expr for the first argument. The argument is
7151 already an *address* so we don't need to set want_pointer in
7153 gfc_init_se (&arg1se
, NULL
);
7154 gfc_conv_expr (&arg1se
, arg
->expr
);
7155 gfc_add_block_to_block (&se
->pre
, &arg1se
.pre
);
7156 gfc_add_block_to_block (&se
->post
, &arg1se
.post
);
7158 /* See if we were given two arguments. */
7159 if (arg
->next
->expr
== NULL
)
7160 /* Only given one arg so generate a null and do a
7161 not-equal comparison against the first arg. */
7162 se
->expr
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
7164 fold_convert (TREE_TYPE (arg1se
.expr
),
7165 null_pointer_node
));
7171 /* Given two arguments so build the arg2se from second arg. */
7172 gfc_init_se (&arg2se
, NULL
);
7173 gfc_conv_expr (&arg2se
, arg
->next
->expr
);
7174 gfc_add_block_to_block (&se
->pre
, &arg2se
.pre
);
7175 gfc_add_block_to_block (&se
->post
, &arg2se
.post
);
7177 /* Generate test to compare that the two args are equal. */
7178 eq_expr
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
,
7179 arg1se
.expr
, arg2se
.expr
);
7180 /* Generate test to ensure that the first arg is not null. */
7181 not_null_expr
= fold_build2_loc (input_location
, NE_EXPR
,
7183 arg1se
.expr
, null_pointer_node
);
7185 /* Finally, the generated test must check that both arg1 is not
7186 NULL and that it is equal to the second arg. */
7187 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
7189 not_null_expr
, eq_expr
);
7197 /* The following routine generates code for the intrinsic
7198 subroutines from the ISO_C_BINDING module:
7200 * C_F_PROCPOINTER. */
7203 conv_isocbinding_subroutine (gfc_code
*code
)
7210 tree desc
, dim
, tmp
, stride
, offset
;
7211 stmtblock_t body
, block
;
7213 gfc_actual_arglist
*arg
= code
->ext
.actual
;
7215 gfc_init_se (&se
, NULL
);
7216 gfc_init_se (&cptrse
, NULL
);
7217 gfc_conv_expr (&cptrse
, arg
->expr
);
7218 gfc_add_block_to_block (&se
.pre
, &cptrse
.pre
);
7219 gfc_add_block_to_block (&se
.post
, &cptrse
.post
);
7221 gfc_init_se (&fptrse
, NULL
);
7222 if (arg
->next
->expr
->rank
== 0)
7224 fptrse
.want_pointer
= 1;
7225 gfc_conv_expr (&fptrse
, arg
->next
->expr
);
7226 gfc_add_block_to_block (&se
.pre
, &fptrse
.pre
);
7227 gfc_add_block_to_block (&se
.post
, &fptrse
.post
);
7228 if (arg
->next
->expr
->symtree
->n
.sym
->attr
.proc_pointer
7229 && arg
->next
->expr
->symtree
->n
.sym
->attr
.dummy
)
7230 fptrse
.expr
= build_fold_indirect_ref_loc (input_location
,
7232 se
.expr
= fold_build2_loc (input_location
, MODIFY_EXPR
,
7233 TREE_TYPE (fptrse
.expr
),
7235 fold_convert (TREE_TYPE (fptrse
.expr
),
7237 gfc_add_expr_to_block (&se
.pre
, se
.expr
);
7238 gfc_add_block_to_block (&se
.pre
, &se
.post
);
7239 return gfc_finish_block (&se
.pre
);
7242 gfc_start_block (&block
);
7244 /* Get the descriptor of the Fortran pointer. */
7245 fptrse
.descriptor_only
= 1;
7246 gfc_conv_expr_descriptor (&fptrse
, arg
->next
->expr
);
7247 gfc_add_block_to_block (&block
, &fptrse
.pre
);
7250 /* Set data value, dtype, and offset. */
7251 tmp
= GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc
));
7252 gfc_conv_descriptor_data_set (&block
, desc
, fold_convert (tmp
, cptrse
.expr
));
7253 gfc_add_modify (&block
, gfc_conv_descriptor_dtype (desc
),
7254 gfc_get_dtype (TREE_TYPE (desc
)));
7256 /* Start scalarization of the bounds, using the shape argument. */
7258 shape_ss
= gfc_walk_expr (arg
->next
->next
->expr
);
7259 gcc_assert (shape_ss
!= gfc_ss_terminator
);
7260 gfc_init_se (&shapese
, NULL
);
7262 gfc_init_loopinfo (&loop
);
7263 gfc_add_ss_to_loop (&loop
, shape_ss
);
7264 gfc_conv_ss_startstride (&loop
);
7265 gfc_conv_loop_setup (&loop
, &arg
->next
->expr
->where
);
7266 gfc_mark_ss_chain_used (shape_ss
, 1);
7268 gfc_copy_loopinfo_to_se (&shapese
, &loop
);
7269 shapese
.ss
= shape_ss
;
7271 stride
= gfc_create_var (gfc_array_index_type
, "stride");
7272 offset
= gfc_create_var (gfc_array_index_type
, "offset");
7273 gfc_add_modify (&block
, stride
, gfc_index_one_node
);
7274 gfc_add_modify (&block
, offset
, gfc_index_zero_node
);
7277 gfc_start_scalarized_body (&loop
, &body
);
7279 dim
= fold_build2_loc (input_location
, MINUS_EXPR
, gfc_array_index_type
,
7280 loop
.loopvar
[0], loop
.from
[0]);
7282 /* Set bounds and stride. */
7283 gfc_conv_descriptor_lbound_set (&body
, desc
, dim
, gfc_index_one_node
);
7284 gfc_conv_descriptor_stride_set (&body
, desc
, dim
, stride
);
7286 gfc_conv_expr (&shapese
, arg
->next
->next
->expr
);
7287 gfc_add_block_to_block (&body
, &shapese
.pre
);
7288 gfc_conv_descriptor_ubound_set (&body
, desc
, dim
, shapese
.expr
);
7289 gfc_add_block_to_block (&body
, &shapese
.post
);
7291 /* Calculate offset. */
7292 gfc_add_modify (&body
, offset
,
7293 fold_build2_loc (input_location
, PLUS_EXPR
,
7294 gfc_array_index_type
, offset
, stride
));
7295 /* Update stride. */
7296 gfc_add_modify (&body
, stride
,
7297 fold_build2_loc (input_location
, MULT_EXPR
,
7298 gfc_array_index_type
, stride
,
7299 fold_convert (gfc_array_index_type
,
7301 /* Finish scalarization loop. */
7302 gfc_trans_scalarizing_loops (&loop
, &body
);
7303 gfc_add_block_to_block (&block
, &loop
.pre
);
7304 gfc_add_block_to_block (&block
, &loop
.post
);
7305 gfc_add_block_to_block (&block
, &fptrse
.post
);
7306 gfc_cleanup_loop (&loop
);
7308 gfc_add_modify (&block
, offset
,
7309 fold_build1_loc (input_location
, NEGATE_EXPR
,
7310 gfc_array_index_type
, offset
));
7311 gfc_conv_descriptor_offset_set (&block
, desc
, offset
);
7313 gfc_add_expr_to_block (&se
.pre
, gfc_finish_block (&block
));
7314 gfc_add_block_to_block (&se
.pre
, &se
.post
);
7315 return gfc_finish_block (&se
.pre
);
7319 /* Save and restore floating-point state. */
7322 gfc_save_fp_state (stmtblock_t
*block
)
7324 tree type
, fpstate
, tmp
;
7326 type
= build_array_type (char_type_node
,
7327 build_range_type (size_type_node
, size_zero_node
,
7328 size_int (GFC_FPE_STATE_BUFFER_SIZE
)));
7329 fpstate
= gfc_create_var (type
, "fpstate");
7330 fpstate
= gfc_build_addr_expr (pvoid_type_node
, fpstate
);
7332 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_ieee_procedure_entry
,
7334 gfc_add_expr_to_block (block
, tmp
);
7341 gfc_restore_fp_state (stmtblock_t
*block
, tree fpstate
)
7345 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_ieee_procedure_exit
,
7347 gfc_add_expr_to_block (block
, tmp
);
7351 /* Generate code for arguments of IEEE functions. */
7354 conv_ieee_function_args (gfc_se
*se
, gfc_expr
*expr
, tree
*argarray
,
7357 gfc_actual_arglist
*actual
;
7362 actual
= expr
->value
.function
.actual
;
7363 for (arg
= 0; arg
< nargs
; arg
++, actual
= actual
->next
)
7365 gcc_assert (actual
);
7368 gfc_init_se (&argse
, se
);
7369 gfc_conv_expr_val (&argse
, e
);
7371 gfc_add_block_to_block (&se
->pre
, &argse
.pre
);
7372 gfc_add_block_to_block (&se
->post
, &argse
.post
);
7373 argarray
[arg
] = argse
.expr
;
7378 /* Generate code for intrinsics IEEE_IS_NAN, IEEE_IS_FINITE,
7379 and IEEE_UNORDERED, which translate directly to GCC type-generic
7383 conv_intrinsic_ieee_builtin (gfc_se
* se
, gfc_expr
* expr
,
7384 enum built_in_function code
, int nargs
)
7387 gcc_assert ((unsigned) nargs
<= sizeof(args
)/sizeof(args
[0]));
7389 conv_ieee_function_args (se
, expr
, args
, nargs
);
7390 se
->expr
= build_call_expr_loc_array (input_location
,
7391 builtin_decl_explicit (code
),
7393 STRIP_TYPE_NOPS (se
->expr
);
7394 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
7398 /* Generate code for IEEE_IS_NORMAL intrinsic:
7399 IEEE_IS_NORMAL(x) --> (__builtin_isnormal(x) || x == 0) */
7402 conv_intrinsic_ieee_is_normal (gfc_se
* se
, gfc_expr
* expr
)
7404 tree arg
, isnormal
, iszero
;
7406 /* Convert arg, evaluate it only once. */
7407 conv_ieee_function_args (se
, expr
, &arg
, 1);
7408 arg
= gfc_evaluate_now (arg
, &se
->pre
);
7410 isnormal
= build_call_expr_loc (input_location
,
7411 builtin_decl_explicit (BUILT_IN_ISNORMAL
),
7413 iszero
= fold_build2_loc (input_location
, EQ_EXPR
, boolean_type_node
, arg
,
7414 build_real_from_int_cst (TREE_TYPE (arg
),
7415 integer_zero_node
));
7416 se
->expr
= fold_build2_loc (input_location
, TRUTH_OR_EXPR
,
7417 boolean_type_node
, isnormal
, iszero
);
7418 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
7422 /* Generate code for IEEE_IS_NEGATIVE intrinsic:
7423 IEEE_IS_NEGATIVE(x) --> (__builtin_signbit(x) && !__builtin_isnan(x)) */
7426 conv_intrinsic_ieee_is_negative (gfc_se
* se
, gfc_expr
* expr
)
7428 tree arg
, signbit
, isnan
, decl
;
7431 /* Convert arg, evaluate it only once. */
7432 conv_ieee_function_args (se
, expr
, &arg
, 1);
7433 arg
= gfc_evaluate_now (arg
, &se
->pre
);
7435 isnan
= build_call_expr_loc (input_location
,
7436 builtin_decl_explicit (BUILT_IN_ISNAN
),
7438 STRIP_TYPE_NOPS (isnan
);
7440 argprec
= TYPE_PRECISION (TREE_TYPE (arg
));
7441 decl
= builtin_decl_for_precision (BUILT_IN_SIGNBIT
, argprec
);
7442 signbit
= build_call_expr_loc (input_location
, decl
, 1, arg
);
7443 signbit
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
7444 signbit
, integer_zero_node
);
7446 se
->expr
= fold_build2_loc (input_location
, TRUTH_AND_EXPR
,
7447 boolean_type_node
, signbit
,
7448 fold_build1_loc (input_location
, TRUTH_NOT_EXPR
,
7449 TREE_TYPE(isnan
), isnan
));
7451 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), se
->expr
);
7455 /* Generate code for IEEE_LOGB and IEEE_RINT. */
7458 conv_intrinsic_ieee_logb_rint (gfc_se
* se
, gfc_expr
* expr
,
7459 enum built_in_function code
)
7461 tree arg
, decl
, call
, fpstate
;
7464 conv_ieee_function_args (se
, expr
, &arg
, 1);
7465 argprec
= TYPE_PRECISION (TREE_TYPE (arg
));
7466 decl
= builtin_decl_for_precision (code
, argprec
);
7468 /* Save floating-point state. */
7469 fpstate
= gfc_save_fp_state (&se
->pre
);
7471 /* Make the function call. */
7472 call
= build_call_expr_loc (input_location
, decl
, 1, arg
);
7473 se
->expr
= fold_convert (gfc_typenode_for_spec (&expr
->ts
), call
);
7475 /* Restore floating-point state. */
7476 gfc_restore_fp_state (&se
->post
, fpstate
);
7480 /* Generate code for IEEE_REM. */
7483 conv_intrinsic_ieee_rem (gfc_se
* se
, gfc_expr
* expr
)
7485 tree args
[2], decl
, call
, fpstate
;
7488 conv_ieee_function_args (se
, expr
, args
, 2);
7490 /* If arguments have unequal size, convert them to the larger. */
7491 if (TYPE_PRECISION (TREE_TYPE (args
[0]))
7492 > TYPE_PRECISION (TREE_TYPE (args
[1])))
7493 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
7494 else if (TYPE_PRECISION (TREE_TYPE (args
[1]))
7495 > TYPE_PRECISION (TREE_TYPE (args
[0])))
7496 args
[0] = fold_convert (TREE_TYPE (args
[1]), args
[0]);
7498 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
7499 decl
= builtin_decl_for_precision (BUILT_IN_REMAINDER
, argprec
);
7501 /* Save floating-point state. */
7502 fpstate
= gfc_save_fp_state (&se
->pre
);
7504 /* Make the function call. */
7505 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
7506 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
7508 /* Restore floating-point state. */
7509 gfc_restore_fp_state (&se
->post
, fpstate
);
7513 /* Generate code for IEEE_NEXT_AFTER. */
7516 conv_intrinsic_ieee_next_after (gfc_se
* se
, gfc_expr
* expr
)
7518 tree args
[2], decl
, call
, fpstate
;
7521 conv_ieee_function_args (se
, expr
, args
, 2);
7523 /* Result has the characteristics of first argument. */
7524 args
[1] = fold_convert (TREE_TYPE (args
[0]), args
[1]);
7525 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
7526 decl
= builtin_decl_for_precision (BUILT_IN_NEXTAFTER
, argprec
);
7528 /* Save floating-point state. */
7529 fpstate
= gfc_save_fp_state (&se
->pre
);
7531 /* Make the function call. */
7532 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
7533 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
7535 /* Restore floating-point state. */
7536 gfc_restore_fp_state (&se
->post
, fpstate
);
7540 /* Generate code for IEEE_SCALB. */
7543 conv_intrinsic_ieee_scalb (gfc_se
* se
, gfc_expr
* expr
)
7545 tree args
[2], decl
, call
, huge
, type
;
7548 conv_ieee_function_args (se
, expr
, args
, 2);
7550 /* Result has the characteristics of first argument. */
7551 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
7552 decl
= builtin_decl_for_precision (BUILT_IN_SCALBN
, argprec
);
7554 if (TYPE_PRECISION (TREE_TYPE (args
[1])) > TYPE_PRECISION (integer_type_node
))
7556 /* We need to fold the integer into the range of a C int. */
7557 args
[1] = gfc_evaluate_now (args
[1], &se
->pre
);
7558 type
= TREE_TYPE (args
[1]);
7560 n
= gfc_validate_kind (BT_INTEGER
, gfc_c_int_kind
, false);
7561 huge
= gfc_conv_mpz_to_tree (gfc_integer_kinds
[n
].huge
,
7563 huge
= fold_convert (type
, huge
);
7564 args
[1] = fold_build2_loc (input_location
, MIN_EXPR
, type
, args
[1],
7566 args
[1] = fold_build2_loc (input_location
, MAX_EXPR
, type
, args
[1],
7567 fold_build1_loc (input_location
, NEGATE_EXPR
,
7571 args
[1] = fold_convert (integer_type_node
, args
[1]);
7573 /* Make the function call. */
7574 call
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
7575 se
->expr
= fold_convert (TREE_TYPE (args
[0]), call
);
7579 /* Generate code for IEEE_COPY_SIGN. */
7582 conv_intrinsic_ieee_copy_sign (gfc_se
* se
, gfc_expr
* expr
)
7584 tree args
[2], decl
, sign
;
7587 conv_ieee_function_args (se
, expr
, args
, 2);
7589 /* Get the sign of the second argument. */
7590 argprec
= TYPE_PRECISION (TREE_TYPE (args
[1]));
7591 decl
= builtin_decl_for_precision (BUILT_IN_SIGNBIT
, argprec
);
7592 sign
= build_call_expr_loc (input_location
, decl
, 1, args
[1]);
7593 sign
= fold_build2_loc (input_location
, NE_EXPR
, boolean_type_node
,
7594 sign
, integer_zero_node
);
7596 /* Create a value of one, with the right sign. */
7597 sign
= fold_build3_loc (input_location
, COND_EXPR
, integer_type_node
,
7599 fold_build1_loc (input_location
, NEGATE_EXPR
,
7603 args
[1] = fold_convert (TREE_TYPE (args
[0]), sign
);
7605 argprec
= TYPE_PRECISION (TREE_TYPE (args
[0]));
7606 decl
= builtin_decl_for_precision (BUILT_IN_COPYSIGN
, argprec
);
7608 se
->expr
= build_call_expr_loc_array (input_location
, decl
, 2, args
);
7612 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
7616 gfc_conv_ieee_arithmetic_function (gfc_se
* se
, gfc_expr
* expr
)
7618 const char *name
= expr
->value
.function
.name
;
7620 #define STARTS_WITH(A,B) (strncmp((A), (B), strlen(B)) == 0)
7622 if (STARTS_WITH (name
, "_gfortran_ieee_is_nan"))
7623 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISNAN
, 1);
7624 else if (STARTS_WITH (name
, "_gfortran_ieee_is_finite"))
7625 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISFINITE
, 1);
7626 else if (STARTS_WITH (name
, "_gfortran_ieee_unordered"))
7627 conv_intrinsic_ieee_builtin (se
, expr
, BUILT_IN_ISUNORDERED
, 2);
7628 else if (STARTS_WITH (name
, "_gfortran_ieee_is_normal"))
7629 conv_intrinsic_ieee_is_normal (se
, expr
);
7630 else if (STARTS_WITH (name
, "_gfortran_ieee_is_negative"))
7631 conv_intrinsic_ieee_is_negative (se
, expr
);
7632 else if (STARTS_WITH (name
, "_gfortran_ieee_copy_sign"))
7633 conv_intrinsic_ieee_copy_sign (se
, expr
);
7634 else if (STARTS_WITH (name
, "_gfortran_ieee_scalb"))
7635 conv_intrinsic_ieee_scalb (se
, expr
);
7636 else if (STARTS_WITH (name
, "_gfortran_ieee_next_after"))
7637 conv_intrinsic_ieee_next_after (se
, expr
);
7638 else if (STARTS_WITH (name
, "_gfortran_ieee_rem"))
7639 conv_intrinsic_ieee_rem (se
, expr
);
7640 else if (STARTS_WITH (name
, "_gfortran_ieee_logb"))
7641 conv_intrinsic_ieee_logb_rint (se
, expr
, BUILT_IN_LOGB
);
7642 else if (STARTS_WITH (name
, "_gfortran_ieee_rint"))
7643 conv_intrinsic_ieee_logb_rint (se
, expr
, BUILT_IN_RINT
);
7645 /* It is not among the functions we translate directly. We return
7646 false, so a library function call is emitted. */
7655 /* Generate code for an intrinsic function. Some map directly to library
7656 calls, others get special handling. In some cases the name of the function
7657 used depends on the type specifiers. */
7660 gfc_conv_intrinsic_function (gfc_se
* se
, gfc_expr
* expr
)
7666 name
= &expr
->value
.function
.name
[2];
7670 lib
= gfc_is_intrinsic_libcall (expr
);
7674 se
->ignore_optional
= 1;
7676 switch (expr
->value
.function
.isym
->id
)
7678 case GFC_ISYM_EOSHIFT
:
7680 case GFC_ISYM_RESHAPE
:
7681 /* For all of those the first argument specifies the type and the
7682 third is optional. */
7683 conv_generic_with_optional_char_arg (se
, expr
, 1, 3);
7687 gfc_conv_intrinsic_funcall (se
, expr
);
7695 switch (expr
->value
.function
.isym
->id
)
7700 case GFC_ISYM_REPEAT
:
7701 gfc_conv_intrinsic_repeat (se
, expr
);
7705 gfc_conv_intrinsic_trim (se
, expr
);
7708 case GFC_ISYM_SC_KIND
:
7709 gfc_conv_intrinsic_sc_kind (se
, expr
);
7712 case GFC_ISYM_SI_KIND
:
7713 gfc_conv_intrinsic_si_kind (se
, expr
);
7716 case GFC_ISYM_SR_KIND
:
7717 gfc_conv_intrinsic_sr_kind (se
, expr
);
7720 case GFC_ISYM_EXPONENT
:
7721 gfc_conv_intrinsic_exponent (se
, expr
);
7725 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
7727 fndecl
= gfor_fndecl_string_scan
;
7729 fndecl
= gfor_fndecl_string_scan_char4
;
7733 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
7736 case GFC_ISYM_VERIFY
:
7737 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
7739 fndecl
= gfor_fndecl_string_verify
;
7741 fndecl
= gfor_fndecl_string_verify_char4
;
7745 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
7748 case GFC_ISYM_ALLOCATED
:
7749 gfc_conv_allocated (se
, expr
);
7752 case GFC_ISYM_ASSOCIATED
:
7753 gfc_conv_associated(se
, expr
);
7756 case GFC_ISYM_SAME_TYPE_AS
:
7757 gfc_conv_same_type_as (se
, expr
);
7761 gfc_conv_intrinsic_abs (se
, expr
);
7764 case GFC_ISYM_ADJUSTL
:
7765 if (expr
->ts
.kind
== 1)
7766 fndecl
= gfor_fndecl_adjustl
;
7767 else if (expr
->ts
.kind
== 4)
7768 fndecl
= gfor_fndecl_adjustl_char4
;
7772 gfc_conv_intrinsic_adjust (se
, expr
, fndecl
);
7775 case GFC_ISYM_ADJUSTR
:
7776 if (expr
->ts
.kind
== 1)
7777 fndecl
= gfor_fndecl_adjustr
;
7778 else if (expr
->ts
.kind
== 4)
7779 fndecl
= gfor_fndecl_adjustr_char4
;
7783 gfc_conv_intrinsic_adjust (se
, expr
, fndecl
);
7786 case GFC_ISYM_AIMAG
:
7787 gfc_conv_intrinsic_imagpart (se
, expr
);
7791 gfc_conv_intrinsic_aint (se
, expr
, RND_TRUNC
);
7795 gfc_conv_intrinsic_anyall (se
, expr
, EQ_EXPR
);
7798 case GFC_ISYM_ANINT
:
7799 gfc_conv_intrinsic_aint (se
, expr
, RND_ROUND
);
7803 gfc_conv_intrinsic_bitop (se
, expr
, BIT_AND_EXPR
);
7807 gfc_conv_intrinsic_anyall (se
, expr
, NE_EXPR
);
7810 case GFC_ISYM_BTEST
:
7811 gfc_conv_intrinsic_btest (se
, expr
);
7815 gfc_conv_intrinsic_bitcomp (se
, expr
, GE_EXPR
);
7819 gfc_conv_intrinsic_bitcomp (se
, expr
, GT_EXPR
);
7823 gfc_conv_intrinsic_bitcomp (se
, expr
, LE_EXPR
);
7827 gfc_conv_intrinsic_bitcomp (se
, expr
, LT_EXPR
);
7830 case GFC_ISYM_C_ASSOCIATED
:
7831 case GFC_ISYM_C_FUNLOC
:
7832 case GFC_ISYM_C_LOC
:
7833 conv_isocbinding_function (se
, expr
);
7836 case GFC_ISYM_ACHAR
:
7838 gfc_conv_intrinsic_char (se
, expr
);
7841 case GFC_ISYM_CONVERSION
:
7843 case GFC_ISYM_LOGICAL
:
7845 gfc_conv_intrinsic_conversion (se
, expr
);
7848 /* Integer conversions are handled separately to make sure we get the
7849 correct rounding mode. */
7854 gfc_conv_intrinsic_int (se
, expr
, RND_TRUNC
);
7858 gfc_conv_intrinsic_int (se
, expr
, RND_ROUND
);
7861 case GFC_ISYM_CEILING
:
7862 gfc_conv_intrinsic_int (se
, expr
, RND_CEIL
);
7865 case GFC_ISYM_FLOOR
:
7866 gfc_conv_intrinsic_int (se
, expr
, RND_FLOOR
);
7870 gfc_conv_intrinsic_mod (se
, expr
, 0);
7873 case GFC_ISYM_MODULO
:
7874 gfc_conv_intrinsic_mod (se
, expr
, 1);
7877 case GFC_ISYM_CAF_GET
:
7878 gfc_conv_intrinsic_caf_get (se
, expr
, NULL_TREE
, NULL_TREE
, NULL_TREE
);
7881 case GFC_ISYM_CMPLX
:
7882 gfc_conv_intrinsic_cmplx (se
, expr
, name
[5] == '1');
7885 case GFC_ISYM_COMMAND_ARGUMENT_COUNT
:
7886 gfc_conv_intrinsic_iargc (se
, expr
);
7889 case GFC_ISYM_COMPLEX
:
7890 gfc_conv_intrinsic_cmplx (se
, expr
, 1);
7893 case GFC_ISYM_CONJG
:
7894 gfc_conv_intrinsic_conjg (se
, expr
);
7897 case GFC_ISYM_COUNT
:
7898 gfc_conv_intrinsic_count (se
, expr
);
7901 case GFC_ISYM_CTIME
:
7902 gfc_conv_intrinsic_ctime (se
, expr
);
7906 gfc_conv_intrinsic_dim (se
, expr
);
7909 case GFC_ISYM_DOT_PRODUCT
:
7910 gfc_conv_intrinsic_dot_product (se
, expr
);
7913 case GFC_ISYM_DPROD
:
7914 gfc_conv_intrinsic_dprod (se
, expr
);
7917 case GFC_ISYM_DSHIFTL
:
7918 gfc_conv_intrinsic_dshift (se
, expr
, true);
7921 case GFC_ISYM_DSHIFTR
:
7922 gfc_conv_intrinsic_dshift (se
, expr
, false);
7925 case GFC_ISYM_FDATE
:
7926 gfc_conv_intrinsic_fdate (se
, expr
);
7929 case GFC_ISYM_FRACTION
:
7930 gfc_conv_intrinsic_fraction (se
, expr
);
7934 gfc_conv_intrinsic_arith (se
, expr
, BIT_AND_EXPR
, false);
7938 gfc_conv_intrinsic_bitop (se
, expr
, BIT_AND_EXPR
);
7942 gfc_conv_intrinsic_arith (se
, expr
, BIT_IOR_EXPR
, false);
7945 case GFC_ISYM_IBCLR
:
7946 gfc_conv_intrinsic_singlebitop (se
, expr
, 0);
7949 case GFC_ISYM_IBITS
:
7950 gfc_conv_intrinsic_ibits (se
, expr
);
7953 case GFC_ISYM_IBSET
:
7954 gfc_conv_intrinsic_singlebitop (se
, expr
, 1);
7957 case GFC_ISYM_IACHAR
:
7958 case GFC_ISYM_ICHAR
:
7959 /* We assume ASCII character sequence. */
7960 gfc_conv_intrinsic_ichar (se
, expr
);
7963 case GFC_ISYM_IARGC
:
7964 gfc_conv_intrinsic_iargc (se
, expr
);
7968 gfc_conv_intrinsic_bitop (se
, expr
, BIT_XOR_EXPR
);
7971 case GFC_ISYM_INDEX
:
7972 kind
= expr
->value
.function
.actual
->expr
->ts
.kind
;
7974 fndecl
= gfor_fndecl_string_index
;
7976 fndecl
= gfor_fndecl_string_index_char4
;
7980 gfc_conv_intrinsic_index_scan_verify (se
, expr
, fndecl
);
7984 gfc_conv_intrinsic_bitop (se
, expr
, BIT_IOR_EXPR
);
7987 case GFC_ISYM_IPARITY
:
7988 gfc_conv_intrinsic_arith (se
, expr
, BIT_XOR_EXPR
, false);
7991 case GFC_ISYM_IS_IOSTAT_END
:
7992 gfc_conv_has_intvalue (se
, expr
, LIBERROR_END
);
7995 case GFC_ISYM_IS_IOSTAT_EOR
:
7996 gfc_conv_has_intvalue (se
, expr
, LIBERROR_EOR
);
7999 case GFC_ISYM_ISNAN
:
8000 gfc_conv_intrinsic_isnan (se
, expr
);
8003 case GFC_ISYM_LSHIFT
:
8004 gfc_conv_intrinsic_shift (se
, expr
, false, false);
8007 case GFC_ISYM_RSHIFT
:
8008 gfc_conv_intrinsic_shift (se
, expr
, true, true);
8011 case GFC_ISYM_SHIFTA
:
8012 gfc_conv_intrinsic_shift (se
, expr
, true, true);
8015 case GFC_ISYM_SHIFTL
:
8016 gfc_conv_intrinsic_shift (se
, expr
, false, false);
8019 case GFC_ISYM_SHIFTR
:
8020 gfc_conv_intrinsic_shift (se
, expr
, true, false);
8023 case GFC_ISYM_ISHFT
:
8024 gfc_conv_intrinsic_ishft (se
, expr
);
8027 case GFC_ISYM_ISHFTC
:
8028 gfc_conv_intrinsic_ishftc (se
, expr
);
8031 case GFC_ISYM_LEADZ
:
8032 gfc_conv_intrinsic_leadz (se
, expr
);
8035 case GFC_ISYM_TRAILZ
:
8036 gfc_conv_intrinsic_trailz (se
, expr
);
8039 case GFC_ISYM_POPCNT
:
8040 gfc_conv_intrinsic_popcnt_poppar (se
, expr
, 0);
8043 case GFC_ISYM_POPPAR
:
8044 gfc_conv_intrinsic_popcnt_poppar (se
, expr
, 1);
8047 case GFC_ISYM_LBOUND
:
8048 gfc_conv_intrinsic_bound (se
, expr
, 0);
8051 case GFC_ISYM_LCOBOUND
:
8052 conv_intrinsic_cobound (se
, expr
);
8055 case GFC_ISYM_TRANSPOSE
:
8056 /* The scalarizer has already been set up for reversed dimension access
8057 order ; now we just get the argument value normally. */
8058 gfc_conv_expr (se
, expr
->value
.function
.actual
->expr
);
8062 gfc_conv_intrinsic_len (se
, expr
);
8065 case GFC_ISYM_LEN_TRIM
:
8066 gfc_conv_intrinsic_len_trim (se
, expr
);
8070 gfc_conv_intrinsic_strcmp (se
, expr
, GE_EXPR
);
8074 gfc_conv_intrinsic_strcmp (se
, expr
, GT_EXPR
);
8078 gfc_conv_intrinsic_strcmp (se
, expr
, LE_EXPR
);
8082 gfc_conv_intrinsic_strcmp (se
, expr
, LT_EXPR
);
8085 case GFC_ISYM_MASKL
:
8086 gfc_conv_intrinsic_mask (se
, expr
, 1);
8089 case GFC_ISYM_MASKR
:
8090 gfc_conv_intrinsic_mask (se
, expr
, 0);
8094 if (expr
->ts
.type
== BT_CHARACTER
)
8095 gfc_conv_intrinsic_minmax_char (se
, expr
, 1);
8097 gfc_conv_intrinsic_minmax (se
, expr
, GT_EXPR
);
8100 case GFC_ISYM_MAXLOC
:
8101 gfc_conv_intrinsic_minmaxloc (se
, expr
, GT_EXPR
);
8104 case GFC_ISYM_MAXVAL
:
8105 gfc_conv_intrinsic_minmaxval (se
, expr
, GT_EXPR
);
8108 case GFC_ISYM_MERGE
:
8109 gfc_conv_intrinsic_merge (se
, expr
);
8112 case GFC_ISYM_MERGE_BITS
:
8113 gfc_conv_intrinsic_merge_bits (se
, expr
);
8117 if (expr
->ts
.type
== BT_CHARACTER
)
8118 gfc_conv_intrinsic_minmax_char (se
, expr
, -1);
8120 gfc_conv_intrinsic_minmax (se
, expr
, LT_EXPR
);
8123 case GFC_ISYM_MINLOC
:
8124 gfc_conv_intrinsic_minmaxloc (se
, expr
, LT_EXPR
);
8127 case GFC_ISYM_MINVAL
:
8128 gfc_conv_intrinsic_minmaxval (se
, expr
, LT_EXPR
);
8131 case GFC_ISYM_NEAREST
:
8132 gfc_conv_intrinsic_nearest (se
, expr
);
8135 case GFC_ISYM_NORM2
:
8136 gfc_conv_intrinsic_arith (se
, expr
, PLUS_EXPR
, true);
8140 gfc_conv_intrinsic_not (se
, expr
);
8144 gfc_conv_intrinsic_bitop (se
, expr
, BIT_IOR_EXPR
);
8147 case GFC_ISYM_PARITY
:
8148 gfc_conv_intrinsic_arith (se
, expr
, NE_EXPR
, false);
8151 case GFC_ISYM_PRESENT
:
8152 gfc_conv_intrinsic_present (se
, expr
);
8155 case GFC_ISYM_PRODUCT
:
8156 gfc_conv_intrinsic_arith (se
, expr
, MULT_EXPR
, false);
8160 gfc_conv_intrinsic_rank (se
, expr
);
8163 case GFC_ISYM_RRSPACING
:
8164 gfc_conv_intrinsic_rrspacing (se
, expr
);
8167 case GFC_ISYM_SET_EXPONENT
:
8168 gfc_conv_intrinsic_set_exponent (se
, expr
);
8171 case GFC_ISYM_SCALE
:
8172 gfc_conv_intrinsic_scale (se
, expr
);
8176 gfc_conv_intrinsic_sign (se
, expr
);
8180 gfc_conv_intrinsic_size (se
, expr
);
8183 case GFC_ISYM_SIZEOF
:
8184 case GFC_ISYM_C_SIZEOF
:
8185 gfc_conv_intrinsic_sizeof (se
, expr
);
8188 case GFC_ISYM_STORAGE_SIZE
:
8189 gfc_conv_intrinsic_storage_size (se
, expr
);
8192 case GFC_ISYM_SPACING
:
8193 gfc_conv_intrinsic_spacing (se
, expr
);
8196 case GFC_ISYM_STRIDE
:
8197 conv_intrinsic_stride (se
, expr
);
8201 gfc_conv_intrinsic_arith (se
, expr
, PLUS_EXPR
, false);
8204 case GFC_ISYM_TRANSFER
:
8205 if (se
->ss
&& se
->ss
->info
->useflags
)
8206 /* Access the previously obtained result. */
8207 gfc_conv_tmp_array_ref (se
);
8209 gfc_conv_intrinsic_transfer (se
, expr
);
8212 case GFC_ISYM_TTYNAM
:
8213 gfc_conv_intrinsic_ttynam (se
, expr
);
8216 case GFC_ISYM_UBOUND
:
8217 gfc_conv_intrinsic_bound (se
, expr
, 1);
8220 case GFC_ISYM_UCOBOUND
:
8221 conv_intrinsic_cobound (se
, expr
);
8225 gfc_conv_intrinsic_bitop (se
, expr
, BIT_XOR_EXPR
);
8229 gfc_conv_intrinsic_loc (se
, expr
);
8232 case GFC_ISYM_THIS_IMAGE
:
8233 /* For num_images() == 1, handle as LCOBOUND. */
8234 if (expr
->value
.function
.actual
->expr
8235 && flag_coarray
== GFC_FCOARRAY_SINGLE
)
8236 conv_intrinsic_cobound (se
, expr
);
8238 trans_this_image (se
, expr
);
8241 case GFC_ISYM_IMAGE_INDEX
:
8242 trans_image_index (se
, expr
);
8245 case GFC_ISYM_NUM_IMAGES
:
8246 trans_num_images (se
, expr
);
8249 case GFC_ISYM_ACCESS
:
8250 case GFC_ISYM_CHDIR
:
8251 case GFC_ISYM_CHMOD
:
8252 case GFC_ISYM_DTIME
:
8253 case GFC_ISYM_ETIME
:
8254 case GFC_ISYM_EXTENDS_TYPE_OF
:
8256 case GFC_ISYM_FGETC
:
8259 case GFC_ISYM_FPUTC
:
8260 case GFC_ISYM_FSTAT
:
8261 case GFC_ISYM_FTELL
:
8262 case GFC_ISYM_GETCWD
:
8263 case GFC_ISYM_GETGID
:
8264 case GFC_ISYM_GETPID
:
8265 case GFC_ISYM_GETUID
:
8266 case GFC_ISYM_HOSTNM
:
8268 case GFC_ISYM_IERRNO
:
8269 case GFC_ISYM_IRAND
:
8270 case GFC_ISYM_ISATTY
:
8273 case GFC_ISYM_LSTAT
:
8274 case GFC_ISYM_MALLOC
:
8275 case GFC_ISYM_MATMUL
:
8276 case GFC_ISYM_MCLOCK
:
8277 case GFC_ISYM_MCLOCK8
:
8279 case GFC_ISYM_RENAME
:
8280 case GFC_ISYM_SECOND
:
8281 case GFC_ISYM_SECNDS
:
8282 case GFC_ISYM_SIGNAL
:
8284 case GFC_ISYM_SYMLNK
:
8285 case GFC_ISYM_SYSTEM
:
8287 case GFC_ISYM_TIME8
:
8288 case GFC_ISYM_UMASK
:
8289 case GFC_ISYM_UNLINK
:
8291 gfc_conv_intrinsic_funcall (se
, expr
);
8294 case GFC_ISYM_EOSHIFT
:
8296 case GFC_ISYM_RESHAPE
:
8297 /* For those, expr->rank should always be >0 and thus the if above the
8298 switch should have matched. */
8303 gfc_conv_intrinsic_lib_function (se
, expr
);
8310 walk_inline_intrinsic_transpose (gfc_ss
*ss
, gfc_expr
*expr
)
8312 gfc_ss
*arg_ss
, *tmp_ss
;
8313 gfc_actual_arglist
*arg
;
8315 arg
= expr
->value
.function
.actual
;
8317 gcc_assert (arg
->expr
);
8319 arg_ss
= gfc_walk_subexpr (gfc_ss_terminator
, arg
->expr
);
8320 gcc_assert (arg_ss
!= gfc_ss_terminator
);
8322 for (tmp_ss
= arg_ss
; ; tmp_ss
= tmp_ss
->next
)
8324 if (tmp_ss
->info
->type
!= GFC_SS_SCALAR
8325 && tmp_ss
->info
->type
!= GFC_SS_REFERENCE
)
8329 gcc_assert (tmp_ss
->dimen
== 2);
8331 /* We just invert dimensions. */
8332 tmp_dim
= tmp_ss
->dim
[0];
8333 tmp_ss
->dim
[0] = tmp_ss
->dim
[1];
8334 tmp_ss
->dim
[1] = tmp_dim
;
8337 /* Stop when tmp_ss points to the last valid element of the chain... */
8338 if (tmp_ss
->next
== gfc_ss_terminator
)
8342 /* ... so that we can attach the rest of the chain to it. */
8349 /* Move the given dimension of the given gfc_ss list to a nested gfc_ss list.
8350 This has the side effect of reversing the nested list, so there is no
8351 need to call gfc_reverse_ss on it (the given list is assumed not to be
8355 nest_loop_dimension (gfc_ss
*ss
, int dim
)
8358 gfc_ss
*new_ss
, *prev_ss
= gfc_ss_terminator
;
8359 gfc_loopinfo
*new_loop
;
8361 gcc_assert (ss
!= gfc_ss_terminator
);
8363 for (; ss
!= gfc_ss_terminator
; ss
= ss
->next
)
8365 new_ss
= gfc_get_ss ();
8366 new_ss
->next
= prev_ss
;
8367 new_ss
->parent
= ss
;
8368 new_ss
->info
= ss
->info
;
8369 new_ss
->info
->refcount
++;
8372 gcc_assert (ss
->info
->type
!= GFC_SS_SCALAR
8373 && ss
->info
->type
!= GFC_SS_REFERENCE
);
8376 new_ss
->dim
[0] = ss
->dim
[dim
];
8378 gcc_assert (dim
< ss
->dimen
);
8380 ss_dim
= --ss
->dimen
;
8381 for (i
= dim
; i
< ss_dim
; i
++)
8382 ss
->dim
[i
] = ss
->dim
[i
+ 1];
8384 ss
->dim
[ss_dim
] = 0;
8390 ss
->nested_ss
->parent
= new_ss
;
8391 new_ss
->nested_ss
= ss
->nested_ss
;
8393 ss
->nested_ss
= new_ss
;
8396 new_loop
= gfc_get_loopinfo ();
8397 gfc_init_loopinfo (new_loop
);
8399 gcc_assert (prev_ss
!= NULL
);
8400 gcc_assert (prev_ss
!= gfc_ss_terminator
);
8401 gfc_add_ss_to_loop (new_loop
, prev_ss
);
8402 return new_ss
->parent
;
8406 /* Create the gfc_ss list for the SUM/PRODUCT arguments when the function
8407 is to be inlined. */
8410 walk_inline_intrinsic_arith (gfc_ss
*ss
, gfc_expr
*expr
)
8412 gfc_ss
*tmp_ss
, *tail
, *array_ss
;
8413 gfc_actual_arglist
*arg1
, *arg2
, *arg3
;
8415 bool scalar_mask
= false;
8417 /* The rank of the result will be determined later. */
8418 arg1
= expr
->value
.function
.actual
;
8421 gcc_assert (arg3
!= NULL
);
8423 if (expr
->rank
== 0)
8426 tmp_ss
= gfc_ss_terminator
;
8432 mask_ss
= gfc_walk_subexpr (tmp_ss
, arg3
->expr
);
8433 if (mask_ss
== tmp_ss
)
8439 array_ss
= gfc_walk_subexpr (tmp_ss
, arg1
->expr
);
8440 gcc_assert (array_ss
!= tmp_ss
);
8442 /* Odd thing: If the mask is scalar, it is used by the frontend after
8443 the array (to make an if around the nested loop). Thus it shall
8444 be after array_ss once the gfc_ss list is reversed. */
8446 tmp_ss
= gfc_get_scalar_ss (array_ss
, arg3
->expr
);
8450 /* "Hide" the dimension on which we will sum in the first arg's scalarization
8452 sum_dim
= mpz_get_si (arg2
->expr
->value
.integer
) - 1;
8453 tail
= nest_loop_dimension (tmp_ss
, sum_dim
);
8461 walk_inline_intrinsic_function (gfc_ss
* ss
, gfc_expr
* expr
)
8464 switch (expr
->value
.function
.isym
->id
)
8466 case GFC_ISYM_PRODUCT
:
8468 return walk_inline_intrinsic_arith (ss
, expr
);
8470 case GFC_ISYM_TRANSPOSE
:
8471 return walk_inline_intrinsic_transpose (ss
, expr
);
8480 /* This generates code to execute before entering the scalarization loop.
8481 Currently does nothing. */
8484 gfc_add_intrinsic_ss_code (gfc_loopinfo
* loop ATTRIBUTE_UNUSED
, gfc_ss
* ss
)
8486 switch (ss
->info
->expr
->value
.function
.isym
->id
)
8488 case GFC_ISYM_UBOUND
:
8489 case GFC_ISYM_LBOUND
:
8490 case GFC_ISYM_UCOBOUND
:
8491 case GFC_ISYM_LCOBOUND
:
8492 case GFC_ISYM_THIS_IMAGE
:
8501 /* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter
8502 are expanded into code inside the scalarization loop. */
8505 gfc_walk_intrinsic_bound (gfc_ss
* ss
, gfc_expr
* expr
)
8507 if (expr
->value
.function
.actual
->expr
->ts
.type
== BT_CLASS
)
8508 gfc_add_class_array_ref (expr
->value
.function
.actual
->expr
);
8510 /* The two argument version returns a scalar. */
8511 if (expr
->value
.function
.actual
->next
->expr
)
8514 return gfc_get_array_ss (ss
, expr
, 1, GFC_SS_INTRINSIC
);
8518 /* Walk an intrinsic array libcall. */
8521 gfc_walk_intrinsic_libfunc (gfc_ss
* ss
, gfc_expr
* expr
)
8523 gcc_assert (expr
->rank
> 0);
8524 return gfc_get_array_ss (ss
, expr
, expr
->rank
, GFC_SS_FUNCTION
);
8528 /* Return whether the function call expression EXPR will be expanded
8529 inline by gfc_conv_intrinsic_function. */
8532 gfc_inline_intrinsic_function_p (gfc_expr
*expr
)
8534 gfc_actual_arglist
*args
;
8536 if (!expr
->value
.function
.isym
)
8539 switch (expr
->value
.function
.isym
->id
)
8541 case GFC_ISYM_PRODUCT
:
8543 /* Disable inline expansion if code size matters. */
8547 args
= expr
->value
.function
.actual
;
8548 /* We need to be able to subset the SUM argument at compile-time. */
8549 if (args
->next
->expr
&& args
->next
->expr
->expr_type
!= EXPR_CONSTANT
)
8554 case GFC_ISYM_TRANSPOSE
:
8563 /* Returns nonzero if the specified intrinsic function call maps directly to
8564 an external library call. Should only be used for functions that return
8568 gfc_is_intrinsic_libcall (gfc_expr
* expr
)
8570 gcc_assert (expr
->expr_type
== EXPR_FUNCTION
&& expr
->value
.function
.isym
);
8571 gcc_assert (expr
->rank
> 0);
8573 if (gfc_inline_intrinsic_function_p (expr
))
8576 switch (expr
->value
.function
.isym
->id
)
8580 case GFC_ISYM_COUNT
:
8584 case GFC_ISYM_IPARITY
:
8585 case GFC_ISYM_MATMUL
:
8586 case GFC_ISYM_MAXLOC
:
8587 case GFC_ISYM_MAXVAL
:
8588 case GFC_ISYM_MINLOC
:
8589 case GFC_ISYM_MINVAL
:
8590 case GFC_ISYM_NORM2
:
8591 case GFC_ISYM_PARITY
:
8592 case GFC_ISYM_PRODUCT
:
8594 case GFC_ISYM_SHAPE
:
8595 case GFC_ISYM_SPREAD
:
8597 /* Ignore absent optional parameters. */
8600 case GFC_ISYM_RESHAPE
:
8601 case GFC_ISYM_CSHIFT
:
8602 case GFC_ISYM_EOSHIFT
:
8604 case GFC_ISYM_UNPACK
:
8605 /* Pass absent optional parameters. */
8613 /* Walk an intrinsic function. */
8615 gfc_walk_intrinsic_function (gfc_ss
* ss
, gfc_expr
* expr
,
8616 gfc_intrinsic_sym
* isym
)
8620 if (isym
->elemental
)
8621 return gfc_walk_elemental_function_args (ss
, expr
->value
.function
.actual
,
8622 NULL
, GFC_SS_SCALAR
);
8624 if (expr
->rank
== 0)
8627 if (gfc_inline_intrinsic_function_p (expr
))
8628 return walk_inline_intrinsic_function (ss
, expr
);
8630 if (gfc_is_intrinsic_libcall (expr
))
8631 return gfc_walk_intrinsic_libfunc (ss
, expr
);
8633 /* Special cases. */
8636 case GFC_ISYM_LBOUND
:
8637 case GFC_ISYM_LCOBOUND
:
8638 case GFC_ISYM_UBOUND
:
8639 case GFC_ISYM_UCOBOUND
:
8640 case GFC_ISYM_THIS_IMAGE
:
8641 return gfc_walk_intrinsic_bound (ss
, expr
);
8643 case GFC_ISYM_TRANSFER
:
8644 case GFC_ISYM_CAF_GET
:
8645 return gfc_walk_intrinsic_libfunc (ss
, expr
);
8648 /* This probably meant someone forgot to add an intrinsic to the above
8649 list(s) when they implemented it, or something's gone horribly
8657 conv_co_collective (gfc_code
*code
)
8660 stmtblock_t block
, post_block
;
8661 tree fndecl
, array
, strlen
, image_index
, stat
, errmsg
, errmsg_len
;
8662 gfc_expr
*image_idx_expr
, *stat_expr
, *errmsg_expr
, *opr_expr
;
8664 gfc_start_block (&block
);
8665 gfc_init_block (&post_block
);
8667 if (code
->resolved_isym
->id
== GFC_ISYM_CO_REDUCE
)
8669 opr_expr
= code
->ext
.actual
->next
->expr
;
8670 image_idx_expr
= code
->ext
.actual
->next
->next
->expr
;
8671 stat_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
8672 errmsg_expr
= code
->ext
.actual
->next
->next
->next
->next
->expr
;
8677 image_idx_expr
= code
->ext
.actual
->next
->expr
;
8678 stat_expr
= code
->ext
.actual
->next
->next
->expr
;
8679 errmsg_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
8685 gfc_init_se (&argse
, NULL
);
8686 gfc_conv_expr (&argse
, stat_expr
);
8687 gfc_add_block_to_block (&block
, &argse
.pre
);
8688 gfc_add_block_to_block (&post_block
, &argse
.post
);
8690 if (flag_coarray
!= GFC_FCOARRAY_SINGLE
)
8691 stat
= gfc_build_addr_expr (NULL_TREE
, stat
);
8693 else if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
8696 stat
= null_pointer_node
;
8698 /* Early exit for GFC_FCOARRAY_SINGLE. */
8699 if (flag_coarray
== GFC_FCOARRAY_SINGLE
)
8701 if (stat
!= NULL_TREE
)
8702 gfc_add_modify (&block
, stat
,
8703 fold_convert (TREE_TYPE (stat
), integer_zero_node
));
8704 return gfc_finish_block (&block
);
8707 /* Handle the array. */
8708 gfc_init_se (&argse
, NULL
);
8709 if (code
->ext
.actual
->expr
->rank
== 0)
8711 symbol_attribute attr
;
8712 gfc_clear_attr (&attr
);
8713 gfc_init_se (&argse
, NULL
);
8714 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
8715 gfc_add_block_to_block (&block
, &argse
.pre
);
8716 gfc_add_block_to_block (&post_block
, &argse
.post
);
8717 array
= gfc_conv_scalar_to_descriptor (&argse
, argse
.expr
, attr
);
8718 array
= gfc_build_addr_expr (NULL_TREE
, array
);
8722 argse
.want_pointer
= 1;
8723 gfc_conv_expr_descriptor (&argse
, code
->ext
.actual
->expr
);
8726 gfc_add_block_to_block (&block
, &argse
.pre
);
8727 gfc_add_block_to_block (&post_block
, &argse
.post
);
8729 if (code
->ext
.actual
->expr
->ts
.type
== BT_CHARACTER
)
8730 strlen
= argse
.string_length
;
8732 strlen
= integer_zero_node
;
8737 gfc_init_se (&argse
, NULL
);
8738 gfc_conv_expr (&argse
, image_idx_expr
);
8739 gfc_add_block_to_block (&block
, &argse
.pre
);
8740 gfc_add_block_to_block (&post_block
, &argse
.post
);
8741 image_index
= fold_convert (integer_type_node
, argse
.expr
);
8744 image_index
= integer_zero_node
;
8749 gfc_init_se (&argse
, NULL
);
8750 gfc_conv_expr (&argse
, errmsg_expr
);
8751 gfc_add_block_to_block (&block
, &argse
.pre
);
8752 gfc_add_block_to_block (&post_block
, &argse
.post
);
8753 errmsg
= argse
.expr
;
8754 errmsg_len
= fold_convert (integer_type_node
, argse
.string_length
);
8758 errmsg
= null_pointer_node
;
8759 errmsg_len
= integer_zero_node
;
8762 /* Generate the function call. */
8763 switch (code
->resolved_isym
->id
)
8765 case GFC_ISYM_CO_BROADCAST
:
8766 fndecl
= gfor_fndecl_co_broadcast
;
8768 case GFC_ISYM_CO_MAX
:
8769 fndecl
= gfor_fndecl_co_max
;
8771 case GFC_ISYM_CO_MIN
:
8772 fndecl
= gfor_fndecl_co_min
;
8774 case GFC_ISYM_CO_REDUCE
:
8775 fndecl
= gfor_fndecl_co_reduce
;
8777 case GFC_ISYM_CO_SUM
:
8778 fndecl
= gfor_fndecl_co_sum
;
8784 if (code
->resolved_isym
->id
== GFC_ISYM_CO_SUM
8785 || code
->resolved_isym
->id
== GFC_ISYM_CO_BROADCAST
)
8786 fndecl
= build_call_expr_loc (input_location
, fndecl
, 5, array
,
8787 image_index
, stat
, errmsg
, errmsg_len
);
8788 else if (code
->resolved_isym
->id
!= GFC_ISYM_CO_REDUCE
)
8789 fndecl
= build_call_expr_loc (input_location
, fndecl
, 6, array
, image_index
,
8790 stat
, errmsg
, strlen
, errmsg_len
);
8793 tree opr
, opr_flags
;
8795 // FIXME: Handle TS29113's bind(C) strings with descriptor.
8797 if (gfc_is_proc_ptr_comp (opr_expr
))
8799 gfc_symbol
*sym
= gfc_get_proc_ptr_comp (opr_expr
)->ts
.interface
;
8800 opr_flag_int
= sym
->attr
.dimension
8801 || (sym
->ts
.type
== BT_CHARACTER
8802 && !sym
->attr
.is_bind_c
)
8803 ? GFC_CAF_BYREF
: 0;
8804 opr_flag_int
|= opr_expr
->ts
.type
== BT_CHARACTER
8805 && !sym
->attr
.is_bind_c
8806 ? GFC_CAF_HIDDENLEN
: 0;
8807 opr_flag_int
|= sym
->formal
->sym
->attr
.value
? GFC_CAF_ARG_VALUE
: 0;
8811 opr_flag_int
= gfc_return_by_reference (opr_expr
->symtree
->n
.sym
)
8812 ? GFC_CAF_BYREF
: 0;
8813 opr_flag_int
|= opr_expr
->ts
.type
== BT_CHARACTER
8814 && !opr_expr
->symtree
->n
.sym
->attr
.is_bind_c
8815 ? GFC_CAF_HIDDENLEN
: 0;
8816 opr_flag_int
|= opr_expr
->symtree
->n
.sym
->formal
->sym
->attr
.value
8817 ? GFC_CAF_ARG_VALUE
: 0;
8819 opr_flags
= build_int_cst (integer_type_node
, opr_flag_int
);
8820 gfc_conv_expr (&argse
, opr_expr
);
8821 opr
= gfc_build_addr_expr (NULL_TREE
, argse
.expr
);
8822 fndecl
= build_call_expr_loc (input_location
, fndecl
, 8, array
, opr
, opr_flags
,
8823 image_index
, stat
, errmsg
, strlen
, errmsg_len
);
8826 gfc_add_expr_to_block (&block
, fndecl
);
8827 gfc_add_block_to_block (&block
, &post_block
);
8829 return gfc_finish_block (&block
);
8834 conv_intrinsic_atomic_op (gfc_code
*code
)
8837 tree tmp
, atom
, value
, old
= NULL_TREE
, stat
= NULL_TREE
;
8838 stmtblock_t block
, post_block
;
8839 gfc_expr
*atom_expr
= code
->ext
.actual
->expr
;
8840 gfc_expr
*stat_expr
;
8841 built_in_function fn
;
8843 if (atom_expr
->expr_type
== EXPR_FUNCTION
8844 && atom_expr
->value
.function
.isym
8845 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
8846 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
8848 gfc_start_block (&block
);
8849 gfc_init_block (&post_block
);
8851 gfc_init_se (&argse
, NULL
);
8852 argse
.want_pointer
= 1;
8853 gfc_conv_expr (&argse
, atom_expr
);
8854 gfc_add_block_to_block (&block
, &argse
.pre
);
8855 gfc_add_block_to_block (&post_block
, &argse
.post
);
8858 gfc_init_se (&argse
, NULL
);
8859 if (flag_coarray
== GFC_FCOARRAY_LIB
8860 && code
->ext
.actual
->next
->expr
->ts
.kind
== atom_expr
->ts
.kind
)
8861 argse
.want_pointer
= 1;
8862 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->expr
);
8863 gfc_add_block_to_block (&block
, &argse
.pre
);
8864 gfc_add_block_to_block (&post_block
, &argse
.post
);
8867 switch (code
->resolved_isym
->id
)
8869 case GFC_ISYM_ATOMIC_ADD
:
8870 case GFC_ISYM_ATOMIC_AND
:
8871 case GFC_ISYM_ATOMIC_DEF
:
8872 case GFC_ISYM_ATOMIC_OR
:
8873 case GFC_ISYM_ATOMIC_XOR
:
8874 stat_expr
= code
->ext
.actual
->next
->next
->expr
;
8875 if (flag_coarray
== GFC_FCOARRAY_LIB
)
8876 old
= null_pointer_node
;
8879 gfc_init_se (&argse
, NULL
);
8880 if (flag_coarray
== GFC_FCOARRAY_LIB
)
8881 argse
.want_pointer
= 1;
8882 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->expr
);
8883 gfc_add_block_to_block (&block
, &argse
.pre
);
8884 gfc_add_block_to_block (&post_block
, &argse
.post
);
8886 stat_expr
= code
->ext
.actual
->next
->next
->next
->expr
;
8890 if (stat_expr
!= NULL
)
8892 gcc_assert (stat_expr
->expr_type
== EXPR_VARIABLE
);
8893 gfc_init_se (&argse
, NULL
);
8894 if (flag_coarray
== GFC_FCOARRAY_LIB
)
8895 argse
.want_pointer
= 1;
8896 gfc_conv_expr_val (&argse
, stat_expr
);
8897 gfc_add_block_to_block (&block
, &argse
.pre
);
8898 gfc_add_block_to_block (&post_block
, &argse
.post
);
8901 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
8902 stat
= null_pointer_node
;
8904 if (flag_coarray
== GFC_FCOARRAY_LIB
)
8906 tree image_index
, caf_decl
, offset
, token
;
8909 switch (code
->resolved_isym
->id
)
8911 case GFC_ISYM_ATOMIC_ADD
:
8912 case GFC_ISYM_ATOMIC_FETCH_ADD
:
8913 op
= (int) GFC_CAF_ATOMIC_ADD
;
8915 case GFC_ISYM_ATOMIC_AND
:
8916 case GFC_ISYM_ATOMIC_FETCH_AND
:
8917 op
= (int) GFC_CAF_ATOMIC_AND
;
8919 case GFC_ISYM_ATOMIC_OR
:
8920 case GFC_ISYM_ATOMIC_FETCH_OR
:
8921 op
= (int) GFC_CAF_ATOMIC_OR
;
8923 case GFC_ISYM_ATOMIC_XOR
:
8924 case GFC_ISYM_ATOMIC_FETCH_XOR
:
8925 op
= (int) GFC_CAF_ATOMIC_XOR
;
8927 case GFC_ISYM_ATOMIC_DEF
:
8928 op
= 0; /* Unused. */
8934 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
8935 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
8936 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
8938 if (gfc_is_coindexed (atom_expr
))
8939 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
8941 image_index
= integer_zero_node
;
8943 if (!POINTER_TYPE_P (TREE_TYPE (value
)))
8945 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (atom
)), "value");
8946 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), value
));
8947 value
= gfc_build_addr_expr (NULL_TREE
, tmp
);
8950 gfc_get_caf_token_offset (&token
, &offset
, caf_decl
, atom
, atom_expr
);
8952 if (code
->resolved_isym
->id
== GFC_ISYM_ATOMIC_DEF
)
8953 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_def
, 7,
8954 token
, offset
, image_index
, value
, stat
,
8955 build_int_cst (integer_type_node
,
8956 (int) atom_expr
->ts
.type
),
8957 build_int_cst (integer_type_node
,
8958 (int) atom_expr
->ts
.kind
));
8960 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_op
, 9,
8961 build_int_cst (integer_type_node
, op
),
8962 token
, offset
, image_index
, value
, old
, stat
,
8963 build_int_cst (integer_type_node
,
8964 (int) atom_expr
->ts
.type
),
8965 build_int_cst (integer_type_node
,
8966 (int) atom_expr
->ts
.kind
));
8968 gfc_add_expr_to_block (&block
, tmp
);
8969 gfc_add_block_to_block (&block
, &post_block
);
8970 return gfc_finish_block (&block
);
8974 switch (code
->resolved_isym
->id
)
8976 case GFC_ISYM_ATOMIC_ADD
:
8977 case GFC_ISYM_ATOMIC_FETCH_ADD
:
8978 fn
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
8980 case GFC_ISYM_ATOMIC_AND
:
8981 case GFC_ISYM_ATOMIC_FETCH_AND
:
8982 fn
= BUILT_IN_ATOMIC_FETCH_AND_N
;
8984 case GFC_ISYM_ATOMIC_DEF
:
8985 fn
= BUILT_IN_ATOMIC_STORE_N
;
8987 case GFC_ISYM_ATOMIC_OR
:
8988 case GFC_ISYM_ATOMIC_FETCH_OR
:
8989 fn
= BUILT_IN_ATOMIC_FETCH_OR_N
;
8991 case GFC_ISYM_ATOMIC_XOR
:
8992 case GFC_ISYM_ATOMIC_FETCH_XOR
:
8993 fn
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
8999 tmp
= TREE_TYPE (TREE_TYPE (atom
));
9000 fn
= (built_in_function
) ((int) fn
9001 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
9003 tmp
= builtin_decl_explicit (fn
);
9004 tree itype
= TREE_TYPE (TREE_TYPE (atom
));
9005 tmp
= builtin_decl_explicit (fn
);
9007 switch (code
->resolved_isym
->id
)
9009 case GFC_ISYM_ATOMIC_ADD
:
9010 case GFC_ISYM_ATOMIC_AND
:
9011 case GFC_ISYM_ATOMIC_DEF
:
9012 case GFC_ISYM_ATOMIC_OR
:
9013 case GFC_ISYM_ATOMIC_XOR
:
9014 tmp
= build_call_expr_loc (input_location
, tmp
, 3, atom
,
9015 fold_convert (itype
, value
),
9016 build_int_cst (NULL
, MEMMODEL_RELAXED
));
9017 gfc_add_expr_to_block (&block
, tmp
);
9020 tmp
= build_call_expr_loc (input_location
, tmp
, 3, atom
,
9021 fold_convert (itype
, value
),
9022 build_int_cst (NULL
, MEMMODEL_RELAXED
));
9023 gfc_add_modify (&block
, old
, fold_convert (TREE_TYPE (old
), tmp
));
9027 if (stat
!= NULL_TREE
)
9028 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
9029 gfc_add_block_to_block (&block
, &post_block
);
9030 return gfc_finish_block (&block
);
9035 conv_intrinsic_atomic_ref (gfc_code
*code
)
9038 tree tmp
, atom
, value
, stat
= NULL_TREE
;
9039 stmtblock_t block
, post_block
;
9040 built_in_function fn
;
9041 gfc_expr
*atom_expr
= code
->ext
.actual
->next
->expr
;
9043 if (atom_expr
->expr_type
== EXPR_FUNCTION
9044 && atom_expr
->value
.function
.isym
9045 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
9046 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
9048 gfc_start_block (&block
);
9049 gfc_init_block (&post_block
);
9050 gfc_init_se (&argse
, NULL
);
9051 argse
.want_pointer
= 1;
9052 gfc_conv_expr (&argse
, atom_expr
);
9053 gfc_add_block_to_block (&block
, &argse
.pre
);
9054 gfc_add_block_to_block (&post_block
, &argse
.post
);
9057 gfc_init_se (&argse
, NULL
);
9058 if (flag_coarray
== GFC_FCOARRAY_LIB
9059 && code
->ext
.actual
->expr
->ts
.kind
== atom_expr
->ts
.kind
)
9060 argse
.want_pointer
= 1;
9061 gfc_conv_expr (&argse
, code
->ext
.actual
->expr
);
9062 gfc_add_block_to_block (&block
, &argse
.pre
);
9063 gfc_add_block_to_block (&post_block
, &argse
.post
);
9067 if (code
->ext
.actual
->next
->next
->expr
!= NULL
)
9069 gcc_assert (code
->ext
.actual
->next
->next
->expr
->expr_type
9071 gfc_init_se (&argse
, NULL
);
9072 if (flag_coarray
== GFC_FCOARRAY_LIB
)
9073 argse
.want_pointer
= 1;
9074 gfc_conv_expr_val (&argse
, code
->ext
.actual
->next
->next
->expr
);
9075 gfc_add_block_to_block (&block
, &argse
.pre
);
9076 gfc_add_block_to_block (&post_block
, &argse
.post
);
9079 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
9080 stat
= null_pointer_node
;
9082 if (flag_coarray
== GFC_FCOARRAY_LIB
)
9084 tree image_index
, caf_decl
, offset
, token
;
9085 tree orig_value
= NULL_TREE
, vardecl
= NULL_TREE
;
9087 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
9088 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
9089 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
9091 if (gfc_is_coindexed (atom_expr
))
9092 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
9094 image_index
= integer_zero_node
;
9096 gfc_get_caf_token_offset (&token
, &offset
, caf_decl
, atom
, atom_expr
);
9098 /* Different type, need type conversion. */
9099 if (!POINTER_TYPE_P (TREE_TYPE (value
)))
9101 vardecl
= gfc_create_var (TREE_TYPE (TREE_TYPE (atom
)), "value");
9103 value
= gfc_build_addr_expr (NULL_TREE
, vardecl
);
9106 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_ref
, 7,
9107 token
, offset
, image_index
, value
, stat
,
9108 build_int_cst (integer_type_node
,
9109 (int) atom_expr
->ts
.type
),
9110 build_int_cst (integer_type_node
,
9111 (int) atom_expr
->ts
.kind
));
9112 gfc_add_expr_to_block (&block
, tmp
);
9113 if (vardecl
!= NULL_TREE
)
9114 gfc_add_modify (&block
, orig_value
,
9115 fold_convert (TREE_TYPE (orig_value
), vardecl
));
9116 gfc_add_block_to_block (&block
, &post_block
);
9117 return gfc_finish_block (&block
);
9120 tmp
= TREE_TYPE (TREE_TYPE (atom
));
9121 fn
= (built_in_function
) ((int) BUILT_IN_ATOMIC_LOAD_N
9122 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
9124 tmp
= builtin_decl_explicit (fn
);
9125 tmp
= build_call_expr_loc (input_location
, tmp
, 2, atom
,
9126 build_int_cst (integer_type_node
,
9128 gfc_add_modify (&block
, value
, fold_convert (TREE_TYPE (value
), tmp
));
9130 if (stat
!= NULL_TREE
)
9131 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
9132 gfc_add_block_to_block (&block
, &post_block
);
9133 return gfc_finish_block (&block
);
9138 conv_intrinsic_atomic_cas (gfc_code
*code
)
9141 tree tmp
, atom
, old
, new_val
, comp
, stat
= NULL_TREE
;
9142 stmtblock_t block
, post_block
;
9143 built_in_function fn
;
9144 gfc_expr
*atom_expr
= code
->ext
.actual
->expr
;
9146 if (atom_expr
->expr_type
== EXPR_FUNCTION
9147 && atom_expr
->value
.function
.isym
9148 && atom_expr
->value
.function
.isym
->id
== GFC_ISYM_CAF_GET
)
9149 atom_expr
= atom_expr
->value
.function
.actual
->expr
;
9151 gfc_init_block (&block
);
9152 gfc_init_block (&post_block
);
9153 gfc_init_se (&argse
, NULL
);
9154 argse
.want_pointer
= 1;
9155 gfc_conv_expr (&argse
, atom_expr
);
9158 gfc_init_se (&argse
, NULL
);
9159 if (flag_coarray
== GFC_FCOARRAY_LIB
)
9160 argse
.want_pointer
= 1;
9161 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->expr
);
9162 gfc_add_block_to_block (&block
, &argse
.pre
);
9163 gfc_add_block_to_block (&post_block
, &argse
.post
);
9166 gfc_init_se (&argse
, NULL
);
9167 if (flag_coarray
== GFC_FCOARRAY_LIB
)
9168 argse
.want_pointer
= 1;
9169 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->expr
);
9170 gfc_add_block_to_block (&block
, &argse
.pre
);
9171 gfc_add_block_to_block (&post_block
, &argse
.post
);
9174 gfc_init_se (&argse
, NULL
);
9175 if (flag_coarray
== GFC_FCOARRAY_LIB
9176 && code
->ext
.actual
->next
->next
->next
->expr
->ts
.kind
9177 == atom_expr
->ts
.kind
)
9178 argse
.want_pointer
= 1;
9179 gfc_conv_expr (&argse
, code
->ext
.actual
->next
->next
->next
->expr
);
9180 gfc_add_block_to_block (&block
, &argse
.pre
);
9181 gfc_add_block_to_block (&post_block
, &argse
.post
);
9182 new_val
= argse
.expr
;
9185 if (code
->ext
.actual
->next
->next
->next
->next
->expr
!= NULL
)
9187 gcc_assert (code
->ext
.actual
->next
->next
->next
->next
->expr
->expr_type
9189 gfc_init_se (&argse
, NULL
);
9190 if (flag_coarray
== GFC_FCOARRAY_LIB
)
9191 argse
.want_pointer
= 1;
9192 gfc_conv_expr_val (&argse
,
9193 code
->ext
.actual
->next
->next
->next
->next
->expr
);
9194 gfc_add_block_to_block (&block
, &argse
.pre
);
9195 gfc_add_block_to_block (&post_block
, &argse
.post
);
9198 else if (flag_coarray
== GFC_FCOARRAY_LIB
)
9199 stat
= null_pointer_node
;
9201 if (flag_coarray
== GFC_FCOARRAY_LIB
)
9203 tree image_index
, caf_decl
, offset
, token
;
9205 caf_decl
= gfc_get_tree_for_caf_expr (atom_expr
);
9206 if (TREE_CODE (TREE_TYPE (caf_decl
)) == REFERENCE_TYPE
)
9207 caf_decl
= build_fold_indirect_ref_loc (input_location
, caf_decl
);
9209 if (gfc_is_coindexed (atom_expr
))
9210 image_index
= gfc_caf_get_image_index (&block
, atom_expr
, caf_decl
);
9212 image_index
= integer_zero_node
;
9214 if (TREE_TYPE (TREE_TYPE (new_val
)) != TREE_TYPE (TREE_TYPE (old
)))
9216 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (old
)), "new");
9217 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), new_val
));
9218 new_val
= gfc_build_addr_expr (NULL_TREE
, tmp
);
9221 /* Convert a constant to a pointer. */
9222 if (!POINTER_TYPE_P (TREE_TYPE (comp
)))
9224 tmp
= gfc_create_var (TREE_TYPE (TREE_TYPE (old
)), "comp");
9225 gfc_add_modify (&block
, tmp
, fold_convert (TREE_TYPE (tmp
), comp
));
9226 comp
= gfc_build_addr_expr (NULL_TREE
, tmp
);
9229 gfc_get_caf_token_offset (&token
, &offset
, caf_decl
, atom
, atom_expr
);
9231 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_atomic_cas
, 9,
9232 token
, offset
, image_index
, old
, comp
, new_val
,
9233 stat
, build_int_cst (integer_type_node
,
9234 (int) atom_expr
->ts
.type
),
9235 build_int_cst (integer_type_node
,
9236 (int) atom_expr
->ts
.kind
));
9237 gfc_add_expr_to_block (&block
, tmp
);
9238 gfc_add_block_to_block (&block
, &post_block
);
9239 return gfc_finish_block (&block
);
9242 tmp
= TREE_TYPE (TREE_TYPE (atom
));
9243 fn
= (built_in_function
) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N
9244 + exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp
)))
9246 tmp
= builtin_decl_explicit (fn
);
9248 gfc_add_modify (&block
, old
, comp
);
9249 tmp
= build_call_expr_loc (input_location
, tmp
, 6, atom
,
9250 gfc_build_addr_expr (NULL
, old
),
9251 fold_convert (TREE_TYPE (old
), new_val
),
9253 build_int_cst (NULL
, MEMMODEL_RELAXED
),
9254 build_int_cst (NULL
, MEMMODEL_RELAXED
));
9255 gfc_add_expr_to_block (&block
, tmp
);
9257 if (stat
!= NULL_TREE
)
9258 gfc_add_modify (&block
, stat
, build_int_cst (TREE_TYPE (stat
), 0));
9259 gfc_add_block_to_block (&block
, &post_block
);
9260 return gfc_finish_block (&block
);
9265 conv_intrinsic_move_alloc (gfc_code
*code
)
9268 gfc_expr
*from_expr
, *to_expr
;
9269 gfc_expr
*to_expr2
, *from_expr2
= NULL
;
9270 gfc_se from_se
, to_se
;
9274 gfc_start_block (&block
);
9276 from_expr
= code
->ext
.actual
->expr
;
9277 to_expr
= code
->ext
.actual
->next
->expr
;
9279 gfc_init_se (&from_se
, NULL
);
9280 gfc_init_se (&to_se
, NULL
);
9282 gcc_assert (from_expr
->ts
.type
!= BT_CLASS
9283 || to_expr
->ts
.type
== BT_CLASS
);
9284 coarray
= gfc_get_corank (from_expr
) != 0;
9286 if (from_expr
->rank
== 0 && !coarray
)
9288 if (from_expr
->ts
.type
!= BT_CLASS
)
9289 from_expr2
= from_expr
;
9292 from_expr2
= gfc_copy_expr (from_expr
);
9293 gfc_add_data_component (from_expr2
);
9296 if (to_expr
->ts
.type
!= BT_CLASS
)
9300 to_expr2
= gfc_copy_expr (to_expr
);
9301 gfc_add_data_component (to_expr2
);
9304 from_se
.want_pointer
= 1;
9305 to_se
.want_pointer
= 1;
9306 gfc_conv_expr (&from_se
, from_expr2
);
9307 gfc_conv_expr (&to_se
, to_expr2
);
9308 gfc_add_block_to_block (&block
, &from_se
.pre
);
9309 gfc_add_block_to_block (&block
, &to_se
.pre
);
9311 /* Deallocate "to". */
9312 tmp
= gfc_deallocate_scalar_with_status (to_se
.expr
, NULL_TREE
, true,
9313 to_expr
, to_expr
->ts
);
9314 gfc_add_expr_to_block (&block
, tmp
);
9316 /* Assign (_data) pointers. */
9317 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
9318 fold_convert (TREE_TYPE (to_se
.expr
), from_se
.expr
));
9320 /* Set "from" to NULL. */
9321 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
9322 fold_convert (TREE_TYPE (from_se
.expr
), null_pointer_node
));
9324 gfc_add_block_to_block (&block
, &from_se
.post
);
9325 gfc_add_block_to_block (&block
, &to_se
.post
);
9328 if (to_expr
->ts
.type
== BT_CLASS
)
9332 gfc_free_expr (to_expr2
);
9333 gfc_init_se (&to_se
, NULL
);
9334 to_se
.want_pointer
= 1;
9335 gfc_add_vptr_component (to_expr
);
9336 gfc_conv_expr (&to_se
, to_expr
);
9338 if (from_expr
->ts
.type
== BT_CLASS
)
9340 if (UNLIMITED_POLY (from_expr
))
9344 vtab
= gfc_find_derived_vtab (from_expr
->ts
.u
.derived
);
9348 gfc_free_expr (from_expr2
);
9349 gfc_init_se (&from_se
, NULL
);
9350 from_se
.want_pointer
= 1;
9351 gfc_add_vptr_component (from_expr
);
9352 gfc_conv_expr (&from_se
, from_expr
);
9353 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
9354 fold_convert (TREE_TYPE (to_se
.expr
),
9357 /* Reset _vptr component to declared type. */
9359 /* Unlimited polymorphic. */
9360 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
9361 fold_convert (TREE_TYPE (from_se
.expr
),
9362 null_pointer_node
));
9365 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
9366 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
9367 fold_convert (TREE_TYPE (from_se
.expr
), tmp
));
9372 vtab
= gfc_find_vtab (&from_expr
->ts
);
9374 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
9375 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
9376 fold_convert (TREE_TYPE (to_se
.expr
), tmp
));
9380 return gfc_finish_block (&block
);
9383 /* Update _vptr component. */
9384 if (to_expr
->ts
.type
== BT_CLASS
)
9388 to_se
.want_pointer
= 1;
9389 to_expr2
= gfc_copy_expr (to_expr
);
9390 gfc_add_vptr_component (to_expr2
);
9391 gfc_conv_expr (&to_se
, to_expr2
);
9393 if (from_expr
->ts
.type
== BT_CLASS
)
9395 if (UNLIMITED_POLY (from_expr
))
9399 vtab
= gfc_find_derived_vtab (from_expr
->ts
.u
.derived
);
9403 from_se
.want_pointer
= 1;
9404 from_expr2
= gfc_copy_expr (from_expr
);
9405 gfc_add_vptr_component (from_expr2
);
9406 gfc_conv_expr (&from_se
, from_expr2
);
9407 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
9408 fold_convert (TREE_TYPE (to_se
.expr
),
9411 /* Reset _vptr component to declared type. */
9413 /* Unlimited polymorphic. */
9414 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
9415 fold_convert (TREE_TYPE (from_se
.expr
),
9416 null_pointer_node
));
9419 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
9420 gfc_add_modify_loc (input_location
, &block
, from_se
.expr
,
9421 fold_convert (TREE_TYPE (from_se
.expr
), tmp
));
9426 vtab
= gfc_find_vtab (&from_expr
->ts
);
9428 tmp
= gfc_build_addr_expr (NULL_TREE
, gfc_get_symbol_decl (vtab
));
9429 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
,
9430 fold_convert (TREE_TYPE (to_se
.expr
), tmp
));
9433 gfc_free_expr (to_expr2
);
9434 gfc_init_se (&to_se
, NULL
);
9436 if (from_expr
->ts
.type
== BT_CLASS
)
9438 gfc_free_expr (from_expr2
);
9439 gfc_init_se (&from_se
, NULL
);
9444 /* Deallocate "to". */
9445 if (from_expr
->rank
== 0)
9447 to_se
.want_coarray
= 1;
9448 from_se
.want_coarray
= 1;
9450 gfc_conv_expr_descriptor (&to_se
, to_expr
);
9451 gfc_conv_expr_descriptor (&from_se
, from_expr
);
9453 /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC
9454 is an image control "statement", cf. IR F08/0040 in 12-006A. */
9455 if (coarray
&& flag_coarray
== GFC_FCOARRAY_LIB
)
9459 tmp
= gfc_deallocate_with_status (to_se
.expr
, NULL_TREE
, NULL_TREE
,
9460 NULL_TREE
, NULL_TREE
, true, to_expr
,
9462 gfc_add_expr_to_block (&block
, tmp
);
9464 tmp
= gfc_conv_descriptor_data_get (to_se
.expr
);
9465 cond
= fold_build2_loc (input_location
, EQ_EXPR
,
9466 boolean_type_node
, tmp
,
9467 fold_convert (TREE_TYPE (tmp
),
9468 null_pointer_node
));
9469 tmp
= build_call_expr_loc (input_location
, gfor_fndecl_caf_sync_all
,
9470 3, null_pointer_node
, null_pointer_node
,
9471 build_int_cst (integer_type_node
, 0));
9473 tmp
= fold_build3_loc (input_location
, COND_EXPR
, void_type_node
, cond
,
9474 tmp
, build_empty_stmt (input_location
));
9475 gfc_add_expr_to_block (&block
, tmp
);
9479 tmp
= gfc_conv_descriptor_data_get (to_se
.expr
);
9480 tmp
= gfc_deallocate_with_status (tmp
, NULL_TREE
, NULL_TREE
, NULL_TREE
,
9481 NULL_TREE
, true, to_expr
, false);
9482 gfc_add_expr_to_block (&block
, tmp
);
9485 /* Move the pointer and update the array descriptor data. */
9486 gfc_add_modify_loc (input_location
, &block
, to_se
.expr
, from_se
.expr
);
9488 /* Set "from" to NULL. */
9489 tmp
= gfc_conv_descriptor_data_get (from_se
.expr
);
9490 gfc_add_modify_loc (input_location
, &block
, tmp
,
9491 fold_convert (TREE_TYPE (tmp
), null_pointer_node
));
9493 return gfc_finish_block (&block
);
9498 gfc_conv_intrinsic_subroutine (gfc_code
*code
)
9502 gcc_assert (code
->resolved_isym
);
9504 switch (code
->resolved_isym
->id
)
9506 case GFC_ISYM_MOVE_ALLOC
:
9507 res
= conv_intrinsic_move_alloc (code
);
9510 case GFC_ISYM_ATOMIC_CAS
:
9511 res
= conv_intrinsic_atomic_cas (code
);
9514 case GFC_ISYM_ATOMIC_ADD
:
9515 case GFC_ISYM_ATOMIC_AND
:
9516 case GFC_ISYM_ATOMIC_DEF
:
9517 case GFC_ISYM_ATOMIC_OR
:
9518 case GFC_ISYM_ATOMIC_XOR
:
9519 case GFC_ISYM_ATOMIC_FETCH_ADD
:
9520 case GFC_ISYM_ATOMIC_FETCH_AND
:
9521 case GFC_ISYM_ATOMIC_FETCH_OR
:
9522 case GFC_ISYM_ATOMIC_FETCH_XOR
:
9523 res
= conv_intrinsic_atomic_op (code
);
9526 case GFC_ISYM_ATOMIC_REF
:
9527 res
= conv_intrinsic_atomic_ref (code
);
9530 case GFC_ISYM_C_F_POINTER
:
9531 case GFC_ISYM_C_F_PROCPOINTER
:
9532 res
= conv_isocbinding_subroutine (code
);
9535 case GFC_ISYM_CAF_SEND
:
9536 res
= conv_caf_send (code
);
9539 case GFC_ISYM_CO_BROADCAST
:
9540 case GFC_ISYM_CO_MIN
:
9541 case GFC_ISYM_CO_MAX
:
9542 case GFC_ISYM_CO_REDUCE
:
9543 case GFC_ISYM_CO_SUM
:
9544 res
= conv_co_collective (code
);
9547 case GFC_ISYM_SYSTEM_CLOCK
:
9548 res
= conv_intrinsic_system_clock (code
);
9559 #include "gt-fortran-trans-intrinsic.h"