re PR target/36634 (-msecure-plt combine gives invalid call insn)
[official-gcc.git] / gcc / fortran / trans-intrinsic.c
blob31780240cd233437cf5005d21d4db38498007840
1 /* Intrinsic translation
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
3 Free Software Foundation, Inc.
4 Contributed by Paul Brook <paul@nowt.org>
5 and Steven Bosscher <s.bosscher@student.tudelft.nl>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* trans-intrinsic.c-- generate GENERIC trees for calls to intrinsics. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "tree.h"
30 #include "ggc.h"
31 #include "toplev.h"
32 #include "real.h"
33 #include "tree-gimple.h"
34 #include "flags.h"
35 #include "gfortran.h"
36 #include "arith.h"
37 #include "intrinsic.h"
38 #include "trans.h"
39 #include "trans-const.h"
40 #include "trans-types.h"
41 #include "trans-array.h"
42 #include "defaults.h"
43 /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
44 #include "trans-stmt.h"
46 /* This maps fortran intrinsic math functions to external library or GCC
47 builtin functions. */
48 typedef struct gfc_intrinsic_map_t GTY(())
50 /* The explicit enum is required to work around inadequacies in the
51 garbage collection/gengtype parsing mechanism. */
52 enum gfc_isym_id id;
54 /* Enum value from the "language-independent", aka C-centric, part
55 of gcc, or END_BUILTINS of no such value set. */
56 enum built_in_function code_r4;
57 enum built_in_function code_r8;
58 enum built_in_function code_r10;
59 enum built_in_function code_r16;
60 enum built_in_function code_c4;
61 enum built_in_function code_c8;
62 enum built_in_function code_c10;
63 enum built_in_function code_c16;
65 /* True if the naming pattern is to prepend "c" for complex and
66 append "f" for kind=4. False if the naming pattern is to
67 prepend "_gfortran_" and append "[rc](4|8|10|16)". */
68 bool libm_name;
70 /* True if a complex version of the function exists. */
71 bool complex_available;
73 /* True if the function should be marked const. */
74 bool is_constant;
76 /* The base library name of this function. */
77 const char *name;
79 /* Cache decls created for the various operand types. */
80 tree real4_decl;
81 tree real8_decl;
82 tree real10_decl;
83 tree real16_decl;
84 tree complex4_decl;
85 tree complex8_decl;
86 tree complex10_decl;
87 tree complex16_decl;
89 gfc_intrinsic_map_t;
91 /* ??? The NARGS==1 hack here is based on the fact that (c99 at least)
92 defines complex variants of all of the entries in mathbuiltins.def
93 except for atan2. */
94 #define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
95 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
96 BUILT_IN_ ## ID ## L, BUILT_IN_ ## ID ## L, 0, 0, 0, 0, true, \
97 false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
98 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
100 #define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
101 { GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
102 BUILT_IN_ ## ID ## L, BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, \
103 BUILT_IN_C ## ID, BUILT_IN_C ## ID ## L, BUILT_IN_C ## ID ## L, true, \
104 true, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
105 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
107 #define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
108 { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
109 END_BUILTINS, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
110 false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
111 NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
113 static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
115 /* Functions built into gcc itself. */
116 #include "mathbuiltins.def"
118 /* Functions in libgfortran. */
119 LIB_FUNCTION (ERFC_SCALED, "erfc_scaled", false),
121 /* End the list. */
122 LIB_FUNCTION (NONE, NULL, false)
125 #undef LIB_FUNCTION
126 #undef DEFINE_MATH_BUILTIN
127 #undef DEFINE_MATH_BUILTIN_C
129 /* Structure for storing components of a floating number to be used by
130 elemental functions to manipulate reals. */
131 typedef struct
133 tree arg; /* Variable tree to view convert to integer. */
134 tree expn; /* Variable tree to save exponent. */
135 tree frac; /* Variable tree to save fraction. */
136 tree smask; /* Constant tree of sign's mask. */
137 tree emask; /* Constant tree of exponent's mask. */
138 tree fmask; /* Constant tree of fraction's mask. */
139 tree edigits; /* Constant tree of the number of exponent bits. */
140 tree fdigits; /* Constant tree of the number of fraction bits. */
141 tree f1; /* Constant tree of the f1 defined in the real model. */
142 tree bias; /* Constant tree of the bias of exponent in the memory. */
143 tree type; /* Type tree of arg1. */
144 tree mtype; /* Type tree of integer type. Kind is that of arg1. */
146 real_compnt_info;
148 enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
150 /* Evaluate the arguments to an intrinsic function. The value
151 of NARGS may be less than the actual number of arguments in EXPR
152 to allow optional "KIND" arguments that are not included in the
153 generated code to be ignored. */
155 static void
156 gfc_conv_intrinsic_function_args (gfc_se *se, gfc_expr *expr,
157 tree *argarray, int nargs)
159 gfc_actual_arglist *actual;
160 gfc_expr *e;
161 gfc_intrinsic_arg *formal;
162 gfc_se argse;
163 int curr_arg;
165 formal = expr->value.function.isym->formal;
166 actual = expr->value.function.actual;
168 for (curr_arg = 0; curr_arg < nargs; curr_arg++,
169 actual = actual->next,
170 formal = formal ? formal->next : NULL)
172 gcc_assert (actual);
173 e = actual->expr;
174 /* Skip omitted optional arguments. */
175 if (!e)
177 --curr_arg;
178 continue;
181 /* Evaluate the parameter. This will substitute scalarized
182 references automatically. */
183 gfc_init_se (&argse, se);
185 if (e->ts.type == BT_CHARACTER)
187 gfc_conv_expr (&argse, e);
188 gfc_conv_string_parameter (&argse);
189 argarray[curr_arg++] = argse.string_length;
190 gcc_assert (curr_arg < nargs);
192 else
193 gfc_conv_expr_val (&argse, e);
195 /* If an optional argument is itself an optional dummy argument,
196 check its presence and substitute a null if absent. */
197 if (e->expr_type == EXPR_VARIABLE
198 && e->symtree->n.sym->attr.optional
199 && formal
200 && formal->optional)
201 gfc_conv_missing_dummy (&argse, e, formal->ts, 0);
203 gfc_add_block_to_block (&se->pre, &argse.pre);
204 gfc_add_block_to_block (&se->post, &argse.post);
205 argarray[curr_arg] = argse.expr;
209 /* Count the number of actual arguments to the intrinsic function EXPR
210 including any "hidden" string length arguments. */
212 static unsigned int
213 gfc_intrinsic_argument_list_length (gfc_expr *expr)
215 int n = 0;
216 gfc_actual_arglist *actual;
218 for (actual = expr->value.function.actual; actual; actual = actual->next)
220 if (!actual->expr)
221 continue;
223 if (actual->expr->ts.type == BT_CHARACTER)
224 n += 2;
225 else
226 n++;
229 return n;
233 /* Conversions between different types are output by the frontend as
234 intrinsic functions. We implement these directly with inline code. */
236 static void
237 gfc_conv_intrinsic_conversion (gfc_se * se, gfc_expr * expr)
239 tree type;
240 tree *args;
241 int nargs;
243 nargs = gfc_intrinsic_argument_list_length (expr);
244 args = (tree *) alloca (sizeof (tree) * nargs);
246 /* Evaluate all the arguments passed. Whilst we're only interested in the
247 first one here, there are other parts of the front-end that assume this
248 and will trigger an ICE if it's not the case. */
249 type = gfc_typenode_for_spec (&expr->ts);
250 gcc_assert (expr->value.function.actual->expr);
251 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
253 /* Conversion between character kinds involves a call to a library
254 function. */
255 if (expr->ts.type == BT_CHARACTER)
257 tree fndecl, var, addr, tmp;
259 if (expr->ts.kind == 1
260 && expr->value.function.actual->expr->ts.kind == 4)
261 fndecl = gfor_fndecl_convert_char4_to_char1;
262 else if (expr->ts.kind == 4
263 && expr->value.function.actual->expr->ts.kind == 1)
264 fndecl = gfor_fndecl_convert_char1_to_char4;
265 else
266 gcc_unreachable ();
268 /* Create the variable storing the converted value. */
269 type = gfc_get_pchar_type (expr->ts.kind);
270 var = gfc_create_var (type, "str");
271 addr = gfc_build_addr_expr (build_pointer_type (type), var);
273 /* Call the library function that will perform the conversion. */
274 gcc_assert (nargs >= 2);
275 tmp = build_call_expr (fndecl, 3, addr, args[0], args[1]);
276 gfc_add_expr_to_block (&se->pre, tmp);
278 /* Free the temporary afterwards. */
279 tmp = gfc_call_free (var);
280 gfc_add_expr_to_block (&se->post, tmp);
282 se->expr = var;
283 se->string_length = args[0];
285 return;
288 /* Conversion from complex to non-complex involves taking the real
289 component of the value. */
290 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
291 && expr->ts.type != BT_COMPLEX)
293 tree artype;
295 artype = TREE_TYPE (TREE_TYPE (args[0]));
296 args[0] = fold_build1 (REALPART_EXPR, artype, args[0]);
299 se->expr = convert (type, args[0]);
302 /* This is needed because the gcc backend only implements
303 FIX_TRUNC_EXPR, which is the same as INT() in Fortran.
304 FLOOR(x) = INT(x) <= x ? INT(x) : INT(x) - 1
305 Similarly for CEILING. */
307 static tree
308 build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up)
310 tree tmp;
311 tree cond;
312 tree argtype;
313 tree intval;
315 argtype = TREE_TYPE (arg);
316 arg = gfc_evaluate_now (arg, pblock);
318 intval = convert (type, arg);
319 intval = gfc_evaluate_now (intval, pblock);
321 tmp = convert (argtype, intval);
322 cond = fold_build2 (up ? GE_EXPR : LE_EXPR, boolean_type_node, tmp, arg);
324 tmp = fold_build2 (up ? PLUS_EXPR : MINUS_EXPR, type, intval,
325 build_int_cst (type, 1));
326 tmp = fold_build3 (COND_EXPR, type, cond, intval, tmp);
327 return tmp;
331 /* Round to nearest integer, away from zero. */
333 static tree
334 build_round_expr (tree arg, tree restype)
336 tree argtype;
337 tree fn;
338 bool longlong;
339 int argprec, resprec;
341 argtype = TREE_TYPE (arg);
342 argprec = TYPE_PRECISION (argtype);
343 resprec = TYPE_PRECISION (restype);
345 /* Depending on the type of the result, choose the long int intrinsic
346 (lround family) or long long intrinsic (llround). We might also
347 need to convert the result afterwards. */
348 if (resprec <= LONG_TYPE_SIZE)
349 longlong = false;
350 else if (resprec <= LONG_LONG_TYPE_SIZE)
351 longlong = true;
352 else
353 gcc_unreachable ();
355 /* Now, depending on the argument type, we choose between intrinsics. */
356 if (argprec == TYPE_PRECISION (float_type_node))
357 fn = built_in_decls[longlong ? BUILT_IN_LLROUNDF : BUILT_IN_LROUNDF];
358 else if (argprec == TYPE_PRECISION (double_type_node))
359 fn = built_in_decls[longlong ? BUILT_IN_LLROUND : BUILT_IN_LROUND];
360 else if (argprec == TYPE_PRECISION (long_double_type_node))
361 fn = built_in_decls[longlong ? BUILT_IN_LLROUNDL : BUILT_IN_LROUNDL];
362 else
363 gcc_unreachable ();
365 return fold_convert (restype, build_call_expr (fn, 1, arg));
369 /* Convert a real to an integer using a specific rounding mode.
370 Ideally we would just build the corresponding GENERIC node,
371 however the RTL expander only actually supports FIX_TRUNC_EXPR. */
373 static tree
374 build_fix_expr (stmtblock_t * pblock, tree arg, tree type,
375 enum rounding_mode op)
377 switch (op)
379 case RND_FLOOR:
380 return build_fixbound_expr (pblock, arg, type, 0);
381 break;
383 case RND_CEIL:
384 return build_fixbound_expr (pblock, arg, type, 1);
385 break;
387 case RND_ROUND:
388 return build_round_expr (arg, type);
389 break;
391 case RND_TRUNC:
392 return fold_build1 (FIX_TRUNC_EXPR, type, arg);
393 break;
395 default:
396 gcc_unreachable ();
401 /* Round a real value using the specified rounding mode.
402 We use a temporary integer of that same kind size as the result.
403 Values larger than those that can be represented by this kind are
404 unchanged, as they will not be accurate enough to represent the
405 rounding.
406 huge = HUGE (KIND (a))
407 aint (a) = ((a > huge) || (a < -huge)) ? a : (real)(int)a
410 static void
411 gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
413 tree type;
414 tree itype;
415 tree arg[2];
416 tree tmp;
417 tree cond;
418 mpfr_t huge;
419 int n, nargs;
420 int kind;
422 kind = expr->ts.kind;
423 nargs = gfc_intrinsic_argument_list_length (expr);
425 n = END_BUILTINS;
426 /* We have builtin functions for some cases. */
427 switch (op)
429 case RND_ROUND:
430 switch (kind)
432 case 4:
433 n = BUILT_IN_ROUNDF;
434 break;
436 case 8:
437 n = BUILT_IN_ROUND;
438 break;
440 case 10:
441 case 16:
442 n = BUILT_IN_ROUNDL;
443 break;
445 break;
447 case RND_TRUNC:
448 switch (kind)
450 case 4:
451 n = BUILT_IN_TRUNCF;
452 break;
454 case 8:
455 n = BUILT_IN_TRUNC;
456 break;
458 case 10:
459 case 16:
460 n = BUILT_IN_TRUNCL;
461 break;
463 break;
465 default:
466 gcc_unreachable ();
469 /* Evaluate the argument. */
470 gcc_assert (expr->value.function.actual->expr);
471 gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
473 /* Use a builtin function if one exists. */
474 if (n != END_BUILTINS)
476 tmp = built_in_decls[n];
477 se->expr = build_call_expr (tmp, 1, arg[0]);
478 return;
481 /* This code is probably redundant, but we'll keep it lying around just
482 in case. */
483 type = gfc_typenode_for_spec (&expr->ts);
484 arg[0] = gfc_evaluate_now (arg[0], &se->pre);
486 /* Test if the value is too large to handle sensibly. */
487 gfc_set_model_kind (kind);
488 mpfr_init (huge);
489 n = gfc_validate_kind (BT_INTEGER, kind, false);
490 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
491 tmp = gfc_conv_mpfr_to_tree (huge, kind);
492 cond = fold_build2 (LT_EXPR, boolean_type_node, arg[0], tmp);
494 mpfr_neg (huge, huge, GFC_RND_MODE);
495 tmp = gfc_conv_mpfr_to_tree (huge, kind);
496 tmp = fold_build2 (GT_EXPR, boolean_type_node, arg[0], tmp);
497 cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond, tmp);
498 itype = gfc_get_int_type (kind);
500 tmp = build_fix_expr (&se->pre, arg[0], itype, op);
501 tmp = convert (type, tmp);
502 se->expr = fold_build3 (COND_EXPR, type, cond, tmp, arg[0]);
503 mpfr_clear (huge);
507 /* Convert to an integer using the specified rounding mode. */
509 static void
510 gfc_conv_intrinsic_int (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
512 tree type;
513 tree *args;
514 int nargs;
516 nargs = gfc_intrinsic_argument_list_length (expr);
517 args = (tree *) alloca (sizeof (tree) * nargs);
519 /* Evaluate the argument, we process all arguments even though we only
520 use the first one for code generation purposes. */
521 type = gfc_typenode_for_spec (&expr->ts);
522 gcc_assert (expr->value.function.actual->expr);
523 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
525 if (TREE_CODE (TREE_TYPE (args[0])) == INTEGER_TYPE)
527 /* Conversion to a different integer kind. */
528 se->expr = convert (type, args[0]);
530 else
532 /* Conversion from complex to non-complex involves taking the real
533 component of the value. */
534 if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE
535 && expr->ts.type != BT_COMPLEX)
537 tree artype;
539 artype = TREE_TYPE (TREE_TYPE (args[0]));
540 args[0] = fold_build1 (REALPART_EXPR, artype, args[0]);
543 se->expr = build_fix_expr (&se->pre, args[0], type, op);
548 /* Get the imaginary component of a value. */
550 static void
551 gfc_conv_intrinsic_imagpart (gfc_se * se, gfc_expr * expr)
553 tree arg;
555 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
556 se->expr = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
560 /* Get the complex conjugate of a value. */
562 static void
563 gfc_conv_intrinsic_conjg (gfc_se * se, gfc_expr * expr)
565 tree arg;
567 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
568 se->expr = fold_build1 (CONJ_EXPR, TREE_TYPE (arg), arg);
572 /* Initialize function decls for library functions. The external functions
573 are created as required. Builtin functions are added here. */
575 void
576 gfc_build_intrinsic_lib_fndecls (void)
578 gfc_intrinsic_map_t *m;
580 /* Add GCC builtin functions. */
581 for (m = gfc_intrinsic_map; m->id != GFC_ISYM_NONE; m++)
583 if (m->code_r4 != END_BUILTINS)
584 m->real4_decl = built_in_decls[m->code_r4];
585 if (m->code_r8 != END_BUILTINS)
586 m->real8_decl = built_in_decls[m->code_r8];
587 if (m->code_r10 != END_BUILTINS)
588 m->real10_decl = built_in_decls[m->code_r10];
589 if (m->code_r16 != END_BUILTINS)
590 m->real16_decl = built_in_decls[m->code_r16];
591 if (m->code_c4 != END_BUILTINS)
592 m->complex4_decl = built_in_decls[m->code_c4];
593 if (m->code_c8 != END_BUILTINS)
594 m->complex8_decl = built_in_decls[m->code_c8];
595 if (m->code_c10 != END_BUILTINS)
596 m->complex10_decl = built_in_decls[m->code_c10];
597 if (m->code_c16 != END_BUILTINS)
598 m->complex16_decl = built_in_decls[m->code_c16];
603 /* Create a fndecl for a simple intrinsic library function. */
605 static tree
606 gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
608 tree type;
609 tree argtypes;
610 tree fndecl;
611 gfc_actual_arglist *actual;
612 tree *pdecl;
613 gfc_typespec *ts;
614 char name[GFC_MAX_SYMBOL_LEN + 3];
616 ts = &expr->ts;
617 if (ts->type == BT_REAL)
619 switch (ts->kind)
621 case 4:
622 pdecl = &m->real4_decl;
623 break;
624 case 8:
625 pdecl = &m->real8_decl;
626 break;
627 case 10:
628 pdecl = &m->real10_decl;
629 break;
630 case 16:
631 pdecl = &m->real16_decl;
632 break;
633 default:
634 gcc_unreachable ();
637 else if (ts->type == BT_COMPLEX)
639 gcc_assert (m->complex_available);
641 switch (ts->kind)
643 case 4:
644 pdecl = &m->complex4_decl;
645 break;
646 case 8:
647 pdecl = &m->complex8_decl;
648 break;
649 case 10:
650 pdecl = &m->complex10_decl;
651 break;
652 case 16:
653 pdecl = &m->complex16_decl;
654 break;
655 default:
656 gcc_unreachable ();
659 else
660 gcc_unreachable ();
662 if (*pdecl)
663 return *pdecl;
665 if (m->libm_name)
667 if (ts->kind == 4)
668 snprintf (name, sizeof (name), "%s%s%s",
669 ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
670 else if (ts->kind == 8)
671 snprintf (name, sizeof (name), "%s%s",
672 ts->type == BT_COMPLEX ? "c" : "", m->name);
673 else
675 gcc_assert (ts->kind == 10 || ts->kind == 16);
676 snprintf (name, sizeof (name), "%s%s%s",
677 ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
680 else
682 snprintf (name, sizeof (name), PREFIX ("%s_%c%d"), m->name,
683 ts->type == BT_COMPLEX ? 'c' : 'r',
684 ts->kind);
687 argtypes = NULL_TREE;
688 for (actual = expr->value.function.actual; actual; actual = actual->next)
690 type = gfc_typenode_for_spec (&actual->expr->ts);
691 argtypes = gfc_chainon_list (argtypes, type);
693 argtypes = gfc_chainon_list (argtypes, void_type_node);
694 type = build_function_type (gfc_typenode_for_spec (ts), argtypes);
695 fndecl = build_decl (FUNCTION_DECL, get_identifier (name), type);
697 /* Mark the decl as external. */
698 DECL_EXTERNAL (fndecl) = 1;
699 TREE_PUBLIC (fndecl) = 1;
701 /* Mark it __attribute__((const)), if possible. */
702 TREE_READONLY (fndecl) = m->is_constant;
704 rest_of_decl_compilation (fndecl, 1, 0);
706 (*pdecl) = fndecl;
707 return fndecl;
711 /* Convert an intrinsic function into an external or builtin call. */
713 static void
714 gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
716 gfc_intrinsic_map_t *m;
717 tree fndecl;
718 tree rettype;
719 tree *args;
720 unsigned int num_args;
721 gfc_isym_id id;
723 id = expr->value.function.isym->id;
724 /* Find the entry for this function. */
725 for (m = gfc_intrinsic_map; m->id != GFC_ISYM_NONE; m++)
727 if (id == m->id)
728 break;
731 if (m->id == GFC_ISYM_NONE)
733 internal_error ("Intrinsic function %s(%d) not recognized",
734 expr->value.function.name, id);
737 /* Get the decl and generate the call. */
738 num_args = gfc_intrinsic_argument_list_length (expr);
739 args = (tree *) alloca (sizeof (tree) * num_args);
741 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
742 fndecl = gfc_get_intrinsic_lib_fndecl (m, expr);
743 rettype = TREE_TYPE (TREE_TYPE (fndecl));
745 fndecl = build_addr (fndecl, current_function_decl);
746 se->expr = build_call_array (rettype, fndecl, num_args, args);
749 /* The EXPONENT(s) intrinsic function is translated into
750 int ret;
751 frexp (s, &ret);
752 return ret;
755 static void
756 gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
758 tree arg, type, res, tmp;
759 int frexp;
761 switch (expr->value.function.actual->expr->ts.kind)
763 case 4:
764 frexp = BUILT_IN_FREXPF;
765 break;
766 case 8:
767 frexp = BUILT_IN_FREXP;
768 break;
769 case 10:
770 case 16:
771 frexp = BUILT_IN_FREXPL;
772 break;
773 default:
774 gcc_unreachable ();
777 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
779 res = gfc_create_var (integer_type_node, NULL);
780 tmp = build_call_expr (built_in_decls[frexp], 2, arg,
781 build_fold_addr_expr (res));
782 gfc_add_expr_to_block (&se->pre, tmp);
784 type = gfc_typenode_for_spec (&expr->ts);
785 se->expr = fold_convert (type, res);
788 /* Evaluate a single upper or lower bound. */
789 /* TODO: bound intrinsic generates way too much unnecessary code. */
791 static void
792 gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
794 gfc_actual_arglist *arg;
795 gfc_actual_arglist *arg2;
796 tree desc;
797 tree type;
798 tree bound;
799 tree tmp;
800 tree cond, cond1, cond2, cond3, cond4, size;
801 tree ubound;
802 tree lbound;
803 gfc_se argse;
804 gfc_ss *ss;
805 gfc_array_spec * as;
806 gfc_ref *ref;
808 arg = expr->value.function.actual;
809 arg2 = arg->next;
811 if (se->ss)
813 /* Create an implicit second parameter from the loop variable. */
814 gcc_assert (!arg2->expr);
815 gcc_assert (se->loop->dimen == 1);
816 gcc_assert (se->ss->expr == expr);
817 gfc_advance_se_ss_chain (se);
818 bound = se->loop->loopvar[0];
819 bound = fold_build2 (MINUS_EXPR, gfc_array_index_type, bound,
820 se->loop->from[0]);
822 else
824 /* use the passed argument. */
825 gcc_assert (arg->next->expr);
826 gfc_init_se (&argse, NULL);
827 gfc_conv_expr_type (&argse, arg->next->expr, gfc_array_index_type);
828 gfc_add_block_to_block (&se->pre, &argse.pre);
829 bound = argse.expr;
830 /* Convert from one based to zero based. */
831 bound = fold_build2 (MINUS_EXPR, gfc_array_index_type, bound,
832 gfc_index_one_node);
835 /* TODO: don't re-evaluate the descriptor on each iteration. */
836 /* Get a descriptor for the first parameter. */
837 ss = gfc_walk_expr (arg->expr);
838 gcc_assert (ss != gfc_ss_terminator);
839 gfc_init_se (&argse, NULL);
840 gfc_conv_expr_descriptor (&argse, arg->expr, ss);
841 gfc_add_block_to_block (&se->pre, &argse.pre);
842 gfc_add_block_to_block (&se->post, &argse.post);
844 desc = argse.expr;
846 if (INTEGER_CST_P (bound))
848 int hi, low;
850 hi = TREE_INT_CST_HIGH (bound);
851 low = TREE_INT_CST_LOW (bound);
852 if (hi || low < 0 || low >= GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)))
853 gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
854 "dimension index", upper ? "UBOUND" : "LBOUND",
855 &expr->where);
857 else
859 if (flag_bounds_check)
861 bound = gfc_evaluate_now (bound, &se->pre);
862 cond = fold_build2 (LT_EXPR, boolean_type_node,
863 bound, build_int_cst (TREE_TYPE (bound), 0));
864 tmp = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc))];
865 tmp = fold_build2 (GE_EXPR, boolean_type_node, bound, tmp);
866 cond = fold_build2 (TRUTH_ORIF_EXPR, boolean_type_node, cond, tmp);
867 gfc_trans_runtime_check (cond, &se->pre, &expr->where, gfc_msg_fault);
871 ubound = gfc_conv_descriptor_ubound (desc, bound);
872 lbound = gfc_conv_descriptor_lbound (desc, bound);
874 /* Follow any component references. */
875 if (arg->expr->expr_type == EXPR_VARIABLE
876 || arg->expr->expr_type == EXPR_CONSTANT)
878 as = arg->expr->symtree->n.sym->as;
879 for (ref = arg->expr->ref; ref; ref = ref->next)
881 switch (ref->type)
883 case REF_COMPONENT:
884 as = ref->u.c.component->as;
885 continue;
887 case REF_SUBSTRING:
888 continue;
890 case REF_ARRAY:
892 switch (ref->u.ar.type)
894 case AR_ELEMENT:
895 case AR_SECTION:
896 case AR_UNKNOWN:
897 as = NULL;
898 continue;
900 case AR_FULL:
901 break;
907 else
908 as = NULL;
910 /* 13.14.53: Result value for LBOUND
912 Case (i): For an array section or for an array expression other than a
913 whole array or array structure component, LBOUND(ARRAY, DIM)
914 has the value 1. For a whole array or array structure
915 component, LBOUND(ARRAY, DIM) has the value:
916 (a) equal to the lower bound for subscript DIM of ARRAY if
917 dimension DIM of ARRAY does not have extent zero
918 or if ARRAY is an assumed-size array of rank DIM,
919 or (b) 1 otherwise.
921 13.14.113: Result value for UBOUND
923 Case (i): For an array section or for an array expression other than a
924 whole array or array structure component, UBOUND(ARRAY, DIM)
925 has the value equal to the number of elements in the given
926 dimension; otherwise, it has a value equal to the upper bound
927 for subscript DIM of ARRAY if dimension DIM of ARRAY does
928 not have size zero and has value zero if dimension DIM has
929 size zero. */
931 if (as)
933 tree stride = gfc_conv_descriptor_stride (desc, bound);
935 cond1 = fold_build2 (GE_EXPR, boolean_type_node, ubound, lbound);
936 cond2 = fold_build2 (LE_EXPR, boolean_type_node, ubound, lbound);
938 cond3 = fold_build2 (GE_EXPR, boolean_type_node, stride,
939 gfc_index_zero_node);
940 cond3 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond3, cond1);
942 cond4 = fold_build2 (LT_EXPR, boolean_type_node, stride,
943 gfc_index_zero_node);
944 cond4 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond4, cond2);
946 if (upper)
948 cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond3, cond4);
950 se->expr = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
951 ubound, gfc_index_zero_node);
953 else
955 if (as->type == AS_ASSUMED_SIZE)
956 cond = fold_build2 (EQ_EXPR, boolean_type_node, bound,
957 build_int_cst (TREE_TYPE (bound),
958 arg->expr->rank - 1));
959 else
960 cond = boolean_false_node;
962 cond1 = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond3, cond4);
963 cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond, cond1);
965 se->expr = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
966 lbound, gfc_index_one_node);
969 else
971 if (upper)
973 size = fold_build2 (MINUS_EXPR, gfc_array_index_type, ubound, lbound);
974 se->expr = fold_build2 (PLUS_EXPR, gfc_array_index_type, size,
975 gfc_index_one_node);
976 se->expr = fold_build2 (MAX_EXPR, gfc_array_index_type, se->expr,
977 gfc_index_zero_node);
979 else
980 se->expr = gfc_index_one_node;
983 type = gfc_typenode_for_spec (&expr->ts);
984 se->expr = convert (type, se->expr);
988 static void
989 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
991 tree arg;
992 int n;
994 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
996 switch (expr->value.function.actual->expr->ts.type)
998 case BT_INTEGER:
999 case BT_REAL:
1000 se->expr = fold_build1 (ABS_EXPR, TREE_TYPE (arg), arg);
1001 break;
1003 case BT_COMPLEX:
1004 switch (expr->ts.kind)
1006 case 4:
1007 n = BUILT_IN_CABSF;
1008 break;
1009 case 8:
1010 n = BUILT_IN_CABS;
1011 break;
1012 case 10:
1013 case 16:
1014 n = BUILT_IN_CABSL;
1015 break;
1016 default:
1017 gcc_unreachable ();
1019 se->expr = build_call_expr (built_in_decls[n], 1, arg);
1020 break;
1022 default:
1023 gcc_unreachable ();
1028 /* Create a complex value from one or two real components. */
1030 static void
1031 gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
1033 tree real;
1034 tree imag;
1035 tree type;
1036 tree *args;
1037 unsigned int num_args;
1039 num_args = gfc_intrinsic_argument_list_length (expr);
1040 args = (tree *) alloca (sizeof (tree) * num_args);
1042 type = gfc_typenode_for_spec (&expr->ts);
1043 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
1044 real = convert (TREE_TYPE (type), args[0]);
1045 if (both)
1046 imag = convert (TREE_TYPE (type), args[1]);
1047 else if (TREE_CODE (TREE_TYPE (args[0])) == COMPLEX_TYPE)
1049 imag = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (args[0])),
1050 args[0]);
1051 imag = convert (TREE_TYPE (type), imag);
1053 else
1054 imag = build_real_from_int_cst (TREE_TYPE (type), integer_zero_node);
1056 se->expr = fold_build2 (COMPLEX_EXPR, type, real, imag);
1059 /* Remainder function MOD(A, P) = A - INT(A / P) * P
1060 MODULO(A, P) = A - FLOOR (A / P) * P */
1061 /* TODO: MOD(x, 0) */
1063 static void
1064 gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
1066 tree type;
1067 tree itype;
1068 tree tmp;
1069 tree test;
1070 tree test2;
1071 mpfr_t huge;
1072 int n, ikind;
1073 tree args[2];
1075 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1077 switch (expr->ts.type)
1079 case BT_INTEGER:
1080 /* Integer case is easy, we've got a builtin op. */
1081 type = TREE_TYPE (args[0]);
1083 if (modulo)
1084 se->expr = fold_build2 (FLOOR_MOD_EXPR, type, args[0], args[1]);
1085 else
1086 se->expr = fold_build2 (TRUNC_MOD_EXPR, type, args[0], args[1]);
1087 break;
1089 case BT_REAL:
1090 n = END_BUILTINS;
1091 /* Check if we have a builtin fmod. */
1092 switch (expr->ts.kind)
1094 case 4:
1095 n = BUILT_IN_FMODF;
1096 break;
1098 case 8:
1099 n = BUILT_IN_FMOD;
1100 break;
1102 case 10:
1103 case 16:
1104 n = BUILT_IN_FMODL;
1105 break;
1107 default:
1108 break;
1111 /* Use it if it exists. */
1112 if (n != END_BUILTINS)
1114 tmp = build_addr (built_in_decls[n], current_function_decl);
1115 se->expr = build_call_array (TREE_TYPE (TREE_TYPE (built_in_decls[n])),
1116 tmp, 2, args);
1117 if (modulo == 0)
1118 return;
1121 type = TREE_TYPE (args[0]);
1123 args[0] = gfc_evaluate_now (args[0], &se->pre);
1124 args[1] = gfc_evaluate_now (args[1], &se->pre);
1126 /* Definition:
1127 modulo = arg - floor (arg/arg2) * arg2, so
1128 = test ? fmod (arg, arg2) : fmod (arg, arg2) + arg2,
1129 where
1130 test = (fmod (arg, arg2) != 0) && ((arg < 0) xor (arg2 < 0))
1131 thereby avoiding another division and retaining the accuracy
1132 of the builtin function. */
1133 if (n != END_BUILTINS && modulo)
1135 tree zero = gfc_build_const (type, integer_zero_node);
1136 tmp = gfc_evaluate_now (se->expr, &se->pre);
1137 test = fold_build2 (LT_EXPR, boolean_type_node, args[0], zero);
1138 test2 = fold_build2 (LT_EXPR, boolean_type_node, args[1], zero);
1139 test2 = fold_build2 (TRUTH_XOR_EXPR, boolean_type_node, test, test2);
1140 test = fold_build2 (NE_EXPR, boolean_type_node, tmp, zero);
1141 test = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, test, test2);
1142 test = gfc_evaluate_now (test, &se->pre);
1143 se->expr = fold_build3 (COND_EXPR, type, test,
1144 fold_build2 (PLUS_EXPR, type, tmp, args[1]),
1145 tmp);
1146 return;
1149 /* If we do not have a built_in fmod, the calculation is going to
1150 have to be done longhand. */
1151 tmp = fold_build2 (RDIV_EXPR, type, args[0], args[1]);
1153 /* Test if the value is too large to handle sensibly. */
1154 gfc_set_model_kind (expr->ts.kind);
1155 mpfr_init (huge);
1156 n = gfc_validate_kind (BT_INTEGER, expr->ts.kind, true);
1157 ikind = expr->ts.kind;
1158 if (n < 0)
1160 n = gfc_validate_kind (BT_INTEGER, gfc_max_integer_kind, false);
1161 ikind = gfc_max_integer_kind;
1163 mpfr_set_z (huge, gfc_integer_kinds[n].huge, GFC_RND_MODE);
1164 test = gfc_conv_mpfr_to_tree (huge, expr->ts.kind);
1165 test2 = fold_build2 (LT_EXPR, boolean_type_node, tmp, test);
1167 mpfr_neg (huge, huge, GFC_RND_MODE);
1168 test = gfc_conv_mpfr_to_tree (huge, expr->ts.kind);
1169 test = fold_build2 (GT_EXPR, boolean_type_node, tmp, test);
1170 test2 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, test, test2);
1172 itype = gfc_get_int_type (ikind);
1173 if (modulo)
1174 tmp = build_fix_expr (&se->pre, tmp, itype, RND_FLOOR);
1175 else
1176 tmp = build_fix_expr (&se->pre, tmp, itype, RND_TRUNC);
1177 tmp = convert (type, tmp);
1178 tmp = fold_build3 (COND_EXPR, type, test2, tmp, args[0]);
1179 tmp = fold_build2 (MULT_EXPR, type, tmp, args[1]);
1180 se->expr = fold_build2 (MINUS_EXPR, type, args[0], tmp);
1181 mpfr_clear (huge);
1182 break;
1184 default:
1185 gcc_unreachable ();
1189 /* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */
1191 static void
1192 gfc_conv_intrinsic_dim (gfc_se * se, gfc_expr * expr)
1194 tree val;
1195 tree tmp;
1196 tree type;
1197 tree zero;
1198 tree args[2];
1200 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1201 type = TREE_TYPE (args[0]);
1203 val = fold_build2 (MINUS_EXPR, type, args[0], args[1]);
1204 val = gfc_evaluate_now (val, &se->pre);
1206 zero = gfc_build_const (type, integer_zero_node);
1207 tmp = fold_build2 (LE_EXPR, boolean_type_node, val, zero);
1208 se->expr = fold_build3 (COND_EXPR, type, tmp, zero, val);
1212 /* SIGN(A, B) is absolute value of A times sign of B.
1213 The real value versions use library functions to ensure the correct
1214 handling of negative zero. Integer case implemented as:
1215 SIGN(A, B) = { tmp = (A ^ B) >> C; (A + tmp) ^ tmp }
1218 static void
1219 gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
1221 tree tmp;
1222 tree type;
1223 tree args[2];
1225 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1226 if (expr->ts.type == BT_REAL)
1228 switch (expr->ts.kind)
1230 case 4:
1231 tmp = built_in_decls[BUILT_IN_COPYSIGNF];
1232 break;
1233 case 8:
1234 tmp = built_in_decls[BUILT_IN_COPYSIGN];
1235 break;
1236 case 10:
1237 case 16:
1238 tmp = built_in_decls[BUILT_IN_COPYSIGNL];
1239 break;
1240 default:
1241 gcc_unreachable ();
1243 se->expr = build_call_expr (tmp, 2, args[0], args[1]);
1244 return;
1247 /* Having excluded floating point types, we know we are now dealing
1248 with signed integer types. */
1249 type = TREE_TYPE (args[0]);
1251 /* Args[0] is used multiple times below. */
1252 args[0] = gfc_evaluate_now (args[0], &se->pre);
1254 /* Construct (A ^ B) >> 31, which generates a bit mask of all zeros if
1255 the signs of A and B are the same, and of all ones if they differ. */
1256 tmp = fold_build2 (BIT_XOR_EXPR, type, args[0], args[1]);
1257 tmp = fold_build2 (RSHIFT_EXPR, type, tmp,
1258 build_int_cst (type, TYPE_PRECISION (type) - 1));
1259 tmp = gfc_evaluate_now (tmp, &se->pre);
1261 /* Construct (A + tmp) ^ tmp, which is A if tmp is zero, and -A if tmp]
1262 is all ones (i.e. -1). */
1263 se->expr = fold_build2 (BIT_XOR_EXPR, type,
1264 fold_build2 (PLUS_EXPR, type, args[0], tmp),
1265 tmp);
1269 /* Test for the presence of an optional argument. */
1271 static void
1272 gfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr)
1274 gfc_expr *arg;
1276 arg = expr->value.function.actual->expr;
1277 gcc_assert (arg->expr_type == EXPR_VARIABLE);
1278 se->expr = gfc_conv_expr_present (arg->symtree->n.sym);
1279 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
1283 /* Calculate the double precision product of two single precision values. */
1285 static void
1286 gfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr)
1288 tree type;
1289 tree args[2];
1291 gfc_conv_intrinsic_function_args (se, expr, args, 2);
1293 /* Convert the args to double precision before multiplying. */
1294 type = gfc_typenode_for_spec (&expr->ts);
1295 args[0] = convert (type, args[0]);
1296 args[1] = convert (type, args[1]);
1297 se->expr = fold_build2 (MULT_EXPR, type, args[0], args[1]);
1301 /* Return a length one character string containing an ascii character. */
1303 static void
1304 gfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr)
1306 tree arg[2];
1307 tree var;
1308 tree type;
1309 unsigned int num_args;
1311 num_args = gfc_intrinsic_argument_list_length (expr);
1312 gfc_conv_intrinsic_function_args (se, expr, arg, num_args);
1314 type = gfc_get_char_type (expr->ts.kind);
1315 var = gfc_create_var (type, "char");
1317 arg[0] = fold_build1 (NOP_EXPR, type, arg[0]);
1318 gfc_add_modify_expr (&se->pre, var, arg[0]);
1319 se->expr = gfc_build_addr_expr (build_pointer_type (type), var);
1320 se->string_length = integer_one_node;
1324 static void
1325 gfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr)
1327 tree var;
1328 tree len;
1329 tree tmp;
1330 tree cond;
1331 tree fndecl;
1332 tree *args;
1333 unsigned int num_args;
1335 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1336 args = (tree *) alloca (sizeof (tree) * num_args);
1338 var = gfc_create_var (pchar_type_node, "pstr");
1339 len = gfc_create_var (gfc_get_int_type (8), "len");
1341 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
1342 args[0] = build_fold_addr_expr (var);
1343 args[1] = build_fold_addr_expr (len);
1345 fndecl = build_addr (gfor_fndecl_ctime, current_function_decl);
1346 tmp = build_call_array (TREE_TYPE (TREE_TYPE (gfor_fndecl_ctime)),
1347 fndecl, num_args, args);
1348 gfc_add_expr_to_block (&se->pre, tmp);
1350 /* Free the temporary afterwards, if necessary. */
1351 cond = fold_build2 (GT_EXPR, boolean_type_node,
1352 len, build_int_cst (TREE_TYPE (len), 0));
1353 tmp = gfc_call_free (var);
1354 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1355 gfc_add_expr_to_block (&se->post, tmp);
1357 se->expr = var;
1358 se->string_length = len;
1362 static void
1363 gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
1365 tree var;
1366 tree len;
1367 tree tmp;
1368 tree cond;
1369 tree fndecl;
1370 tree *args;
1371 unsigned int num_args;
1373 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1374 args = (tree *) alloca (sizeof (tree) * num_args);
1376 var = gfc_create_var (pchar_type_node, "pstr");
1377 len = gfc_create_var (gfc_get_int_type (4), "len");
1379 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
1380 args[0] = build_fold_addr_expr (var);
1381 args[1] = build_fold_addr_expr (len);
1383 fndecl = build_addr (gfor_fndecl_fdate, current_function_decl);
1384 tmp = build_call_array (TREE_TYPE (TREE_TYPE (gfor_fndecl_fdate)),
1385 fndecl, num_args, args);
1386 gfc_add_expr_to_block (&se->pre, tmp);
1388 /* Free the temporary afterwards, if necessary. */
1389 cond = fold_build2 (GT_EXPR, boolean_type_node,
1390 len, build_int_cst (TREE_TYPE (len), 0));
1391 tmp = gfc_call_free (var);
1392 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1393 gfc_add_expr_to_block (&se->post, tmp);
1395 se->expr = var;
1396 se->string_length = len;
1400 /* Return a character string containing the tty name. */
1402 static void
1403 gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
1405 tree var;
1406 tree len;
1407 tree tmp;
1408 tree cond;
1409 tree fndecl;
1410 tree *args;
1411 unsigned int num_args;
1413 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
1414 args = (tree *) alloca (sizeof (tree) * num_args);
1416 var = gfc_create_var (pchar_type_node, "pstr");
1417 len = gfc_create_var (gfc_get_int_type (4), "len");
1419 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
1420 args[0] = build_fold_addr_expr (var);
1421 args[1] = build_fold_addr_expr (len);
1423 fndecl = build_addr (gfor_fndecl_ttynam, current_function_decl);
1424 tmp = build_call_array (TREE_TYPE (TREE_TYPE (gfor_fndecl_ttynam)),
1425 fndecl, num_args, args);
1426 gfc_add_expr_to_block (&se->pre, tmp);
1428 /* Free the temporary afterwards, if necessary. */
1429 cond = fold_build2 (GT_EXPR, boolean_type_node,
1430 len, build_int_cst (TREE_TYPE (len), 0));
1431 tmp = gfc_call_free (var);
1432 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1433 gfc_add_expr_to_block (&se->post, tmp);
1435 se->expr = var;
1436 se->string_length = len;
1440 /* Get the minimum/maximum value of all the parameters.
1441 minmax (a1, a2, a3, ...)
1443 mvar = a1;
1444 if (a2 .op. mvar || isnan(mvar))
1445 mvar = a2;
1446 if (a3 .op. mvar || isnan(mvar))
1447 mvar = a3;
1449 return mvar
1453 /* TODO: Mismatching types can occur when specific names are used.
1454 These should be handled during resolution. */
1455 static void
1456 gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, int op)
1458 tree tmp;
1459 tree mvar;
1460 tree val;
1461 tree thencase;
1462 tree *args;
1463 tree type;
1464 gfc_actual_arglist *argexpr;
1465 unsigned int i, nargs;
1467 nargs = gfc_intrinsic_argument_list_length (expr);
1468 args = (tree *) alloca (sizeof (tree) * nargs);
1470 gfc_conv_intrinsic_function_args (se, expr, args, nargs);
1471 type = gfc_typenode_for_spec (&expr->ts);
1473 argexpr = expr->value.function.actual;
1474 if (TREE_TYPE (args[0]) != type)
1475 args[0] = convert (type, args[0]);
1476 /* Only evaluate the argument once. */
1477 if (TREE_CODE (args[0]) != VAR_DECL && !TREE_CONSTANT (args[0]))
1478 args[0] = gfc_evaluate_now (args[0], &se->pre);
1480 mvar = gfc_create_var (type, "M");
1481 gfc_add_modify_expr (&se->pre, mvar, args[0]);
1482 for (i = 1, argexpr = argexpr->next; i < nargs; i++)
1484 tree cond, isnan;
1486 val = args[i];
1488 /* Handle absent optional arguments by ignoring the comparison. */
1489 if (argexpr->expr->expr_type == EXPR_VARIABLE
1490 && argexpr->expr->symtree->n.sym->attr.optional
1491 && TREE_CODE (val) == INDIRECT_REF)
1492 cond = fold_build2
1493 (NE_EXPR, boolean_type_node, TREE_OPERAND (val, 0),
1494 build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
1495 else
1497 cond = NULL_TREE;
1499 /* Only evaluate the argument once. */
1500 if (TREE_CODE (val) != VAR_DECL && !TREE_CONSTANT (val))
1501 val = gfc_evaluate_now (val, &se->pre);
1504 thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
1506 tmp = fold_build2 (op, boolean_type_node, convert (type, val), mvar);
1508 /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to
1509 __builtin_isnan might be made dependent on that module being loaded,
1510 to help performance of programs that don't rely on IEEE semantics. */
1511 if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
1513 isnan = build_call_expr (built_in_decls[BUILT_IN_ISNAN], 1, mvar);
1514 tmp = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, tmp,
1515 fold_convert (boolean_type_node, isnan));
1517 tmp = build3_v (COND_EXPR, tmp, thencase, build_empty_stmt ());
1519 if (cond != NULL_TREE)
1520 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1522 gfc_add_expr_to_block (&se->pre, tmp);
1523 argexpr = argexpr->next;
1525 se->expr = mvar;
1529 /* Generate library calls for MIN and MAX intrinsics for character
1530 variables. */
1531 static void
1532 gfc_conv_intrinsic_minmax_char (gfc_se * se, gfc_expr * expr, int op)
1534 tree *args;
1535 tree var, len, fndecl, tmp, cond, function;
1536 unsigned int nargs;
1538 nargs = gfc_intrinsic_argument_list_length (expr);
1539 args = (tree *) alloca (sizeof (tree) * (nargs + 4));
1540 gfc_conv_intrinsic_function_args (se, expr, &args[4], nargs);
1542 /* Create the result variables. */
1543 len = gfc_create_var (gfc_charlen_type_node, "len");
1544 args[0] = build_fold_addr_expr (len);
1545 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
1546 args[1] = gfc_build_addr_expr (ppvoid_type_node, var);
1547 args[2] = build_int_cst (NULL_TREE, op);
1548 args[3] = build_int_cst (NULL_TREE, nargs / 2);
1550 if (expr->ts.kind == 1)
1551 function = gfor_fndecl_string_minmax;
1552 else if (expr->ts.kind == 4)
1553 function = gfor_fndecl_string_minmax_char4;
1554 else
1555 gcc_unreachable ();
1557 /* Make the function call. */
1558 fndecl = build_addr (function, current_function_decl);
1559 tmp = build_call_array (TREE_TYPE (TREE_TYPE (function)), fndecl,
1560 nargs + 4, args);
1561 gfc_add_expr_to_block (&se->pre, tmp);
1563 /* Free the temporary afterwards, if necessary. */
1564 cond = fold_build2 (GT_EXPR, boolean_type_node,
1565 len, build_int_cst (TREE_TYPE (len), 0));
1566 tmp = gfc_call_free (var);
1567 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1568 gfc_add_expr_to_block (&se->post, tmp);
1570 se->expr = var;
1571 se->string_length = len;
1575 /* Create a symbol node for this intrinsic. The symbol from the frontend
1576 has the generic name. */
1578 static gfc_symbol *
1579 gfc_get_symbol_for_expr (gfc_expr * expr)
1581 gfc_symbol *sym;
1583 /* TODO: Add symbols for intrinsic function to the global namespace. */
1584 gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);
1585 sym = gfc_new_symbol (expr->value.function.name, NULL);
1587 sym->ts = expr->ts;
1588 sym->attr.external = 1;
1589 sym->attr.function = 1;
1590 sym->attr.always_explicit = 1;
1591 sym->attr.proc = PROC_INTRINSIC;
1592 sym->attr.flavor = FL_PROCEDURE;
1593 sym->result = sym;
1594 if (expr->rank > 0)
1596 sym->attr.dimension = 1;
1597 sym->as = gfc_get_array_spec ();
1598 sym->as->type = AS_ASSUMED_SHAPE;
1599 sym->as->rank = expr->rank;
1602 /* TODO: proper argument lists for external intrinsics. */
1603 return sym;
1606 /* Generate a call to an external intrinsic function. */
1607 static void
1608 gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
1610 gfc_symbol *sym;
1611 tree append_args;
1613 gcc_assert (!se->ss || se->ss->expr == expr);
1615 if (se->ss)
1616 gcc_assert (expr->rank > 0);
1617 else
1618 gcc_assert (expr->rank == 0);
1620 sym = gfc_get_symbol_for_expr (expr);
1622 /* Calls to libgfortran_matmul need to be appended special arguments,
1623 to be able to call the BLAS ?gemm functions if required and possible. */
1624 append_args = NULL_TREE;
1625 if (expr->value.function.isym->id == GFC_ISYM_MATMUL
1626 && sym->ts.type != BT_LOGICAL)
1628 tree cint = gfc_get_int_type (gfc_c_int_kind);
1630 if (gfc_option.flag_external_blas
1631 && (sym->ts.type == BT_REAL || sym->ts.type == BT_COMPLEX)
1632 && (sym->ts.kind == gfc_default_real_kind
1633 || sym->ts.kind == gfc_default_double_kind))
1635 tree gemm_fndecl;
1637 if (sym->ts.type == BT_REAL)
1639 if (sym->ts.kind == gfc_default_real_kind)
1640 gemm_fndecl = gfor_fndecl_sgemm;
1641 else
1642 gemm_fndecl = gfor_fndecl_dgemm;
1644 else
1646 if (sym->ts.kind == gfc_default_real_kind)
1647 gemm_fndecl = gfor_fndecl_cgemm;
1648 else
1649 gemm_fndecl = gfor_fndecl_zgemm;
1652 append_args = gfc_chainon_list (NULL_TREE, build_int_cst (cint, 1));
1653 append_args = gfc_chainon_list
1654 (append_args, build_int_cst
1655 (cint, gfc_option.blas_matmul_limit));
1656 append_args = gfc_chainon_list (append_args,
1657 gfc_build_addr_expr (NULL_TREE,
1658 gemm_fndecl));
1660 else
1662 append_args = gfc_chainon_list (NULL_TREE, build_int_cst (cint, 0));
1663 append_args = gfc_chainon_list (append_args, build_int_cst (cint, 0));
1664 append_args = gfc_chainon_list (append_args, null_pointer_node);
1668 gfc_conv_function_call (se, sym, expr->value.function.actual, append_args);
1669 gfc_free (sym);
1672 /* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.
1673 Implemented as
1674 any(a)
1676 forall (i=...)
1677 if (a[i] != 0)
1678 return 1
1679 end forall
1680 return 0
1682 all(a)
1684 forall (i=...)
1685 if (a[i] == 0)
1686 return 0
1687 end forall
1688 return 1
1691 static void
1692 gfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, int op)
1694 tree resvar;
1695 stmtblock_t block;
1696 stmtblock_t body;
1697 tree type;
1698 tree tmp;
1699 tree found;
1700 gfc_loopinfo loop;
1701 gfc_actual_arglist *actual;
1702 gfc_ss *arrayss;
1703 gfc_se arrayse;
1704 tree exit_label;
1706 if (se->ss)
1708 gfc_conv_intrinsic_funcall (se, expr);
1709 return;
1712 actual = expr->value.function.actual;
1713 type = gfc_typenode_for_spec (&expr->ts);
1714 /* Initialize the result. */
1715 resvar = gfc_create_var (type, "test");
1716 if (op == EQ_EXPR)
1717 tmp = convert (type, boolean_true_node);
1718 else
1719 tmp = convert (type, boolean_false_node);
1720 gfc_add_modify_expr (&se->pre, resvar, tmp);
1722 /* Walk the arguments. */
1723 arrayss = gfc_walk_expr (actual->expr);
1724 gcc_assert (arrayss != gfc_ss_terminator);
1726 /* Initialize the scalarizer. */
1727 gfc_init_loopinfo (&loop);
1728 exit_label = gfc_build_label_decl (NULL_TREE);
1729 TREE_USED (exit_label) = 1;
1730 gfc_add_ss_to_loop (&loop, arrayss);
1732 /* Initialize the loop. */
1733 gfc_conv_ss_startstride (&loop);
1734 gfc_conv_loop_setup (&loop);
1736 gfc_mark_ss_chain_used (arrayss, 1);
1737 /* Generate the loop body. */
1738 gfc_start_scalarized_body (&loop, &body);
1740 /* If the condition matches then set the return value. */
1741 gfc_start_block (&block);
1742 if (op == EQ_EXPR)
1743 tmp = convert (type, boolean_false_node);
1744 else
1745 tmp = convert (type, boolean_true_node);
1746 gfc_add_modify_expr (&block, resvar, tmp);
1748 /* And break out of the loop. */
1749 tmp = build1_v (GOTO_EXPR, exit_label);
1750 gfc_add_expr_to_block (&block, tmp);
1752 found = gfc_finish_block (&block);
1754 /* Check this element. */
1755 gfc_init_se (&arrayse, NULL);
1756 gfc_copy_loopinfo_to_se (&arrayse, &loop);
1757 arrayse.ss = arrayss;
1758 gfc_conv_expr_val (&arrayse, actual->expr);
1760 gfc_add_block_to_block (&body, &arrayse.pre);
1761 tmp = fold_build2 (op, boolean_type_node, arrayse.expr,
1762 build_int_cst (TREE_TYPE (arrayse.expr), 0));
1763 tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt ());
1764 gfc_add_expr_to_block (&body, tmp);
1765 gfc_add_block_to_block (&body, &arrayse.post);
1767 gfc_trans_scalarizing_loops (&loop, &body);
1769 /* Add the exit label. */
1770 tmp = build1_v (LABEL_EXPR, exit_label);
1771 gfc_add_expr_to_block (&loop.pre, tmp);
1773 gfc_add_block_to_block (&se->pre, &loop.pre);
1774 gfc_add_block_to_block (&se->pre, &loop.post);
1775 gfc_cleanup_loop (&loop);
1777 se->expr = resvar;
1780 /* COUNT(A) = Number of true elements in A. */
1781 static void
1782 gfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr)
1784 tree resvar;
1785 tree type;
1786 stmtblock_t body;
1787 tree tmp;
1788 gfc_loopinfo loop;
1789 gfc_actual_arglist *actual;
1790 gfc_ss *arrayss;
1791 gfc_se arrayse;
1793 if (se->ss)
1795 gfc_conv_intrinsic_funcall (se, expr);
1796 return;
1799 actual = expr->value.function.actual;
1801 type = gfc_typenode_for_spec (&expr->ts);
1802 /* Initialize the result. */
1803 resvar = gfc_create_var (type, "count");
1804 gfc_add_modify_expr (&se->pre, resvar, build_int_cst (type, 0));
1806 /* Walk the arguments. */
1807 arrayss = gfc_walk_expr (actual->expr);
1808 gcc_assert (arrayss != gfc_ss_terminator);
1810 /* Initialize the scalarizer. */
1811 gfc_init_loopinfo (&loop);
1812 gfc_add_ss_to_loop (&loop, arrayss);
1814 /* Initialize the loop. */
1815 gfc_conv_ss_startstride (&loop);
1816 gfc_conv_loop_setup (&loop);
1818 gfc_mark_ss_chain_used (arrayss, 1);
1819 /* Generate the loop body. */
1820 gfc_start_scalarized_body (&loop, &body);
1822 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (resvar),
1823 resvar, build_int_cst (TREE_TYPE (resvar), 1));
1824 tmp = build2_v (MODIFY_EXPR, resvar, tmp);
1826 gfc_init_se (&arrayse, NULL);
1827 gfc_copy_loopinfo_to_se (&arrayse, &loop);
1828 arrayse.ss = arrayss;
1829 gfc_conv_expr_val (&arrayse, actual->expr);
1830 tmp = build3_v (COND_EXPR, arrayse.expr, tmp, build_empty_stmt ());
1832 gfc_add_block_to_block (&body, &arrayse.pre);
1833 gfc_add_expr_to_block (&body, tmp);
1834 gfc_add_block_to_block (&body, &arrayse.post);
1836 gfc_trans_scalarizing_loops (&loop, &body);
1838 gfc_add_block_to_block (&se->pre, &loop.pre);
1839 gfc_add_block_to_block (&se->pre, &loop.post);
1840 gfc_cleanup_loop (&loop);
1842 se->expr = resvar;
1845 /* Inline implementation of the sum and product intrinsics. */
1846 static void
1847 gfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, int op)
1849 tree resvar;
1850 tree type;
1851 stmtblock_t body;
1852 stmtblock_t block;
1853 tree tmp;
1854 gfc_loopinfo loop;
1855 gfc_actual_arglist *actual;
1856 gfc_ss *arrayss;
1857 gfc_ss *maskss;
1858 gfc_se arrayse;
1859 gfc_se maskse;
1860 gfc_expr *arrayexpr;
1861 gfc_expr *maskexpr;
1863 if (se->ss)
1865 gfc_conv_intrinsic_funcall (se, expr);
1866 return;
1869 type = gfc_typenode_for_spec (&expr->ts);
1870 /* Initialize the result. */
1871 resvar = gfc_create_var (type, "val");
1872 if (op == PLUS_EXPR)
1873 tmp = gfc_build_const (type, integer_zero_node);
1874 else
1875 tmp = gfc_build_const (type, integer_one_node);
1877 gfc_add_modify_expr (&se->pre, resvar, tmp);
1879 /* Walk the arguments. */
1880 actual = expr->value.function.actual;
1881 arrayexpr = actual->expr;
1882 arrayss = gfc_walk_expr (arrayexpr);
1883 gcc_assert (arrayss != gfc_ss_terminator);
1885 actual = actual->next->next;
1886 gcc_assert (actual);
1887 maskexpr = actual->expr;
1888 if (maskexpr && maskexpr->rank != 0)
1890 maskss = gfc_walk_expr (maskexpr);
1891 gcc_assert (maskss != gfc_ss_terminator);
1893 else
1894 maskss = NULL;
1896 /* Initialize the scalarizer. */
1897 gfc_init_loopinfo (&loop);
1898 gfc_add_ss_to_loop (&loop, arrayss);
1899 if (maskss)
1900 gfc_add_ss_to_loop (&loop, maskss);
1902 /* Initialize the loop. */
1903 gfc_conv_ss_startstride (&loop);
1904 gfc_conv_loop_setup (&loop);
1906 gfc_mark_ss_chain_used (arrayss, 1);
1907 if (maskss)
1908 gfc_mark_ss_chain_used (maskss, 1);
1909 /* Generate the loop body. */
1910 gfc_start_scalarized_body (&loop, &body);
1912 /* If we have a mask, only add this element if the mask is set. */
1913 if (maskss)
1915 gfc_init_se (&maskse, NULL);
1916 gfc_copy_loopinfo_to_se (&maskse, &loop);
1917 maskse.ss = maskss;
1918 gfc_conv_expr_val (&maskse, maskexpr);
1919 gfc_add_block_to_block (&body, &maskse.pre);
1921 gfc_start_block (&block);
1923 else
1924 gfc_init_block (&block);
1926 /* Do the actual summation/product. */
1927 gfc_init_se (&arrayse, NULL);
1928 gfc_copy_loopinfo_to_se (&arrayse, &loop);
1929 arrayse.ss = arrayss;
1930 gfc_conv_expr_val (&arrayse, arrayexpr);
1931 gfc_add_block_to_block (&block, &arrayse.pre);
1933 tmp = fold_build2 (op, type, resvar, arrayse.expr);
1934 gfc_add_modify_expr (&block, resvar, tmp);
1935 gfc_add_block_to_block (&block, &arrayse.post);
1937 if (maskss)
1939 /* We enclose the above in if (mask) {...} . */
1940 tmp = gfc_finish_block (&block);
1942 tmp = build3_v (COND_EXPR, maskse.expr, tmp, build_empty_stmt ());
1944 else
1945 tmp = gfc_finish_block (&block);
1946 gfc_add_expr_to_block (&body, tmp);
1948 gfc_trans_scalarizing_loops (&loop, &body);
1950 /* For a scalar mask, enclose the loop in an if statement. */
1951 if (maskexpr && maskss == NULL)
1953 gfc_init_se (&maskse, NULL);
1954 gfc_conv_expr_val (&maskse, maskexpr);
1955 gfc_init_block (&block);
1956 gfc_add_block_to_block (&block, &loop.pre);
1957 gfc_add_block_to_block (&block, &loop.post);
1958 tmp = gfc_finish_block (&block);
1960 tmp = build3_v (COND_EXPR, maskse.expr, tmp, build_empty_stmt ());
1961 gfc_add_expr_to_block (&block, tmp);
1962 gfc_add_block_to_block (&se->pre, &block);
1964 else
1966 gfc_add_block_to_block (&se->pre, &loop.pre);
1967 gfc_add_block_to_block (&se->pre, &loop.post);
1970 gfc_cleanup_loop (&loop);
1972 se->expr = resvar;
1976 /* Inline implementation of the dot_product intrinsic. This function
1977 is based on gfc_conv_intrinsic_arith (the previous function). */
1978 static void
1979 gfc_conv_intrinsic_dot_product (gfc_se * se, gfc_expr * expr)
1981 tree resvar;
1982 tree type;
1983 stmtblock_t body;
1984 stmtblock_t block;
1985 tree tmp;
1986 gfc_loopinfo loop;
1987 gfc_actual_arglist *actual;
1988 gfc_ss *arrayss1, *arrayss2;
1989 gfc_se arrayse1, arrayse2;
1990 gfc_expr *arrayexpr1, *arrayexpr2;
1992 type = gfc_typenode_for_spec (&expr->ts);
1994 /* Initialize the result. */
1995 resvar = gfc_create_var (type, "val");
1996 if (expr->ts.type == BT_LOGICAL)
1997 tmp = build_int_cst (type, 0);
1998 else
1999 tmp = gfc_build_const (type, integer_zero_node);
2001 gfc_add_modify_expr (&se->pre, resvar, tmp);
2003 /* Walk argument #1. */
2004 actual = expr->value.function.actual;
2005 arrayexpr1 = actual->expr;
2006 arrayss1 = gfc_walk_expr (arrayexpr1);
2007 gcc_assert (arrayss1 != gfc_ss_terminator);
2009 /* Walk argument #2. */
2010 actual = actual->next;
2011 arrayexpr2 = actual->expr;
2012 arrayss2 = gfc_walk_expr (arrayexpr2);
2013 gcc_assert (arrayss2 != gfc_ss_terminator);
2015 /* Initialize the scalarizer. */
2016 gfc_init_loopinfo (&loop);
2017 gfc_add_ss_to_loop (&loop, arrayss1);
2018 gfc_add_ss_to_loop (&loop, arrayss2);
2020 /* Initialize the loop. */
2021 gfc_conv_ss_startstride (&loop);
2022 gfc_conv_loop_setup (&loop);
2024 gfc_mark_ss_chain_used (arrayss1, 1);
2025 gfc_mark_ss_chain_used (arrayss2, 1);
2027 /* Generate the loop body. */
2028 gfc_start_scalarized_body (&loop, &body);
2029 gfc_init_block (&block);
2031 /* Make the tree expression for [conjg(]array1[)]. */
2032 gfc_init_se (&arrayse1, NULL);
2033 gfc_copy_loopinfo_to_se (&arrayse1, &loop);
2034 arrayse1.ss = arrayss1;
2035 gfc_conv_expr_val (&arrayse1, arrayexpr1);
2036 if (expr->ts.type == BT_COMPLEX)
2037 arrayse1.expr = fold_build1 (CONJ_EXPR, type, arrayse1.expr);
2038 gfc_add_block_to_block (&block, &arrayse1.pre);
2040 /* Make the tree expression for array2. */
2041 gfc_init_se (&arrayse2, NULL);
2042 gfc_copy_loopinfo_to_se (&arrayse2, &loop);
2043 arrayse2.ss = arrayss2;
2044 gfc_conv_expr_val (&arrayse2, arrayexpr2);
2045 gfc_add_block_to_block (&block, &arrayse2.pre);
2047 /* Do the actual product and sum. */
2048 if (expr->ts.type == BT_LOGICAL)
2050 tmp = fold_build2 (TRUTH_AND_EXPR, type, arrayse1.expr, arrayse2.expr);
2051 tmp = fold_build2 (TRUTH_OR_EXPR, type, resvar, tmp);
2053 else
2055 tmp = fold_build2 (MULT_EXPR, type, arrayse1.expr, arrayse2.expr);
2056 tmp = fold_build2 (PLUS_EXPR, type, resvar, tmp);
2058 gfc_add_modify_expr (&block, resvar, tmp);
2060 /* Finish up the loop block and the loop. */
2061 tmp = gfc_finish_block (&block);
2062 gfc_add_expr_to_block (&body, tmp);
2064 gfc_trans_scalarizing_loops (&loop, &body);
2065 gfc_add_block_to_block (&se->pre, &loop.pre);
2066 gfc_add_block_to_block (&se->pre, &loop.post);
2067 gfc_cleanup_loop (&loop);
2069 se->expr = resvar;
2073 static void
2074 gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, int op)
2076 stmtblock_t body;
2077 stmtblock_t block;
2078 stmtblock_t ifblock;
2079 stmtblock_t elseblock;
2080 tree limit;
2081 tree type;
2082 tree tmp;
2083 tree elsetmp;
2084 tree ifbody;
2085 tree offset;
2086 gfc_loopinfo loop;
2087 gfc_actual_arglist *actual;
2088 gfc_ss *arrayss;
2089 gfc_ss *maskss;
2090 gfc_se arrayse;
2091 gfc_se maskse;
2092 gfc_expr *arrayexpr;
2093 gfc_expr *maskexpr;
2094 tree pos;
2095 int n;
2097 if (se->ss)
2099 gfc_conv_intrinsic_funcall (se, expr);
2100 return;
2103 /* Initialize the result. */
2104 pos = gfc_create_var (gfc_array_index_type, "pos");
2105 offset = gfc_create_var (gfc_array_index_type, "offset");
2106 type = gfc_typenode_for_spec (&expr->ts);
2108 /* Walk the arguments. */
2109 actual = expr->value.function.actual;
2110 arrayexpr = actual->expr;
2111 arrayss = gfc_walk_expr (arrayexpr);
2112 gcc_assert (arrayss != gfc_ss_terminator);
2114 actual = actual->next->next;
2115 gcc_assert (actual);
2116 maskexpr = actual->expr;
2117 if (maskexpr && maskexpr->rank != 0)
2119 maskss = gfc_walk_expr (maskexpr);
2120 gcc_assert (maskss != gfc_ss_terminator);
2122 else
2123 maskss = NULL;
2125 limit = gfc_create_var (gfc_typenode_for_spec (&arrayexpr->ts), "limit");
2126 n = gfc_validate_kind (arrayexpr->ts.type, arrayexpr->ts.kind, false);
2127 switch (arrayexpr->ts.type)
2129 case BT_REAL:
2130 tmp = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge, arrayexpr->ts.kind);
2131 break;
2133 case BT_INTEGER:
2134 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge,
2135 arrayexpr->ts.kind);
2136 break;
2138 default:
2139 gcc_unreachable ();
2142 /* We start with the most negative possible value for MAXLOC, and the most
2143 positive possible value for MINLOC. The most negative possible value is
2144 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
2145 possible value is HUGE in both cases. */
2146 if (op == GT_EXPR)
2147 tmp = fold_build1 (NEGATE_EXPR, TREE_TYPE (tmp), tmp);
2148 gfc_add_modify_expr (&se->pre, limit, tmp);
2150 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
2151 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), tmp,
2152 build_int_cst (type, 1));
2154 /* Initialize the scalarizer. */
2155 gfc_init_loopinfo (&loop);
2156 gfc_add_ss_to_loop (&loop, arrayss);
2157 if (maskss)
2158 gfc_add_ss_to_loop (&loop, maskss);
2160 /* Initialize the loop. */
2161 gfc_conv_ss_startstride (&loop);
2162 gfc_conv_loop_setup (&loop);
2164 gcc_assert (loop.dimen == 1);
2166 /* Initialize the position to zero, following Fortran 2003. We are free
2167 to do this because Fortran 95 allows the result of an entirely false
2168 mask to be processor dependent. */
2169 gfc_add_modify_expr (&loop.pre, pos, gfc_index_zero_node);
2171 gfc_mark_ss_chain_used (arrayss, 1);
2172 if (maskss)
2173 gfc_mark_ss_chain_used (maskss, 1);
2174 /* Generate the loop body. */
2175 gfc_start_scalarized_body (&loop, &body);
2177 /* If we have a mask, only check this element if the mask is set. */
2178 if (maskss)
2180 gfc_init_se (&maskse, NULL);
2181 gfc_copy_loopinfo_to_se (&maskse, &loop);
2182 maskse.ss = maskss;
2183 gfc_conv_expr_val (&maskse, maskexpr);
2184 gfc_add_block_to_block (&body, &maskse.pre);
2186 gfc_start_block (&block);
2188 else
2189 gfc_init_block (&block);
2191 /* Compare with the current limit. */
2192 gfc_init_se (&arrayse, NULL);
2193 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2194 arrayse.ss = arrayss;
2195 gfc_conv_expr_val (&arrayse, arrayexpr);
2196 gfc_add_block_to_block (&block, &arrayse.pre);
2198 /* We do the following if this is a more extreme value. */
2199 gfc_start_block (&ifblock);
2201 /* Assign the value to the limit... */
2202 gfc_add_modify_expr (&ifblock, limit, arrayse.expr);
2204 /* Remember where we are. An offset must be added to the loop
2205 counter to obtain the required position. */
2206 if (loop.from[0])
2207 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
2208 gfc_index_one_node, loop.from[0]);
2209 else
2210 tmp = build_int_cst (gfc_array_index_type, 1);
2212 gfc_add_modify_expr (&block, offset, tmp);
2214 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (pos),
2215 loop.loopvar[0], offset);
2216 gfc_add_modify_expr (&ifblock, pos, tmp);
2218 ifbody = gfc_finish_block (&ifblock);
2220 /* If it is a more extreme value or pos is still zero and the value
2221 equal to the limit. */
2222 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2223 fold_build2 (EQ_EXPR, boolean_type_node,
2224 pos, gfc_index_zero_node),
2225 fold_build2 (EQ_EXPR, boolean_type_node,
2226 arrayse.expr, limit));
2227 tmp = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
2228 fold_build2 (op, boolean_type_node,
2229 arrayse.expr, limit), tmp);
2230 tmp = build3_v (COND_EXPR, tmp, ifbody, build_empty_stmt ());
2231 gfc_add_expr_to_block (&block, tmp);
2233 if (maskss)
2235 /* We enclose the above in if (mask) {...}. */
2236 tmp = gfc_finish_block (&block);
2238 tmp = build3_v (COND_EXPR, maskse.expr, tmp, build_empty_stmt ());
2240 else
2241 tmp = gfc_finish_block (&block);
2242 gfc_add_expr_to_block (&body, tmp);
2244 gfc_trans_scalarizing_loops (&loop, &body);
2246 /* For a scalar mask, enclose the loop in an if statement. */
2247 if (maskexpr && maskss == NULL)
2249 gfc_init_se (&maskse, NULL);
2250 gfc_conv_expr_val (&maskse, maskexpr);
2251 gfc_init_block (&block);
2252 gfc_add_block_to_block (&block, &loop.pre);
2253 gfc_add_block_to_block (&block, &loop.post);
2254 tmp = gfc_finish_block (&block);
2256 /* For the else part of the scalar mask, just initialize
2257 the pos variable the same way as above. */
2259 gfc_init_block (&elseblock);
2260 gfc_add_modify_expr (&elseblock, pos, gfc_index_zero_node);
2261 elsetmp = gfc_finish_block (&elseblock);
2263 tmp = build3_v (COND_EXPR, maskse.expr, tmp, elsetmp);
2264 gfc_add_expr_to_block (&block, tmp);
2265 gfc_add_block_to_block (&se->pre, &block);
2267 else
2269 gfc_add_block_to_block (&se->pre, &loop.pre);
2270 gfc_add_block_to_block (&se->pre, &loop.post);
2272 gfc_cleanup_loop (&loop);
2274 se->expr = convert (type, pos);
2277 static void
2278 gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, int op)
2280 tree limit;
2281 tree type;
2282 tree tmp;
2283 tree ifbody;
2284 stmtblock_t body;
2285 stmtblock_t block;
2286 gfc_loopinfo loop;
2287 gfc_actual_arglist *actual;
2288 gfc_ss *arrayss;
2289 gfc_ss *maskss;
2290 gfc_se arrayse;
2291 gfc_se maskse;
2292 gfc_expr *arrayexpr;
2293 gfc_expr *maskexpr;
2294 int n;
2296 if (se->ss)
2298 gfc_conv_intrinsic_funcall (se, expr);
2299 return;
2302 type = gfc_typenode_for_spec (&expr->ts);
2303 /* Initialize the result. */
2304 limit = gfc_create_var (type, "limit");
2305 n = gfc_validate_kind (expr->ts.type, expr->ts.kind, false);
2306 switch (expr->ts.type)
2308 case BT_REAL:
2309 tmp = gfc_conv_mpfr_to_tree (gfc_real_kinds[n].huge, expr->ts.kind);
2310 break;
2312 case BT_INTEGER:
2313 tmp = gfc_conv_mpz_to_tree (gfc_integer_kinds[n].huge, expr->ts.kind);
2314 break;
2316 default:
2317 gcc_unreachable ();
2320 /* We start with the most negative possible value for MAXVAL, and the most
2321 positive possible value for MINVAL. The most negative possible value is
2322 -HUGE for BT_REAL and (-HUGE - 1) for BT_INTEGER; the most positive
2323 possible value is HUGE in both cases. */
2324 if (op == GT_EXPR)
2325 tmp = fold_build1 (NEGATE_EXPR, TREE_TYPE (tmp), tmp);
2327 if (op == GT_EXPR && expr->ts.type == BT_INTEGER)
2328 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp),
2329 tmp, build_int_cst (type, 1));
2331 gfc_add_modify_expr (&se->pre, limit, tmp);
2333 /* Walk the arguments. */
2334 actual = expr->value.function.actual;
2335 arrayexpr = actual->expr;
2336 arrayss = gfc_walk_expr (arrayexpr);
2337 gcc_assert (arrayss != gfc_ss_terminator);
2339 actual = actual->next->next;
2340 gcc_assert (actual);
2341 maskexpr = actual->expr;
2342 if (maskexpr && maskexpr->rank != 0)
2344 maskss = gfc_walk_expr (maskexpr);
2345 gcc_assert (maskss != gfc_ss_terminator);
2347 else
2348 maskss = NULL;
2350 /* Initialize the scalarizer. */
2351 gfc_init_loopinfo (&loop);
2352 gfc_add_ss_to_loop (&loop, arrayss);
2353 if (maskss)
2354 gfc_add_ss_to_loop (&loop, maskss);
2356 /* Initialize the loop. */
2357 gfc_conv_ss_startstride (&loop);
2358 gfc_conv_loop_setup (&loop);
2360 gfc_mark_ss_chain_used (arrayss, 1);
2361 if (maskss)
2362 gfc_mark_ss_chain_used (maskss, 1);
2363 /* Generate the loop body. */
2364 gfc_start_scalarized_body (&loop, &body);
2366 /* If we have a mask, only add this element if the mask is set. */
2367 if (maskss)
2369 gfc_init_se (&maskse, NULL);
2370 gfc_copy_loopinfo_to_se (&maskse, &loop);
2371 maskse.ss = maskss;
2372 gfc_conv_expr_val (&maskse, maskexpr);
2373 gfc_add_block_to_block (&body, &maskse.pre);
2375 gfc_start_block (&block);
2377 else
2378 gfc_init_block (&block);
2380 /* Compare with the current limit. */
2381 gfc_init_se (&arrayse, NULL);
2382 gfc_copy_loopinfo_to_se (&arrayse, &loop);
2383 arrayse.ss = arrayss;
2384 gfc_conv_expr_val (&arrayse, arrayexpr);
2385 gfc_add_block_to_block (&block, &arrayse.pre);
2387 /* Assign the value to the limit... */
2388 ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
2390 /* If it is a more extreme value. */
2391 tmp = fold_build2 (op, boolean_type_node, arrayse.expr, limit);
2392 tmp = build3_v (COND_EXPR, tmp, ifbody, build_empty_stmt ());
2393 gfc_add_expr_to_block (&block, tmp);
2394 gfc_add_block_to_block (&block, &arrayse.post);
2396 tmp = gfc_finish_block (&block);
2397 if (maskss)
2398 /* We enclose the above in if (mask) {...}. */
2399 tmp = build3_v (COND_EXPR, maskse.expr, tmp, build_empty_stmt ());
2400 gfc_add_expr_to_block (&body, tmp);
2402 gfc_trans_scalarizing_loops (&loop, &body);
2404 /* For a scalar mask, enclose the loop in an if statement. */
2405 if (maskexpr && maskss == NULL)
2407 gfc_init_se (&maskse, NULL);
2408 gfc_conv_expr_val (&maskse, maskexpr);
2409 gfc_init_block (&block);
2410 gfc_add_block_to_block (&block, &loop.pre);
2411 gfc_add_block_to_block (&block, &loop.post);
2412 tmp = gfc_finish_block (&block);
2414 tmp = build3_v (COND_EXPR, maskse.expr, tmp, build_empty_stmt ());
2415 gfc_add_expr_to_block (&block, tmp);
2416 gfc_add_block_to_block (&se->pre, &block);
2418 else
2420 gfc_add_block_to_block (&se->pre, &loop.pre);
2421 gfc_add_block_to_block (&se->pre, &loop.post);
2424 gfc_cleanup_loop (&loop);
2426 se->expr = limit;
2429 /* BTEST (i, pos) = (i & (1 << pos)) != 0. */
2430 static void
2431 gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr)
2433 tree args[2];
2434 tree type;
2435 tree tmp;
2437 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2438 type = TREE_TYPE (args[0]);
2440 tmp = fold_build2 (LSHIFT_EXPR, type, build_int_cst (type, 1), args[1]);
2441 tmp = fold_build2 (BIT_AND_EXPR, type, args[0], tmp);
2442 tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp,
2443 build_int_cst (type, 0));
2444 type = gfc_typenode_for_spec (&expr->ts);
2445 se->expr = convert (type, tmp);
2448 /* Generate code to perform the specified operation. */
2449 static void
2450 gfc_conv_intrinsic_bitop (gfc_se * se, gfc_expr * expr, int op)
2452 tree args[2];
2454 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2455 se->expr = fold_build2 (op, TREE_TYPE (args[0]), args[0], args[1]);
2458 /* Bitwise not. */
2459 static void
2460 gfc_conv_intrinsic_not (gfc_se * se, gfc_expr * expr)
2462 tree arg;
2464 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
2465 se->expr = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg), arg);
2468 /* Set or clear a single bit. */
2469 static void
2470 gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set)
2472 tree args[2];
2473 tree type;
2474 tree tmp;
2475 int op;
2477 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2478 type = TREE_TYPE (args[0]);
2480 tmp = fold_build2 (LSHIFT_EXPR, type, build_int_cst (type, 1), args[1]);
2481 if (set)
2482 op = BIT_IOR_EXPR;
2483 else
2485 op = BIT_AND_EXPR;
2486 tmp = fold_build1 (BIT_NOT_EXPR, type, tmp);
2488 se->expr = fold_build2 (op, type, args[0], tmp);
2491 /* Extract a sequence of bits.
2492 IBITS(I, POS, LEN) = (I >> POS) & ~((~0) << LEN). */
2493 static void
2494 gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
2496 tree args[3];
2497 tree type;
2498 tree tmp;
2499 tree mask;
2501 gfc_conv_intrinsic_function_args (se, expr, args, 3);
2502 type = TREE_TYPE (args[0]);
2504 mask = build_int_cst (type, -1);
2505 mask = fold_build2 (LSHIFT_EXPR, type, mask, args[2]);
2506 mask = fold_build1 (BIT_NOT_EXPR, type, mask);
2508 tmp = fold_build2 (RSHIFT_EXPR, type, args[0], args[1]);
2510 se->expr = fold_build2 (BIT_AND_EXPR, type, tmp, mask);
2513 /* RSHIFT (I, SHIFT) = I >> SHIFT
2514 LSHIFT (I, SHIFT) = I << SHIFT */
2515 static void
2516 gfc_conv_intrinsic_rlshift (gfc_se * se, gfc_expr * expr, int right_shift)
2518 tree args[2];
2520 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2522 se->expr = fold_build2 (right_shift ? RSHIFT_EXPR : LSHIFT_EXPR,
2523 TREE_TYPE (args[0]), args[0], args[1]);
2526 /* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
2528 : ((shift >= 0) ? i << shift : i >> -shift)
2529 where all shifts are logical shifts. */
2530 static void
2531 gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr)
2533 tree args[2];
2534 tree type;
2535 tree utype;
2536 tree tmp;
2537 tree width;
2538 tree num_bits;
2539 tree cond;
2540 tree lshift;
2541 tree rshift;
2543 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2544 type = TREE_TYPE (args[0]);
2545 utype = unsigned_type_for (type);
2547 width = fold_build1 (ABS_EXPR, TREE_TYPE (args[1]), args[1]);
2549 /* Left shift if positive. */
2550 lshift = fold_build2 (LSHIFT_EXPR, type, args[0], width);
2552 /* Right shift if negative.
2553 We convert to an unsigned type because we want a logical shift.
2554 The standard doesn't define the case of shifting negative
2555 numbers, and we try to be compatible with other compilers, most
2556 notably g77, here. */
2557 rshift = fold_convert (type, fold_build2 (RSHIFT_EXPR, utype,
2558 convert (utype, args[0]), width));
2560 tmp = fold_build2 (GE_EXPR, boolean_type_node, args[1],
2561 build_int_cst (TREE_TYPE (args[1]), 0));
2562 tmp = fold_build3 (COND_EXPR, type, tmp, lshift, rshift);
2564 /* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
2565 gcc requires a shift width < BIT_SIZE(I), so we have to catch this
2566 special case. */
2567 num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type));
2568 cond = fold_build2 (GE_EXPR, boolean_type_node, width, num_bits);
2570 se->expr = fold_build3 (COND_EXPR, type, cond,
2571 build_int_cst (type, 0), tmp);
2575 /* Circular shift. AKA rotate or barrel shift. */
2577 static void
2578 gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr)
2580 tree *args;
2581 tree type;
2582 tree tmp;
2583 tree lrot;
2584 tree rrot;
2585 tree zero;
2586 unsigned int num_args;
2588 num_args = gfc_intrinsic_argument_list_length (expr);
2589 args = (tree *) alloca (sizeof (tree) * num_args);
2591 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2593 if (num_args == 3)
2595 /* Use a library function for the 3 parameter version. */
2596 tree int4type = gfc_get_int_type (4);
2598 type = TREE_TYPE (args[0]);
2599 /* We convert the first argument to at least 4 bytes, and
2600 convert back afterwards. This removes the need for library
2601 functions for all argument sizes, and function will be
2602 aligned to at least 32 bits, so there's no loss. */
2603 if (expr->ts.kind < 4)
2604 args[0] = convert (int4type, args[0]);
2606 /* Convert the SHIFT and SIZE args to INTEGER*4 otherwise we would
2607 need loads of library functions. They cannot have values >
2608 BIT_SIZE (I) so the conversion is safe. */
2609 args[1] = convert (int4type, args[1]);
2610 args[2] = convert (int4type, args[2]);
2612 switch (expr->ts.kind)
2614 case 1:
2615 case 2:
2616 case 4:
2617 tmp = gfor_fndecl_math_ishftc4;
2618 break;
2619 case 8:
2620 tmp = gfor_fndecl_math_ishftc8;
2621 break;
2622 case 16:
2623 tmp = gfor_fndecl_math_ishftc16;
2624 break;
2625 default:
2626 gcc_unreachable ();
2628 se->expr = build_call_expr (tmp, 3, args[0], args[1], args[2]);
2629 /* Convert the result back to the original type, if we extended
2630 the first argument's width above. */
2631 if (expr->ts.kind < 4)
2632 se->expr = convert (type, se->expr);
2634 return;
2636 type = TREE_TYPE (args[0]);
2638 /* Rotate left if positive. */
2639 lrot = fold_build2 (LROTATE_EXPR, type, args[0], args[1]);
2641 /* Rotate right if negative. */
2642 tmp = fold_build1 (NEGATE_EXPR, TREE_TYPE (args[1]), args[1]);
2643 rrot = fold_build2 (RROTATE_EXPR, type, args[0], tmp);
2645 zero = build_int_cst (TREE_TYPE (args[1]), 0);
2646 tmp = fold_build2 (GT_EXPR, boolean_type_node, args[1], zero);
2647 rrot = fold_build3 (COND_EXPR, type, tmp, lrot, rrot);
2649 /* Do nothing if shift == 0. */
2650 tmp = fold_build2 (EQ_EXPR, boolean_type_node, args[1], zero);
2651 se->expr = fold_build3 (COND_EXPR, type, tmp, args[0], rrot);
2654 /* The length of a character string. */
2655 static void
2656 gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr)
2658 tree len;
2659 tree type;
2660 tree decl;
2661 gfc_symbol *sym;
2662 gfc_se argse;
2663 gfc_expr *arg;
2664 gfc_ss *ss;
2666 gcc_assert (!se->ss);
2668 arg = expr->value.function.actual->expr;
2670 type = gfc_typenode_for_spec (&expr->ts);
2671 switch (arg->expr_type)
2673 case EXPR_CONSTANT:
2674 len = build_int_cst (NULL_TREE, arg->value.character.length);
2675 break;
2677 case EXPR_ARRAY:
2678 /* Obtain the string length from the function used by
2679 trans-array.c(gfc_trans_array_constructor). */
2680 len = NULL_TREE;
2681 get_array_ctor_strlen (&se->pre, arg->value.constructor, &len);
2682 break;
2684 case EXPR_VARIABLE:
2685 if (arg->ref == NULL
2686 || (arg->ref->next == NULL && arg->ref->type == REF_ARRAY))
2688 /* This doesn't catch all cases.
2689 See http://gcc.gnu.org/ml/fortran/2004-06/msg00165.html
2690 and the surrounding thread. */
2691 sym = arg->symtree->n.sym;
2692 decl = gfc_get_symbol_decl (sym);
2693 if (decl == current_function_decl && sym->attr.function
2694 && (sym->result == sym))
2695 decl = gfc_get_fake_result_decl (sym, 0);
2697 len = sym->ts.cl->backend_decl;
2698 gcc_assert (len);
2699 break;
2702 /* Otherwise fall through. */
2704 default:
2705 /* Anybody stupid enough to do this deserves inefficient code. */
2706 ss = gfc_walk_expr (arg);
2707 gfc_init_se (&argse, se);
2708 if (ss == gfc_ss_terminator)
2709 gfc_conv_expr (&argse, arg);
2710 else
2711 gfc_conv_expr_descriptor (&argse, arg, ss);
2712 gfc_add_block_to_block (&se->pre, &argse.pre);
2713 gfc_add_block_to_block (&se->post, &argse.post);
2714 len = argse.string_length;
2715 break;
2717 se->expr = convert (type, len);
2720 /* The length of a character string not including trailing blanks. */
2721 static void
2722 gfc_conv_intrinsic_len_trim (gfc_se * se, gfc_expr * expr)
2724 int kind = expr->value.function.actual->expr->ts.kind;
2725 tree args[2], type, fndecl;
2727 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2728 type = gfc_typenode_for_spec (&expr->ts);
2730 if (kind == 1)
2731 fndecl = gfor_fndecl_string_len_trim;
2732 else if (kind == 4)
2733 fndecl = gfor_fndecl_string_len_trim_char4;
2734 else
2735 gcc_unreachable ();
2737 se->expr = build_call_expr (fndecl, 2, args[0], args[1]);
2738 se->expr = convert (type, se->expr);
2742 /* Returns the starting position of a substring within a string. */
2744 static void
2745 gfc_conv_intrinsic_index_scan_verify (gfc_se * se, gfc_expr * expr,
2746 tree function)
2748 tree logical4_type_node = gfc_get_logical_type (4);
2749 tree type;
2750 tree fndecl;
2751 tree *args;
2752 unsigned int num_args;
2754 args = (tree *) alloca (sizeof (tree) * 5);
2756 /* Get number of arguments; characters count double due to the
2757 string length argument. Kind= is not passed to the libary
2758 and thus ignored. */
2759 if (expr->value.function.actual->next->next->expr == NULL)
2760 num_args = 4;
2761 else
2762 num_args = 5;
2764 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2765 type = gfc_typenode_for_spec (&expr->ts);
2767 if (num_args == 4)
2768 args[4] = build_int_cst (logical4_type_node, 0);
2769 else
2770 args[4] = convert (logical4_type_node, args[4]);
2772 fndecl = build_addr (function, current_function_decl);
2773 se->expr = build_call_array (TREE_TYPE (TREE_TYPE (function)), fndecl,
2774 5, args);
2775 se->expr = convert (type, se->expr);
2779 /* The ascii value for a single character. */
2780 static void
2781 gfc_conv_intrinsic_ichar (gfc_se * se, gfc_expr * expr)
2783 tree args[2], type, pchartype;
2785 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2786 gcc_assert (POINTER_TYPE_P (TREE_TYPE (args[1])));
2787 pchartype = gfc_get_pchar_type (expr->value.function.actual->expr->ts.kind);
2788 args[1] = fold_build1 (NOP_EXPR, pchartype, args[1]);
2789 type = gfc_typenode_for_spec (&expr->ts);
2791 se->expr = build_fold_indirect_ref (args[1]);
2792 se->expr = convert (type, se->expr);
2796 /* Intrinsic ISNAN calls __builtin_isnan. */
2798 static void
2799 gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
2801 tree arg;
2803 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
2804 se->expr = build_call_expr (built_in_decls[BUILT_IN_ISNAN], 1, arg);
2805 STRIP_TYPE_NOPS (se->expr);
2806 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
2810 /* Intrinsics IS_IOSTAT_END and IS_IOSTAT_EOR just need to compare
2811 their argument against a constant integer value. */
2813 static void
2814 gfc_conv_has_intvalue (gfc_se * se, gfc_expr * expr, const int value)
2816 tree arg;
2818 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
2819 se->expr = fold_build2 (EQ_EXPR, gfc_typenode_for_spec (&expr->ts),
2820 arg, build_int_cst (TREE_TYPE (arg), value));
2825 /* MERGE (tsource, fsource, mask) = mask ? tsource : fsource. */
2827 static void
2828 gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
2830 tree tsource;
2831 tree fsource;
2832 tree mask;
2833 tree type;
2834 tree len;
2835 tree *args;
2836 unsigned int num_args;
2838 num_args = gfc_intrinsic_argument_list_length (expr);
2839 args = (tree *) alloca (sizeof (tree) * num_args);
2841 gfc_conv_intrinsic_function_args (se, expr, args, num_args);
2842 if (expr->ts.type != BT_CHARACTER)
2844 tsource = args[0];
2845 fsource = args[1];
2846 mask = args[2];
2848 else
2850 /* We do the same as in the non-character case, but the argument
2851 list is different because of the string length arguments. We
2852 also have to set the string length for the result. */
2853 len = args[0];
2854 tsource = args[1];
2855 fsource = args[3];
2856 mask = args[4];
2858 se->string_length = len;
2860 type = TREE_TYPE (tsource);
2861 se->expr = fold_build3 (COND_EXPR, type, mask, tsource, fsource);
2865 /* FRACTION (s) is translated into frexp (s, &dummy_int). */
2866 static void
2867 gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
2869 tree arg, type, tmp;
2870 int frexp;
2872 switch (expr->ts.kind)
2874 case 4:
2875 frexp = BUILT_IN_FREXPF;
2876 break;
2877 case 8:
2878 frexp = BUILT_IN_FREXP;
2879 break;
2880 case 10:
2881 case 16:
2882 frexp = BUILT_IN_FREXPL;
2883 break;
2884 default:
2885 gcc_unreachable ();
2888 type = gfc_typenode_for_spec (&expr->ts);
2889 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
2890 tmp = gfc_create_var (integer_type_node, NULL);
2891 se->expr = build_call_expr (built_in_decls[frexp], 2,
2892 fold_convert (type, arg),
2893 build_fold_addr_expr (tmp));
2894 se->expr = fold_convert (type, se->expr);
2898 /* NEAREST (s, dir) is translated into
2899 tmp = copysign (INF, dir);
2900 return nextafter (s, tmp);
2902 static void
2903 gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
2905 tree args[2], type, tmp;
2906 int nextafter, copysign, inf;
2908 switch (expr->ts.kind)
2910 case 4:
2911 nextafter = BUILT_IN_NEXTAFTERF;
2912 copysign = BUILT_IN_COPYSIGNF;
2913 inf = BUILT_IN_INFF;
2914 break;
2915 case 8:
2916 nextafter = BUILT_IN_NEXTAFTER;
2917 copysign = BUILT_IN_COPYSIGN;
2918 inf = BUILT_IN_INF;
2919 break;
2920 case 10:
2921 case 16:
2922 nextafter = BUILT_IN_NEXTAFTERL;
2923 copysign = BUILT_IN_COPYSIGNL;
2924 inf = BUILT_IN_INFL;
2925 break;
2926 default:
2927 gcc_unreachable ();
2930 type = gfc_typenode_for_spec (&expr->ts);
2931 gfc_conv_intrinsic_function_args (se, expr, args, 2);
2932 tmp = build_call_expr (built_in_decls[copysign], 2,
2933 build_call_expr (built_in_decls[inf], 0),
2934 fold_convert (type, args[1]));
2935 se->expr = build_call_expr (built_in_decls[nextafter], 2,
2936 fold_convert (type, args[0]), tmp);
2937 se->expr = fold_convert (type, se->expr);
2941 /* SPACING (s) is translated into
2942 int e;
2943 if (s == 0)
2944 res = tiny;
2945 else
2947 frexp (s, &e);
2948 e = e - prec;
2949 e = MAX_EXPR (e, emin);
2950 res = scalbn (1., e);
2952 return res;
2954 where prec is the precision of s, gfc_real_kinds[k].digits,
2955 emin is min_exponent - 1, gfc_real_kinds[k].min_exponent - 1,
2956 and tiny is tiny(s), gfc_real_kinds[k].tiny. */
2958 static void
2959 gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
2961 tree arg, type, prec, emin, tiny, res, e;
2962 tree cond, tmp;
2963 int frexp, scalbn, k;
2964 stmtblock_t block;
2966 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
2967 prec = build_int_cst (NULL_TREE, gfc_real_kinds[k].digits);
2968 emin = build_int_cst (NULL_TREE, gfc_real_kinds[k].min_exponent - 1);
2969 tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind);
2971 switch (expr->ts.kind)
2973 case 4:
2974 frexp = BUILT_IN_FREXPF;
2975 scalbn = BUILT_IN_SCALBNF;
2976 break;
2977 case 8:
2978 frexp = BUILT_IN_FREXP;
2979 scalbn = BUILT_IN_SCALBN;
2980 break;
2981 case 10:
2982 case 16:
2983 frexp = BUILT_IN_FREXPL;
2984 scalbn = BUILT_IN_SCALBNL;
2985 break;
2986 default:
2987 gcc_unreachable ();
2990 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
2991 arg = gfc_evaluate_now (arg, &se->pre);
2993 type = gfc_typenode_for_spec (&expr->ts);
2994 e = gfc_create_var (integer_type_node, NULL);
2995 res = gfc_create_var (type, NULL);
2998 /* Build the block for s /= 0. */
2999 gfc_start_block (&block);
3000 tmp = build_call_expr (built_in_decls[frexp], 2, arg,
3001 build_fold_addr_expr (e));
3002 gfc_add_expr_to_block (&block, tmp);
3004 tmp = fold_build2 (MINUS_EXPR, integer_type_node, e, prec);
3005 gfc_add_modify_expr (&block, e, fold_build2 (MAX_EXPR, integer_type_node,
3006 tmp, emin));
3008 tmp = build_call_expr (built_in_decls[scalbn], 2,
3009 build_real_from_int_cst (type, integer_one_node), e);
3010 gfc_add_modify_expr (&block, res, tmp);
3012 /* Finish by building the IF statement. */
3013 cond = fold_build2 (EQ_EXPR, boolean_type_node, arg,
3014 build_real_from_int_cst (type, integer_zero_node));
3015 tmp = build3_v (COND_EXPR, cond, build2_v (MODIFY_EXPR, res, tiny),
3016 gfc_finish_block (&block));
3018 gfc_add_expr_to_block (&se->pre, tmp);
3019 se->expr = res;
3023 /* RRSPACING (s) is translated into
3024 int e;
3025 real x;
3026 x = fabs (s);
3027 if (x != 0)
3029 frexp (s, &e);
3030 x = scalbn (x, precision - e);
3032 return x;
3034 where precision is gfc_real_kinds[k].digits. */
3036 static void
3037 gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
3039 tree arg, type, e, x, cond, stmt, tmp;
3040 int frexp, scalbn, fabs, prec, k;
3041 stmtblock_t block;
3043 k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
3044 prec = gfc_real_kinds[k].digits;
3045 switch (expr->ts.kind)
3047 case 4:
3048 frexp = BUILT_IN_FREXPF;
3049 scalbn = BUILT_IN_SCALBNF;
3050 fabs = BUILT_IN_FABSF;
3051 break;
3052 case 8:
3053 frexp = BUILT_IN_FREXP;
3054 scalbn = BUILT_IN_SCALBN;
3055 fabs = BUILT_IN_FABS;
3056 break;
3057 case 10:
3058 case 16:
3059 frexp = BUILT_IN_FREXPL;
3060 scalbn = BUILT_IN_SCALBNL;
3061 fabs = BUILT_IN_FABSL;
3062 break;
3063 default:
3064 gcc_unreachable ();
3067 type = gfc_typenode_for_spec (&expr->ts);
3068 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3069 arg = gfc_evaluate_now (arg, &se->pre);
3071 e = gfc_create_var (integer_type_node, NULL);
3072 x = gfc_create_var (type, NULL);
3073 gfc_add_modify_expr (&se->pre, x,
3074 build_call_expr (built_in_decls[fabs], 1, arg));
3077 gfc_start_block (&block);
3078 tmp = build_call_expr (built_in_decls[frexp], 2, arg,
3079 build_fold_addr_expr (e));
3080 gfc_add_expr_to_block (&block, tmp);
3082 tmp = fold_build2 (MINUS_EXPR, integer_type_node,
3083 build_int_cst (NULL_TREE, prec), e);
3084 tmp = build_call_expr (built_in_decls[scalbn], 2, x, tmp);
3085 gfc_add_modify_expr (&block, x, tmp);
3086 stmt = gfc_finish_block (&block);
3088 cond = fold_build2 (NE_EXPR, boolean_type_node, x,
3089 build_real_from_int_cst (type, integer_zero_node));
3090 tmp = build3_v (COND_EXPR, cond, stmt, build_empty_stmt ());
3091 gfc_add_expr_to_block (&se->pre, tmp);
3093 se->expr = fold_convert (type, x);
3097 /* SCALE (s, i) is translated into scalbn (s, i). */
3098 static void
3099 gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
3101 tree args[2], type;
3102 int scalbn;
3104 switch (expr->ts.kind)
3106 case 4:
3107 scalbn = BUILT_IN_SCALBNF;
3108 break;
3109 case 8:
3110 scalbn = BUILT_IN_SCALBN;
3111 break;
3112 case 10:
3113 case 16:
3114 scalbn = BUILT_IN_SCALBNL;
3115 break;
3116 default:
3117 gcc_unreachable ();
3120 type = gfc_typenode_for_spec (&expr->ts);
3121 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3122 se->expr = build_call_expr (built_in_decls[scalbn], 2,
3123 fold_convert (type, args[0]),
3124 fold_convert (integer_type_node, args[1]));
3125 se->expr = fold_convert (type, se->expr);
3129 /* SET_EXPONENT (s, i) is translated into
3130 scalbn (frexp (s, &dummy_int), i). */
3131 static void
3132 gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
3134 tree args[2], type, tmp;
3135 int frexp, scalbn;
3137 switch (expr->ts.kind)
3139 case 4:
3140 frexp = BUILT_IN_FREXPF;
3141 scalbn = BUILT_IN_SCALBNF;
3142 break;
3143 case 8:
3144 frexp = BUILT_IN_FREXP;
3145 scalbn = BUILT_IN_SCALBN;
3146 break;
3147 case 10:
3148 case 16:
3149 frexp = BUILT_IN_FREXPL;
3150 scalbn = BUILT_IN_SCALBNL;
3151 break;
3152 default:
3153 gcc_unreachable ();
3156 type = gfc_typenode_for_spec (&expr->ts);
3157 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3159 tmp = gfc_create_var (integer_type_node, NULL);
3160 tmp = build_call_expr (built_in_decls[frexp], 2,
3161 fold_convert (type, args[0]),
3162 build_fold_addr_expr (tmp));
3163 se->expr = build_call_expr (built_in_decls[scalbn], 2, tmp,
3164 fold_convert (integer_type_node, args[1]));
3165 se->expr = fold_convert (type, se->expr);
3169 static void
3170 gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
3172 gfc_actual_arglist *actual;
3173 tree arg1;
3174 tree type;
3175 tree fncall0;
3176 tree fncall1;
3177 gfc_se argse;
3178 gfc_ss *ss;
3180 gfc_init_se (&argse, NULL);
3181 actual = expr->value.function.actual;
3183 ss = gfc_walk_expr (actual->expr);
3184 gcc_assert (ss != gfc_ss_terminator);
3185 argse.want_pointer = 1;
3186 argse.data_not_needed = 1;
3187 gfc_conv_expr_descriptor (&argse, actual->expr, ss);
3188 gfc_add_block_to_block (&se->pre, &argse.pre);
3189 gfc_add_block_to_block (&se->post, &argse.post);
3190 arg1 = gfc_evaluate_now (argse.expr, &se->pre);
3192 /* Build the call to size0. */
3193 fncall0 = build_call_expr (gfor_fndecl_size0, 1, arg1);
3195 actual = actual->next;
3197 if (actual->expr)
3199 gfc_init_se (&argse, NULL);
3200 gfc_conv_expr_type (&argse, actual->expr,
3201 gfc_array_index_type);
3202 gfc_add_block_to_block (&se->pre, &argse.pre);
3204 /* Build the call to size1. */
3205 fncall1 = build_call_expr (gfor_fndecl_size1, 2,
3206 arg1, argse.expr);
3208 /* Unusually, for an intrinsic, size does not exclude
3209 an optional arg2, so we must test for it. */
3210 if (actual->expr->expr_type == EXPR_VARIABLE
3211 && actual->expr->symtree->n.sym->attr.dummy
3212 && actual->expr->symtree->n.sym->attr.optional)
3214 tree tmp;
3215 gfc_init_se (&argse, NULL);
3216 argse.want_pointer = 1;
3217 argse.data_not_needed = 1;
3218 gfc_conv_expr (&argse, actual->expr);
3219 gfc_add_block_to_block (&se->pre, &argse.pre);
3220 tmp = fold_build2 (NE_EXPR, boolean_type_node,
3221 argse.expr, null_pointer_node);
3222 tmp = gfc_evaluate_now (tmp, &se->pre);
3223 se->expr = fold_build3 (COND_EXPR, pvoid_type_node,
3224 tmp, fncall1, fncall0);
3226 else
3227 se->expr = fncall1;
3229 else
3230 se->expr = fncall0;
3232 type = gfc_typenode_for_spec (&expr->ts);
3233 se->expr = convert (type, se->expr);
3237 /* Helper function to compute the size of a character variable,
3238 excluding the terminating null characters. The result has
3239 gfc_array_index_type type. */
3241 static tree
3242 size_of_string_in_bytes (int kind, tree string_length)
3244 tree bytesize;
3245 int i = gfc_validate_kind (BT_CHARACTER, kind, false);
3247 bytesize = build_int_cst (gfc_array_index_type,
3248 gfc_character_kinds[i].bit_size / 8);
3250 return fold_build2 (MULT_EXPR, gfc_array_index_type, bytesize,
3251 fold_convert (gfc_array_index_type, string_length));
3255 static void
3256 gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr)
3258 gfc_expr *arg;
3259 gfc_ss *ss;
3260 gfc_se argse;
3261 tree source;
3262 tree source_bytes;
3263 tree type;
3264 tree tmp;
3265 tree lower;
3266 tree upper;
3267 int n;
3269 arg = expr->value.function.actual->expr;
3271 gfc_init_se (&argse, NULL);
3272 ss = gfc_walk_expr (arg);
3274 if (ss == gfc_ss_terminator)
3276 gfc_conv_expr_reference (&argse, arg);
3277 source = argse.expr;
3279 type = TREE_TYPE (build_fold_indirect_ref (argse.expr));
3281 /* Obtain the source word length. */
3282 if (arg->ts.type == BT_CHARACTER)
3283 se->expr = size_of_string_in_bytes (arg->ts.kind,
3284 argse.string_length);
3285 else
3286 se->expr = fold_convert (gfc_array_index_type, size_in_bytes (type));
3288 else
3290 source_bytes = gfc_create_var (gfc_array_index_type, "bytes");
3291 argse.want_pointer = 0;
3292 gfc_conv_expr_descriptor (&argse, arg, ss);
3293 source = gfc_conv_descriptor_data_get (argse.expr);
3294 type = gfc_get_element_type (TREE_TYPE (argse.expr));
3296 /* Obtain the argument's word length. */
3297 if (arg->ts.type == BT_CHARACTER)
3298 tmp = size_of_string_in_bytes (arg->ts.kind, argse.string_length);
3299 else
3300 tmp = fold_convert (gfc_array_index_type,
3301 size_in_bytes (type));
3302 gfc_add_modify_expr (&argse.pre, source_bytes, tmp);
3304 /* Obtain the size of the array in bytes. */
3305 for (n = 0; n < arg->rank; n++)
3307 tree idx;
3308 idx = gfc_rank_cst[n];
3309 lower = gfc_conv_descriptor_lbound (argse.expr, idx);
3310 upper = gfc_conv_descriptor_ubound (argse.expr, idx);
3311 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3312 upper, lower);
3313 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3314 tmp, gfc_index_one_node);
3315 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3316 tmp, source_bytes);
3317 gfc_add_modify_expr (&argse.pre, source_bytes, tmp);
3319 se->expr = source_bytes;
3322 gfc_add_block_to_block (&se->pre, &argse.pre);
3326 /* Intrinsic string comparison functions. */
3328 static void
3329 gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, int op)
3331 tree args[4];
3333 gfc_conv_intrinsic_function_args (se, expr, args, 4);
3335 se->expr
3336 = gfc_build_compare_string (args[0], args[1], args[2], args[3],
3337 expr->value.function.actual->expr->ts.kind);
3338 se->expr = fold_build2 (op, gfc_typenode_for_spec (&expr->ts), se->expr,
3339 build_int_cst (TREE_TYPE (se->expr), 0));
3342 /* Generate a call to the adjustl/adjustr library function. */
3343 static void
3344 gfc_conv_intrinsic_adjust (gfc_se * se, gfc_expr * expr, tree fndecl)
3346 tree args[3];
3347 tree len;
3348 tree type;
3349 tree var;
3350 tree tmp;
3352 gfc_conv_intrinsic_function_args (se, expr, &args[1], 2);
3353 len = args[1];
3355 type = TREE_TYPE (args[2]);
3356 var = gfc_conv_string_tmp (se, type, len);
3357 args[0] = var;
3359 tmp = build_call_expr (fndecl, 3, args[0], args[1], args[2]);
3360 gfc_add_expr_to_block (&se->pre, tmp);
3361 se->expr = var;
3362 se->string_length = len;
3366 /* Array transfer statement.
3367 DEST(1:N) = TRANSFER (SOURCE, MOLD[, SIZE])
3368 where:
3369 typeof<DEST> = typeof<MOLD>
3370 and:
3371 N = min (sizeof (SOURCE(:)), sizeof (DEST(:)),
3372 sizeof (DEST(0) * SIZE). */
3374 static void
3375 gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr)
3377 tree tmp;
3378 tree extent;
3379 tree source;
3380 tree source_type;
3381 tree source_bytes;
3382 tree mold_type;
3383 tree dest_word_len;
3384 tree size_words;
3385 tree size_bytes;
3386 tree upper;
3387 tree lower;
3388 tree stride;
3389 tree stmt;
3390 gfc_actual_arglist *arg;
3391 gfc_se argse;
3392 gfc_ss *ss;
3393 gfc_ss_info *info;
3394 stmtblock_t block;
3395 int n;
3397 gcc_assert (se->loop);
3398 info = &se->ss->data.info;
3400 /* Convert SOURCE. The output from this stage is:-
3401 source_bytes = length of the source in bytes
3402 source = pointer to the source data. */
3403 arg = expr->value.function.actual;
3404 gfc_init_se (&argse, NULL);
3405 ss = gfc_walk_expr (arg->expr);
3407 source_bytes = gfc_create_var (gfc_array_index_type, NULL);
3409 /* Obtain the pointer to source and the length of source in bytes. */
3410 if (ss == gfc_ss_terminator)
3412 gfc_conv_expr_reference (&argse, arg->expr);
3413 source = argse.expr;
3415 source_type = TREE_TYPE (build_fold_indirect_ref (argse.expr));
3417 /* Obtain the source word length. */
3418 if (arg->expr->ts.type == BT_CHARACTER)
3419 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
3420 argse.string_length);
3421 else
3422 tmp = fold_convert (gfc_array_index_type,
3423 size_in_bytes (source_type));
3425 else
3427 argse.want_pointer = 0;
3428 gfc_conv_expr_descriptor (&argse, arg->expr, ss);
3429 source = gfc_conv_descriptor_data_get (argse.expr);
3430 source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
3432 /* Repack the source if not a full variable array. */
3433 if (!(arg->expr->expr_type == EXPR_VARIABLE
3434 && arg->expr->ref->u.ar.type == AR_FULL))
3436 tmp = build_fold_addr_expr (argse.expr);
3437 source = build_call_expr (gfor_fndecl_in_pack, 1, tmp);
3438 source = gfc_evaluate_now (source, &argse.pre);
3440 /* Free the temporary. */
3441 gfc_start_block (&block);
3442 tmp = gfc_call_free (convert (pvoid_type_node, source));
3443 gfc_add_expr_to_block (&block, tmp);
3444 stmt = gfc_finish_block (&block);
3446 /* Clean up if it was repacked. */
3447 gfc_init_block (&block);
3448 tmp = gfc_conv_array_data (argse.expr);
3449 tmp = fold_build2 (NE_EXPR, boolean_type_node, source, tmp);
3450 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
3451 gfc_add_expr_to_block (&block, tmp);
3452 gfc_add_block_to_block (&block, &se->post);
3453 gfc_init_block (&se->post);
3454 gfc_add_block_to_block (&se->post, &block);
3457 /* Obtain the source word length. */
3458 if (arg->expr->ts.type == BT_CHARACTER)
3459 tmp = size_of_string_in_bytes (arg->expr->ts.kind,
3460 argse.string_length);
3461 else
3462 tmp = fold_convert (gfc_array_index_type,
3463 size_in_bytes (source_type));
3465 /* Obtain the size of the array in bytes. */
3466 extent = gfc_create_var (gfc_array_index_type, NULL);
3467 for (n = 0; n < arg->expr->rank; n++)
3469 tree idx;
3470 idx = gfc_rank_cst[n];
3471 gfc_add_modify_expr (&argse.pre, source_bytes, tmp);
3472 stride = gfc_conv_descriptor_stride (argse.expr, idx);
3473 lower = gfc_conv_descriptor_lbound (argse.expr, idx);
3474 upper = gfc_conv_descriptor_ubound (argse.expr, idx);
3475 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3476 upper, lower);
3477 gfc_add_modify_expr (&argse.pre, extent, tmp);
3478 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3479 extent, gfc_index_one_node);
3480 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3481 tmp, source_bytes);
3485 gfc_add_modify_expr (&argse.pre, source_bytes, tmp);
3486 gfc_add_block_to_block (&se->pre, &argse.pre);
3487 gfc_add_block_to_block (&se->post, &argse.post);
3489 /* Now convert MOLD. The outputs are:
3490 mold_type = the TREE type of MOLD
3491 dest_word_len = destination word length in bytes. */
3492 arg = arg->next;
3494 gfc_init_se (&argse, NULL);
3495 ss = gfc_walk_expr (arg->expr);
3497 if (ss == gfc_ss_terminator)
3499 gfc_conv_expr_reference (&argse, arg->expr);
3500 mold_type = TREE_TYPE (build_fold_indirect_ref (argse.expr));
3502 else
3504 gfc_init_se (&argse, NULL);
3505 argse.want_pointer = 0;
3506 gfc_conv_expr_descriptor (&argse, arg->expr, ss);
3507 mold_type = gfc_get_element_type (TREE_TYPE (argse.expr));
3510 if (arg->expr->ts.type == BT_CHARACTER)
3512 tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length);
3513 mold_type = gfc_get_character_type_len (arg->expr->ts.kind, tmp);
3515 else
3516 tmp = fold_convert (gfc_array_index_type,
3517 size_in_bytes (mold_type));
3519 dest_word_len = gfc_create_var (gfc_array_index_type, NULL);
3520 gfc_add_modify_expr (&se->pre, dest_word_len, tmp);
3522 /* Finally convert SIZE, if it is present. */
3523 arg = arg->next;
3524 size_words = gfc_create_var (gfc_array_index_type, NULL);
3526 if (arg->expr)
3528 gfc_init_se (&argse, NULL);
3529 gfc_conv_expr_reference (&argse, arg->expr);
3530 tmp = convert (gfc_array_index_type,
3531 build_fold_indirect_ref (argse.expr));
3532 gfc_add_block_to_block (&se->pre, &argse.pre);
3533 gfc_add_block_to_block (&se->post, &argse.post);
3535 else
3536 tmp = NULL_TREE;
3538 size_bytes = gfc_create_var (gfc_array_index_type, NULL);
3539 if (tmp != NULL_TREE)
3541 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3542 tmp, dest_word_len);
3543 tmp = fold_build2 (MIN_EXPR, gfc_array_index_type,
3544 tmp, source_bytes);
3546 else
3547 tmp = source_bytes;
3549 gfc_add_modify_expr (&se->pre, size_bytes, tmp);
3550 gfc_add_modify_expr (&se->pre, size_words,
3551 fold_build2 (CEIL_DIV_EXPR, gfc_array_index_type,
3552 size_bytes, dest_word_len));
3554 /* Evaluate the bounds of the result. If the loop range exists, we have
3555 to check if it is too large. If so, we modify loop->to be consistent
3556 with min(size, size(source)). Otherwise, size is made consistent with
3557 the loop range, so that the right number of bytes is transferred.*/
3558 n = se->loop->order[0];
3559 if (se->loop->to[n] != NULL_TREE)
3561 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3562 se->loop->to[n], se->loop->from[n]);
3563 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3564 tmp, gfc_index_one_node);
3565 tmp = fold_build2 (MIN_EXPR, gfc_array_index_type,
3566 tmp, size_words);
3567 gfc_add_modify_expr (&se->pre, size_words, tmp);
3568 gfc_add_modify_expr (&se->pre, size_bytes,
3569 fold_build2 (MULT_EXPR, gfc_array_index_type,
3570 size_words, dest_word_len));
3571 upper = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3572 size_words, se->loop->from[n]);
3573 upper = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3574 upper, gfc_index_one_node);
3576 else
3578 upper = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3579 size_words, gfc_index_one_node);
3580 se->loop->from[n] = gfc_index_zero_node;
3583 se->loop->to[n] = upper;
3585 /* Build a destination descriptor, using the pointer, source, as the
3586 data field. This is already allocated so set callee_alloc.
3587 FIXME callee_alloc is not set! */
3589 gfc_trans_create_temp_array (&se->pre, &se->post, se->loop,
3590 info, mold_type, false, true, false);
3592 /* Cast the pointer to the result. */
3593 tmp = gfc_conv_descriptor_data_get (info->descriptor);
3594 tmp = fold_convert (pvoid_type_node, tmp);
3596 /* Use memcpy to do the transfer. */
3597 tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY],
3599 tmp,
3600 fold_convert (pvoid_type_node, source),
3601 size_bytes);
3602 gfc_add_expr_to_block (&se->pre, tmp);
3604 se->expr = info->descriptor;
3605 if (expr->ts.type == BT_CHARACTER)
3606 se->string_length = dest_word_len;
3610 /* Scalar transfer statement.
3611 TRANSFER (source, mold) = memcpy(&tmpdecl, &source, size), tmpdecl. */
3613 static void
3614 gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
3616 gfc_actual_arglist *arg;
3617 gfc_se argse;
3618 tree type;
3619 tree ptr;
3620 gfc_ss *ss;
3621 tree tmpdecl, tmp;
3623 /* Get a pointer to the source. */
3624 arg = expr->value.function.actual;
3625 ss = gfc_walk_expr (arg->expr);
3626 gfc_init_se (&argse, NULL);
3627 if (ss == gfc_ss_terminator)
3628 gfc_conv_expr_reference (&argse, arg->expr);
3629 else
3630 gfc_conv_array_parameter (&argse, arg->expr, ss, 1);
3631 gfc_add_block_to_block (&se->pre, &argse.pre);
3632 gfc_add_block_to_block (&se->post, &argse.post);
3633 ptr = argse.expr;
3635 arg = arg->next;
3636 type = gfc_typenode_for_spec (&expr->ts);
3638 if (expr->ts.type == BT_CHARACTER)
3640 ptr = convert (build_pointer_type (type), ptr);
3641 gfc_init_se (&argse, NULL);
3642 gfc_conv_expr (&argse, arg->expr);
3643 gfc_add_block_to_block (&se->pre, &argse.pre);
3644 gfc_add_block_to_block (&se->post, &argse.post);
3645 se->expr = ptr;
3646 se->string_length = argse.string_length;
3648 else
3650 tree moldsize;
3651 tmpdecl = gfc_create_var (type, "transfer");
3652 moldsize = size_in_bytes (type);
3654 /* Use memcpy to do the transfer. */
3655 tmp = fold_build1 (ADDR_EXPR, build_pointer_type (type), tmpdecl);
3656 tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
3657 fold_convert (pvoid_type_node, tmp),
3658 fold_convert (pvoid_type_node, ptr),
3659 moldsize);
3660 gfc_add_expr_to_block (&se->pre, tmp);
3662 se->expr = tmpdecl;
3667 /* Generate code for the ALLOCATED intrinsic.
3668 Generate inline code that directly check the address of the argument. */
3670 static void
3671 gfc_conv_allocated (gfc_se *se, gfc_expr *expr)
3673 gfc_actual_arglist *arg1;
3674 gfc_se arg1se;
3675 gfc_ss *ss1;
3676 tree tmp;
3678 gfc_init_se (&arg1se, NULL);
3679 arg1 = expr->value.function.actual;
3680 ss1 = gfc_walk_expr (arg1->expr);
3681 arg1se.descriptor_only = 1;
3682 gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1);
3684 tmp = gfc_conv_descriptor_data_get (arg1se.expr);
3685 tmp = fold_build2 (NE_EXPR, boolean_type_node,
3686 tmp, fold_convert (TREE_TYPE (tmp), null_pointer_node));
3687 se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
3691 /* Generate code for the ASSOCIATED intrinsic.
3692 If both POINTER and TARGET are arrays, generate a call to library function
3693 _gfor_associated, and pass descriptors of POINTER and TARGET to it.
3694 In other cases, generate inline code that directly compare the address of
3695 POINTER with the address of TARGET. */
3697 static void
3698 gfc_conv_associated (gfc_se *se, gfc_expr *expr)
3700 gfc_actual_arglist *arg1;
3701 gfc_actual_arglist *arg2;
3702 gfc_se arg1se;
3703 gfc_se arg2se;
3704 tree tmp2;
3705 tree tmp;
3706 tree nonzero_charlen;
3707 tree nonzero_arraylen;
3708 gfc_ss *ss1, *ss2;
3710 gfc_init_se (&arg1se, NULL);
3711 gfc_init_se (&arg2se, NULL);
3712 arg1 = expr->value.function.actual;
3713 arg2 = arg1->next;
3714 ss1 = gfc_walk_expr (arg1->expr);
3716 if (!arg2->expr)
3718 /* No optional target. */
3719 if (ss1 == gfc_ss_terminator)
3721 /* A pointer to a scalar. */
3722 arg1se.want_pointer = 1;
3723 gfc_conv_expr (&arg1se, arg1->expr);
3724 tmp2 = arg1se.expr;
3726 else
3728 /* A pointer to an array. */
3729 gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1);
3730 tmp2 = gfc_conv_descriptor_data_get (arg1se.expr);
3732 gfc_add_block_to_block (&se->pre, &arg1se.pre);
3733 gfc_add_block_to_block (&se->post, &arg1se.post);
3734 tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp2,
3735 fold_convert (TREE_TYPE (tmp2), null_pointer_node));
3736 se->expr = tmp;
3738 else
3740 /* An optional target. */
3741 ss2 = gfc_walk_expr (arg2->expr);
3743 nonzero_charlen = NULL_TREE;
3744 if (arg1->expr->ts.type == BT_CHARACTER)
3745 nonzero_charlen = fold_build2 (NE_EXPR, boolean_type_node,
3746 arg1->expr->ts.cl->backend_decl,
3747 integer_zero_node);
3749 if (ss1 == gfc_ss_terminator)
3751 /* A pointer to a scalar. */
3752 gcc_assert (ss2 == gfc_ss_terminator);
3753 arg1se.want_pointer = 1;
3754 gfc_conv_expr (&arg1se, arg1->expr);
3755 arg2se.want_pointer = 1;
3756 gfc_conv_expr (&arg2se, arg2->expr);
3757 gfc_add_block_to_block (&se->pre, &arg1se.pre);
3758 gfc_add_block_to_block (&se->post, &arg1se.post);
3759 tmp = fold_build2 (EQ_EXPR, boolean_type_node,
3760 arg1se.expr, arg2se.expr);
3761 tmp2 = fold_build2 (NE_EXPR, boolean_type_node,
3762 arg1se.expr, null_pointer_node);
3763 se->expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3764 tmp, tmp2);
3766 else
3768 /* An array pointer of zero length is not associated if target is
3769 present. */
3770 arg1se.descriptor_only = 1;
3771 gfc_conv_expr_lhs (&arg1se, arg1->expr);
3772 tmp = gfc_conv_descriptor_stride (arg1se.expr,
3773 gfc_rank_cst[arg1->expr->rank - 1]);
3774 nonzero_arraylen = fold_build2 (NE_EXPR, boolean_type_node, tmp,
3775 build_int_cst (TREE_TYPE (tmp), 0));
3777 /* A pointer to an array, call library function _gfor_associated. */
3778 gcc_assert (ss2 != gfc_ss_terminator);
3779 arg1se.want_pointer = 1;
3780 gfc_conv_expr_descriptor (&arg1se, arg1->expr, ss1);
3782 arg2se.want_pointer = 1;
3783 gfc_conv_expr_descriptor (&arg2se, arg2->expr, ss2);
3784 gfc_add_block_to_block (&se->pre, &arg2se.pre);
3785 gfc_add_block_to_block (&se->post, &arg2se.post);
3786 se->expr = build_call_expr (gfor_fndecl_associated, 2,
3787 arg1se.expr, arg2se.expr);
3788 se->expr = convert (boolean_type_node, se->expr);
3789 se->expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3790 se->expr, nonzero_arraylen);
3793 /* If target is present zero character length pointers cannot
3794 be associated. */
3795 if (nonzero_charlen != NULL_TREE)
3796 se->expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3797 se->expr, nonzero_charlen);
3800 se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3804 /* Generate code for SELECTED_CHAR_KIND (NAME) intrinsic function. */
3806 static void
3807 gfc_conv_intrinsic_sc_kind (gfc_se *se, gfc_expr *expr)
3809 tree args[2];
3811 gfc_conv_intrinsic_function_args (se, expr, args, 2);
3812 se->expr = build_call_expr (gfor_fndecl_sc_kind, 2, args[0], args[1]);
3813 se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
3817 /* Generate code for SELECTED_INT_KIND (R) intrinsic function. */
3819 static void
3820 gfc_conv_intrinsic_si_kind (gfc_se *se, gfc_expr *expr)
3822 tree arg, type;
3824 gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
3826 /* The argument to SELECTED_INT_KIND is INTEGER(4). */
3827 type = gfc_get_int_type (4);
3828 arg = build_fold_addr_expr (fold_convert (type, arg));
3830 /* Convert it to the required type. */
3831 type = gfc_typenode_for_spec (&expr->ts);
3832 se->expr = build_call_expr (gfor_fndecl_si_kind, 1, arg);
3833 se->expr = fold_convert (type, se->expr);
3837 /* Generate code for SELECTED_REAL_KIND (P, R) intrinsic function. */
3839 static void
3840 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
3842 gfc_actual_arglist *actual;
3843 tree args, type;
3844 gfc_se argse;
3846 args = NULL_TREE;
3847 for (actual = expr->value.function.actual; actual; actual = actual->next)
3849 gfc_init_se (&argse, se);
3851 /* Pass a NULL pointer for an absent arg. */
3852 if (actual->expr == NULL)
3853 argse.expr = null_pointer_node;
3854 else
3856 gfc_typespec ts;
3857 gfc_clear_ts (&ts);
3859 if (actual->expr->ts.kind != gfc_c_int_kind)
3861 /* The arguments to SELECTED_REAL_KIND are INTEGER(4). */
3862 ts.type = BT_INTEGER;
3863 ts.kind = gfc_c_int_kind;
3864 gfc_convert_type (actual->expr, &ts, 2);
3866 gfc_conv_expr_reference (&argse, actual->expr);
3869 gfc_add_block_to_block (&se->pre, &argse.pre);
3870 gfc_add_block_to_block (&se->post, &argse.post);
3871 args = gfc_chainon_list (args, argse.expr);
3874 /* Convert it to the required type. */
3875 type = gfc_typenode_for_spec (&expr->ts);
3876 se->expr = build_function_call_expr (gfor_fndecl_sr_kind, args);
3877 se->expr = fold_convert (type, se->expr);
3881 /* Generate code for TRIM (A) intrinsic function. */
3883 static void
3884 gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
3886 tree var;
3887 tree len;
3888 tree addr;
3889 tree tmp;
3890 tree cond;
3891 tree fndecl;
3892 tree function;
3893 tree *args;
3894 unsigned int num_args;
3896 num_args = gfc_intrinsic_argument_list_length (expr) + 2;
3897 args = (tree *) alloca (sizeof (tree) * num_args);
3899 var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
3900 addr = gfc_build_addr_expr (ppvoid_type_node, var);
3901 len = gfc_create_var (gfc_get_int_type (4), "len");
3903 gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
3904 args[0] = build_fold_addr_expr (len);
3905 args[1] = addr;
3907 if (expr->ts.kind == 1)
3908 function = gfor_fndecl_string_trim;
3909 else if (expr->ts.kind == 4)
3910 function = gfor_fndecl_string_trim_char4;
3911 else
3912 gcc_unreachable ();
3914 fndecl = build_addr (function, current_function_decl);
3915 tmp = build_call_array (TREE_TYPE (TREE_TYPE (function)), fndecl,
3916 num_args, args);
3917 gfc_add_expr_to_block (&se->pre, tmp);
3919 /* Free the temporary afterwards, if necessary. */
3920 cond = fold_build2 (GT_EXPR, boolean_type_node,
3921 len, build_int_cst (TREE_TYPE (len), 0));
3922 tmp = gfc_call_free (var);
3923 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
3924 gfc_add_expr_to_block (&se->post, tmp);
3926 se->expr = var;
3927 se->string_length = len;
3931 /* Generate code for REPEAT (STRING, NCOPIES) intrinsic function. */
3933 static void
3934 gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
3936 tree args[3], ncopies, dest, dlen, src, slen, ncopies_type;
3937 tree type, cond, tmp, count, exit_label, n, max, largest;
3938 tree size;
3939 stmtblock_t block, body;
3940 int i;
3942 /* We store in charsize the size of a character. */
3943 i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
3944 size = build_int_cst (size_type_node, gfc_character_kinds[i].bit_size / 8);
3946 /* Get the arguments. */
3947 gfc_conv_intrinsic_function_args (se, expr, args, 3);
3948 slen = fold_convert (size_type_node, gfc_evaluate_now (args[0], &se->pre));
3949 src = args[1];
3950 ncopies = gfc_evaluate_now (args[2], &se->pre);
3951 ncopies_type = TREE_TYPE (ncopies);
3953 /* Check that NCOPIES is not negative. */
3954 cond = fold_build2 (LT_EXPR, boolean_type_node, ncopies,
3955 build_int_cst (ncopies_type, 0));
3956 gfc_trans_runtime_check (cond, &se->pre, &expr->where,
3957 "Argument NCOPIES of REPEAT intrinsic is negative "
3958 "(its value is %lld)",
3959 fold_convert (long_integer_type_node, ncopies));
3961 /* If the source length is zero, any non negative value of NCOPIES
3962 is valid, and nothing happens. */
3963 n = gfc_create_var (ncopies_type, "ncopies");
3964 cond = fold_build2 (EQ_EXPR, boolean_type_node, slen,
3965 build_int_cst (size_type_node, 0));
3966 tmp = fold_build3 (COND_EXPR, ncopies_type, cond,
3967 build_int_cst (ncopies_type, 0), ncopies);
3968 gfc_add_modify_expr (&se->pre, n, tmp);
3969 ncopies = n;
3971 /* Check that ncopies is not too large: ncopies should be less than
3972 (or equal to) MAX / slen, where MAX is the maximal integer of
3973 the gfc_charlen_type_node type. If slen == 0, we need a special
3974 case to avoid the division by zero. */
3975 i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
3976 max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, gfc_charlen_int_kind);
3977 max = fold_build2 (TRUNC_DIV_EXPR, size_type_node,
3978 fold_convert (size_type_node, max), slen);
3979 largest = TYPE_PRECISION (size_type_node) > TYPE_PRECISION (ncopies_type)
3980 ? size_type_node : ncopies_type;
3981 cond = fold_build2 (GT_EXPR, boolean_type_node,
3982 fold_convert (largest, ncopies),
3983 fold_convert (largest, max));
3984 tmp = fold_build2 (EQ_EXPR, boolean_type_node, slen,
3985 build_int_cst (size_type_node, 0));
3986 cond = fold_build3 (COND_EXPR, boolean_type_node, tmp, boolean_false_node,
3987 cond);
3988 gfc_trans_runtime_check (cond, &se->pre, &expr->where,
3989 "Argument NCOPIES of REPEAT intrinsic is too large");
3991 /* Compute the destination length. */
3992 dlen = fold_build2 (MULT_EXPR, gfc_charlen_type_node,
3993 fold_convert (gfc_charlen_type_node, slen),
3994 fold_convert (gfc_charlen_type_node, ncopies));
3995 type = gfc_get_character_type (expr->ts.kind, expr->ts.cl);
3996 dest = gfc_conv_string_tmp (se, build_pointer_type (type), dlen);
3998 /* Generate the code to do the repeat operation:
3999 for (i = 0; i < ncopies; i++)
4000 memmove (dest + (i * slen * size), src, slen*size); */
4001 gfc_start_block (&block);
4002 count = gfc_create_var (ncopies_type, "count");
4003 gfc_add_modify_expr (&block, count, build_int_cst (ncopies_type, 0));
4004 exit_label = gfc_build_label_decl (NULL_TREE);
4006 /* Start the loop body. */
4007 gfc_start_block (&body);
4009 /* Exit the loop if count >= ncopies. */
4010 cond = fold_build2 (GE_EXPR, boolean_type_node, count, ncopies);
4011 tmp = build1_v (GOTO_EXPR, exit_label);
4012 TREE_USED (exit_label) = 1;
4013 tmp = fold_build3 (COND_EXPR, void_type_node, cond, tmp,
4014 build_empty_stmt ());
4015 gfc_add_expr_to_block (&body, tmp);
4017 /* Call memmove (dest + (i*slen*size), src, slen*size). */
4018 tmp = fold_build2 (MULT_EXPR, gfc_charlen_type_node,
4019 fold_convert (gfc_charlen_type_node, slen),
4020 fold_convert (gfc_charlen_type_node, count));
4021 tmp = fold_build2 (MULT_EXPR, gfc_charlen_type_node,
4022 tmp, fold_convert (gfc_charlen_type_node, size));
4023 tmp = fold_build2 (POINTER_PLUS_EXPR, pvoid_type_node,
4024 fold_convert (pvoid_type_node, dest),
4025 fold_convert (sizetype, tmp));
4026 tmp = build_call_expr (built_in_decls[BUILT_IN_MEMMOVE], 3, tmp, src,
4027 fold_build2 (MULT_EXPR, size_type_node, slen,
4028 fold_convert (size_type_node, size)));
4029 gfc_add_expr_to_block (&body, tmp);
4031 /* Increment count. */
4032 tmp = fold_build2 (PLUS_EXPR, ncopies_type,
4033 count, build_int_cst (TREE_TYPE (count), 1));
4034 gfc_add_modify_expr (&body, count, tmp);
4036 /* Build the loop. */
4037 tmp = build1_v (LOOP_EXPR, gfc_finish_block (&body));
4038 gfc_add_expr_to_block (&block, tmp);
4040 /* Add the exit label. */
4041 tmp = build1_v (LABEL_EXPR, exit_label);
4042 gfc_add_expr_to_block (&block, tmp);
4044 /* Finish the block. */
4045 tmp = gfc_finish_block (&block);
4046 gfc_add_expr_to_block (&se->pre, tmp);
4048 /* Set the result value. */
4049 se->expr = dest;
4050 se->string_length = dlen;
4054 /* Generate code for the IARGC intrinsic. */
4056 static void
4057 gfc_conv_intrinsic_iargc (gfc_se * se, gfc_expr * expr)
4059 tree tmp;
4060 tree fndecl;
4061 tree type;
4063 /* Call the library function. This always returns an INTEGER(4). */
4064 fndecl = gfor_fndecl_iargc;
4065 tmp = build_call_expr (fndecl, 0);
4067 /* Convert it to the required type. */
4068 type = gfc_typenode_for_spec (&expr->ts);
4069 tmp = fold_convert (type, tmp);
4071 se->expr = tmp;
4075 /* The loc intrinsic returns the address of its argument as
4076 gfc_index_integer_kind integer. */
4078 static void
4079 gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
4081 tree temp_var;
4082 gfc_expr *arg_expr;
4083 gfc_ss *ss;
4085 gcc_assert (!se->ss);
4087 arg_expr = expr->value.function.actual->expr;
4088 ss = gfc_walk_expr (arg_expr);
4089 if (ss == gfc_ss_terminator)
4090 gfc_conv_expr_reference (se, arg_expr);
4091 else
4092 gfc_conv_array_parameter (se, arg_expr, ss, 1);
4093 se->expr= convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
4095 /* Create a temporary variable for loc return value. Without this,
4096 we get an error an ICE in gcc/expr.c(expand_expr_addr_expr_1). */
4097 temp_var = gfc_create_var (gfc_get_int_type (gfc_index_integer_kind), NULL);
4098 gfc_add_modify_expr (&se->pre, temp_var, se->expr);
4099 se->expr = temp_var;
4102 /* Generate code for an intrinsic function. Some map directly to library
4103 calls, others get special handling. In some cases the name of the function
4104 used depends on the type specifiers. */
4106 void
4107 gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
4109 gfc_intrinsic_sym *isym;
4110 const char *name;
4111 int lib, kind;
4112 tree fndecl;
4114 isym = expr->value.function.isym;
4116 name = &expr->value.function.name[2];
4118 if (expr->rank > 0 && !expr->inline_noncopying_intrinsic)
4120 lib = gfc_is_intrinsic_libcall (expr);
4121 if (lib != 0)
4123 if (lib == 1)
4124 se->ignore_optional = 1;
4125 gfc_conv_intrinsic_funcall (se, expr);
4126 return;
4130 switch (expr->value.function.isym->id)
4132 case GFC_ISYM_NONE:
4133 gcc_unreachable ();
4135 case GFC_ISYM_REPEAT:
4136 gfc_conv_intrinsic_repeat (se, expr);
4137 break;
4139 case GFC_ISYM_TRIM:
4140 gfc_conv_intrinsic_trim (se, expr);
4141 break;
4143 case GFC_ISYM_SC_KIND:
4144 gfc_conv_intrinsic_sc_kind (se, expr);
4145 break;
4147 case GFC_ISYM_SI_KIND:
4148 gfc_conv_intrinsic_si_kind (se, expr);
4149 break;
4151 case GFC_ISYM_SR_KIND:
4152 gfc_conv_intrinsic_sr_kind (se, expr);
4153 break;
4155 case GFC_ISYM_EXPONENT:
4156 gfc_conv_intrinsic_exponent (se, expr);
4157 break;
4159 case GFC_ISYM_SCAN:
4160 kind = expr->value.function.actual->expr->ts.kind;
4161 if (kind == 1)
4162 fndecl = gfor_fndecl_string_scan;
4163 else if (kind == 4)
4164 fndecl = gfor_fndecl_string_scan_char4;
4165 else
4166 gcc_unreachable ();
4168 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
4169 break;
4171 case GFC_ISYM_VERIFY:
4172 kind = expr->value.function.actual->expr->ts.kind;
4173 if (kind == 1)
4174 fndecl = gfor_fndecl_string_verify;
4175 else if (kind == 4)
4176 fndecl = gfor_fndecl_string_verify_char4;
4177 else
4178 gcc_unreachable ();
4180 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
4181 break;
4183 case GFC_ISYM_ALLOCATED:
4184 gfc_conv_allocated (se, expr);
4185 break;
4187 case GFC_ISYM_ASSOCIATED:
4188 gfc_conv_associated(se, expr);
4189 break;
4191 case GFC_ISYM_ABS:
4192 gfc_conv_intrinsic_abs (se, expr);
4193 break;
4195 case GFC_ISYM_ADJUSTL:
4196 if (expr->ts.kind == 1)
4197 fndecl = gfor_fndecl_adjustl;
4198 else if (expr->ts.kind == 4)
4199 fndecl = gfor_fndecl_adjustl_char4;
4200 else
4201 gcc_unreachable ();
4203 gfc_conv_intrinsic_adjust (se, expr, fndecl);
4204 break;
4206 case GFC_ISYM_ADJUSTR:
4207 if (expr->ts.kind == 1)
4208 fndecl = gfor_fndecl_adjustr;
4209 else if (expr->ts.kind == 4)
4210 fndecl = gfor_fndecl_adjustr_char4;
4211 else
4212 gcc_unreachable ();
4214 gfc_conv_intrinsic_adjust (se, expr, fndecl);
4215 break;
4217 case GFC_ISYM_AIMAG:
4218 gfc_conv_intrinsic_imagpart (se, expr);
4219 break;
4221 case GFC_ISYM_AINT:
4222 gfc_conv_intrinsic_aint (se, expr, RND_TRUNC);
4223 break;
4225 case GFC_ISYM_ALL:
4226 gfc_conv_intrinsic_anyall (se, expr, EQ_EXPR);
4227 break;
4229 case GFC_ISYM_ANINT:
4230 gfc_conv_intrinsic_aint (se, expr, RND_ROUND);
4231 break;
4233 case GFC_ISYM_AND:
4234 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
4235 break;
4237 case GFC_ISYM_ANY:
4238 gfc_conv_intrinsic_anyall (se, expr, NE_EXPR);
4239 break;
4241 case GFC_ISYM_BTEST:
4242 gfc_conv_intrinsic_btest (se, expr);
4243 break;
4245 case GFC_ISYM_ACHAR:
4246 case GFC_ISYM_CHAR:
4247 gfc_conv_intrinsic_char (se, expr);
4248 break;
4250 case GFC_ISYM_CONVERSION:
4251 case GFC_ISYM_REAL:
4252 case GFC_ISYM_LOGICAL:
4253 case GFC_ISYM_DBLE:
4254 gfc_conv_intrinsic_conversion (se, expr);
4255 break;
4257 /* Integer conversions are handled separately to make sure we get the
4258 correct rounding mode. */
4259 case GFC_ISYM_INT:
4260 case GFC_ISYM_INT2:
4261 case GFC_ISYM_INT8:
4262 case GFC_ISYM_LONG:
4263 gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
4264 break;
4266 case GFC_ISYM_NINT:
4267 gfc_conv_intrinsic_int (se, expr, RND_ROUND);
4268 break;
4270 case GFC_ISYM_CEILING:
4271 gfc_conv_intrinsic_int (se, expr, RND_CEIL);
4272 break;
4274 case GFC_ISYM_FLOOR:
4275 gfc_conv_intrinsic_int (se, expr, RND_FLOOR);
4276 break;
4278 case GFC_ISYM_MOD:
4279 gfc_conv_intrinsic_mod (se, expr, 0);
4280 break;
4282 case GFC_ISYM_MODULO:
4283 gfc_conv_intrinsic_mod (se, expr, 1);
4284 break;
4286 case GFC_ISYM_CMPLX:
4287 gfc_conv_intrinsic_cmplx (se, expr, name[5] == '1');
4288 break;
4290 case GFC_ISYM_COMMAND_ARGUMENT_COUNT:
4291 gfc_conv_intrinsic_iargc (se, expr);
4292 break;
4294 case GFC_ISYM_COMPLEX:
4295 gfc_conv_intrinsic_cmplx (se, expr, 1);
4296 break;
4298 case GFC_ISYM_CONJG:
4299 gfc_conv_intrinsic_conjg (se, expr);
4300 break;
4302 case GFC_ISYM_COUNT:
4303 gfc_conv_intrinsic_count (se, expr);
4304 break;
4306 case GFC_ISYM_CTIME:
4307 gfc_conv_intrinsic_ctime (se, expr);
4308 break;
4310 case GFC_ISYM_DIM:
4311 gfc_conv_intrinsic_dim (se, expr);
4312 break;
4314 case GFC_ISYM_DOT_PRODUCT:
4315 gfc_conv_intrinsic_dot_product (se, expr);
4316 break;
4318 case GFC_ISYM_DPROD:
4319 gfc_conv_intrinsic_dprod (se, expr);
4320 break;
4322 case GFC_ISYM_FDATE:
4323 gfc_conv_intrinsic_fdate (se, expr);
4324 break;
4326 case GFC_ISYM_FRACTION:
4327 gfc_conv_intrinsic_fraction (se, expr);
4328 break;
4330 case GFC_ISYM_IAND:
4331 gfc_conv_intrinsic_bitop (se, expr, BIT_AND_EXPR);
4332 break;
4334 case GFC_ISYM_IBCLR:
4335 gfc_conv_intrinsic_singlebitop (se, expr, 0);
4336 break;
4338 case GFC_ISYM_IBITS:
4339 gfc_conv_intrinsic_ibits (se, expr);
4340 break;
4342 case GFC_ISYM_IBSET:
4343 gfc_conv_intrinsic_singlebitop (se, expr, 1);
4344 break;
4346 case GFC_ISYM_IACHAR:
4347 case GFC_ISYM_ICHAR:
4348 /* We assume ASCII character sequence. */
4349 gfc_conv_intrinsic_ichar (se, expr);
4350 break;
4352 case GFC_ISYM_IARGC:
4353 gfc_conv_intrinsic_iargc (se, expr);
4354 break;
4356 case GFC_ISYM_IEOR:
4357 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
4358 break;
4360 case GFC_ISYM_INDEX:
4361 kind = expr->value.function.actual->expr->ts.kind;
4362 if (kind == 1)
4363 fndecl = gfor_fndecl_string_index;
4364 else if (kind == 4)
4365 fndecl = gfor_fndecl_string_index_char4;
4366 else
4367 gcc_unreachable ();
4369 gfc_conv_intrinsic_index_scan_verify (se, expr, fndecl);
4370 break;
4372 case GFC_ISYM_IOR:
4373 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
4374 break;
4376 case GFC_ISYM_IS_IOSTAT_END:
4377 gfc_conv_has_intvalue (se, expr, LIBERROR_END);
4378 break;
4380 case GFC_ISYM_IS_IOSTAT_EOR:
4381 gfc_conv_has_intvalue (se, expr, LIBERROR_EOR);
4382 break;
4384 case GFC_ISYM_ISNAN:
4385 gfc_conv_intrinsic_isnan (se, expr);
4386 break;
4388 case GFC_ISYM_LSHIFT:
4389 gfc_conv_intrinsic_rlshift (se, expr, 0);
4390 break;
4392 case GFC_ISYM_RSHIFT:
4393 gfc_conv_intrinsic_rlshift (se, expr, 1);
4394 break;
4396 case GFC_ISYM_ISHFT:
4397 gfc_conv_intrinsic_ishft (se, expr);
4398 break;
4400 case GFC_ISYM_ISHFTC:
4401 gfc_conv_intrinsic_ishftc (se, expr);
4402 break;
4404 case GFC_ISYM_LBOUND:
4405 gfc_conv_intrinsic_bound (se, expr, 0);
4406 break;
4408 case GFC_ISYM_TRANSPOSE:
4409 if (se->ss && se->ss->useflags)
4411 gfc_conv_tmp_array_ref (se);
4412 gfc_advance_se_ss_chain (se);
4414 else
4415 gfc_conv_array_transpose (se, expr->value.function.actual->expr);
4416 break;
4418 case GFC_ISYM_LEN:
4419 gfc_conv_intrinsic_len (se, expr);
4420 break;
4422 case GFC_ISYM_LEN_TRIM:
4423 gfc_conv_intrinsic_len_trim (se, expr);
4424 break;
4426 case GFC_ISYM_LGE:
4427 gfc_conv_intrinsic_strcmp (se, expr, GE_EXPR);
4428 break;
4430 case GFC_ISYM_LGT:
4431 gfc_conv_intrinsic_strcmp (se, expr, GT_EXPR);
4432 break;
4434 case GFC_ISYM_LLE:
4435 gfc_conv_intrinsic_strcmp (se, expr, LE_EXPR);
4436 break;
4438 case GFC_ISYM_LLT:
4439 gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR);
4440 break;
4442 case GFC_ISYM_MAX:
4443 if (expr->ts.type == BT_CHARACTER)
4444 gfc_conv_intrinsic_minmax_char (se, expr, 1);
4445 else
4446 gfc_conv_intrinsic_minmax (se, expr, GT_EXPR);
4447 break;
4449 case GFC_ISYM_MAXLOC:
4450 gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR);
4451 break;
4453 case GFC_ISYM_MAXVAL:
4454 gfc_conv_intrinsic_minmaxval (se, expr, GT_EXPR);
4455 break;
4457 case GFC_ISYM_MERGE:
4458 gfc_conv_intrinsic_merge (se, expr);
4459 break;
4461 case GFC_ISYM_MIN:
4462 if (expr->ts.type == BT_CHARACTER)
4463 gfc_conv_intrinsic_minmax_char (se, expr, -1);
4464 else
4465 gfc_conv_intrinsic_minmax (se, expr, LT_EXPR);
4466 break;
4468 case GFC_ISYM_MINLOC:
4469 gfc_conv_intrinsic_minmaxloc (se, expr, LT_EXPR);
4470 break;
4472 case GFC_ISYM_MINVAL:
4473 gfc_conv_intrinsic_minmaxval (se, expr, LT_EXPR);
4474 break;
4476 case GFC_ISYM_NEAREST:
4477 gfc_conv_intrinsic_nearest (se, expr);
4478 break;
4480 case GFC_ISYM_NOT:
4481 gfc_conv_intrinsic_not (se, expr);
4482 break;
4484 case GFC_ISYM_OR:
4485 gfc_conv_intrinsic_bitop (se, expr, BIT_IOR_EXPR);
4486 break;
4488 case GFC_ISYM_PRESENT:
4489 gfc_conv_intrinsic_present (se, expr);
4490 break;
4492 case GFC_ISYM_PRODUCT:
4493 gfc_conv_intrinsic_arith (se, expr, MULT_EXPR);
4494 break;
4496 case GFC_ISYM_RRSPACING:
4497 gfc_conv_intrinsic_rrspacing (se, expr);
4498 break;
4500 case GFC_ISYM_SET_EXPONENT:
4501 gfc_conv_intrinsic_set_exponent (se, expr);
4502 break;
4504 case GFC_ISYM_SCALE:
4505 gfc_conv_intrinsic_scale (se, expr);
4506 break;
4508 case GFC_ISYM_SIGN:
4509 gfc_conv_intrinsic_sign (se, expr);
4510 break;
4512 case GFC_ISYM_SIZE:
4513 gfc_conv_intrinsic_size (se, expr);
4514 break;
4516 case GFC_ISYM_SIZEOF:
4517 gfc_conv_intrinsic_sizeof (se, expr);
4518 break;
4520 case GFC_ISYM_SPACING:
4521 gfc_conv_intrinsic_spacing (se, expr);
4522 break;
4524 case GFC_ISYM_SUM:
4525 gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR);
4526 break;
4528 case GFC_ISYM_TRANSFER:
4529 if (se->ss)
4531 if (se->ss->useflags)
4533 /* Access the previously obtained result. */
4534 gfc_conv_tmp_array_ref (se);
4535 gfc_advance_se_ss_chain (se);
4536 break;
4538 else
4539 gfc_conv_intrinsic_array_transfer (se, expr);
4541 else
4542 gfc_conv_intrinsic_transfer (se, expr);
4543 break;
4545 case GFC_ISYM_TTYNAM:
4546 gfc_conv_intrinsic_ttynam (se, expr);
4547 break;
4549 case GFC_ISYM_UBOUND:
4550 gfc_conv_intrinsic_bound (se, expr, 1);
4551 break;
4553 case GFC_ISYM_XOR:
4554 gfc_conv_intrinsic_bitop (se, expr, BIT_XOR_EXPR);
4555 break;
4557 case GFC_ISYM_LOC:
4558 gfc_conv_intrinsic_loc (se, expr);
4559 break;
4561 case GFC_ISYM_ACCESS:
4562 case GFC_ISYM_CHDIR:
4563 case GFC_ISYM_CHMOD:
4564 case GFC_ISYM_DTIME:
4565 case GFC_ISYM_ETIME:
4566 case GFC_ISYM_FGET:
4567 case GFC_ISYM_FGETC:
4568 case GFC_ISYM_FNUM:
4569 case GFC_ISYM_FPUT:
4570 case GFC_ISYM_FPUTC:
4571 case GFC_ISYM_FSTAT:
4572 case GFC_ISYM_FTELL:
4573 case GFC_ISYM_GETCWD:
4574 case GFC_ISYM_GETGID:
4575 case GFC_ISYM_GETPID:
4576 case GFC_ISYM_GETUID:
4577 case GFC_ISYM_HOSTNM:
4578 case GFC_ISYM_KILL:
4579 case GFC_ISYM_IERRNO:
4580 case GFC_ISYM_IRAND:
4581 case GFC_ISYM_ISATTY:
4582 case GFC_ISYM_LINK:
4583 case GFC_ISYM_LSTAT:
4584 case GFC_ISYM_MALLOC:
4585 case GFC_ISYM_MATMUL:
4586 case GFC_ISYM_MCLOCK:
4587 case GFC_ISYM_MCLOCK8:
4588 case GFC_ISYM_RAND:
4589 case GFC_ISYM_RENAME:
4590 case GFC_ISYM_SECOND:
4591 case GFC_ISYM_SECNDS:
4592 case GFC_ISYM_SIGNAL:
4593 case GFC_ISYM_STAT:
4594 case GFC_ISYM_SYMLNK:
4595 case GFC_ISYM_SYSTEM:
4596 case GFC_ISYM_TIME:
4597 case GFC_ISYM_TIME8:
4598 case GFC_ISYM_UMASK:
4599 case GFC_ISYM_UNLINK:
4600 gfc_conv_intrinsic_funcall (se, expr);
4601 break;
4603 default:
4604 gfc_conv_intrinsic_lib_function (se, expr);
4605 break;
4610 /* This generates code to execute before entering the scalarization loop.
4611 Currently does nothing. */
4613 void
4614 gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss)
4616 switch (ss->expr->value.function.isym->id)
4618 case GFC_ISYM_UBOUND:
4619 case GFC_ISYM_LBOUND:
4620 break;
4622 default:
4623 gcc_unreachable ();
4628 /* UBOUND and LBOUND intrinsics with one parameter are expanded into code
4629 inside the scalarization loop. */
4631 static gfc_ss *
4632 gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
4634 gfc_ss *newss;
4636 /* The two argument version returns a scalar. */
4637 if (expr->value.function.actual->next->expr)
4638 return ss;
4640 newss = gfc_get_ss ();
4641 newss->type = GFC_SS_INTRINSIC;
4642 newss->expr = expr;
4643 newss->next = ss;
4644 newss->data.info.dimen = 1;
4646 return newss;
4650 /* Walk an intrinsic array libcall. */
4652 static gfc_ss *
4653 gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
4655 gfc_ss *newss;
4657 gcc_assert (expr->rank > 0);
4659 newss = gfc_get_ss ();
4660 newss->type = GFC_SS_FUNCTION;
4661 newss->expr = expr;
4662 newss->next = ss;
4663 newss->data.info.dimen = expr->rank;
4665 return newss;
4669 /* Returns nonzero if the specified intrinsic function call maps directly to a
4670 an external library call. Should only be used for functions that return
4671 arrays. */
4674 gfc_is_intrinsic_libcall (gfc_expr * expr)
4676 gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
4677 gcc_assert (expr->rank > 0);
4679 switch (expr->value.function.isym->id)
4681 case GFC_ISYM_ALL:
4682 case GFC_ISYM_ANY:
4683 case GFC_ISYM_COUNT:
4684 case GFC_ISYM_MATMUL:
4685 case GFC_ISYM_MAXLOC:
4686 case GFC_ISYM_MAXVAL:
4687 case GFC_ISYM_MINLOC:
4688 case GFC_ISYM_MINVAL:
4689 case GFC_ISYM_PRODUCT:
4690 case GFC_ISYM_SUM:
4691 case GFC_ISYM_SHAPE:
4692 case GFC_ISYM_SPREAD:
4693 case GFC_ISYM_TRANSPOSE:
4694 /* Ignore absent optional parameters. */
4695 return 1;
4697 case GFC_ISYM_RESHAPE:
4698 case GFC_ISYM_CSHIFT:
4699 case GFC_ISYM_EOSHIFT:
4700 case GFC_ISYM_PACK:
4701 case GFC_ISYM_UNPACK:
4702 /* Pass absent optional parameters. */
4703 return 2;
4705 default:
4706 return 0;
4710 /* Walk an intrinsic function. */
4711 gfc_ss *
4712 gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
4713 gfc_intrinsic_sym * isym)
4715 gcc_assert (isym);
4717 if (isym->elemental)
4718 return gfc_walk_elemental_function_args (ss, expr->value.function.actual, GFC_SS_SCALAR);
4720 if (expr->rank == 0)
4721 return ss;
4723 if (gfc_is_intrinsic_libcall (expr))
4724 return gfc_walk_intrinsic_libfunc (ss, expr);
4726 /* Special cases. */
4727 switch (isym->id)
4729 case GFC_ISYM_LBOUND:
4730 case GFC_ISYM_UBOUND:
4731 return gfc_walk_intrinsic_bound (ss, expr);
4733 case GFC_ISYM_TRANSFER:
4734 return gfc_walk_intrinsic_libfunc (ss, expr);
4736 default:
4737 /* This probably meant someone forgot to add an intrinsic to the above
4738 list(s) when they implemented it, or something's gone horribly
4739 wrong. */
4740 gcc_unreachable ();
4744 #include "gt-fortran-trans-intrinsic.h"